From d0f16784a05bf029f036fd488044c0b6ddd6f489 Mon Sep 17 00:00:00 2001 From: "zhuangbowei.zbw" Date: Thu, 14 Aug 2025 16:05:16 +0800 Subject: [PATCH 1/5] pkg/snapshot: skip erofs fs meta when rootfs is writable Signed-off-by: zhuangbowei.zbw --- pkg/snapshot/overlay.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/snapshot/overlay.go b/pkg/snapshot/overlay.go index c74e42cd..6fe307fa 100644 --- a/pkg/snapshot/overlay.go +++ b/pkg/snapshot/overlay.go @@ -1544,6 +1544,10 @@ func (o *snapshotter) turboOCIFsMeta(id string) (string, string) { log.L.Warn("erofs is not supported on this system, fallback to other fs type") continue } + if fsType == "erofs" && o.rwMode != RoDir { + log.L.Warn("erofs is read-only, it cannot be used as a writable rootfs, fallback to other fs type") + continue + } return fsmeta, fsType } else if !errors.Is(err, os.ErrNotExist) { log.L.Errorf("error while checking fs meta file: %s", err) From 1b23c36b38240f466b8beb1e5aefe5612a9b8ba5 Mon Sep 17 00:00:00 2001 From: "zhuangbowei.zbw" Date: Mon, 7 Sep 2026 12:31:17 +0800 Subject: [PATCH 2/5] pkg/snapshot: fix device probe Signed-off-by: zhuangbowei.zbw --- pkg/snapshot/storage.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/pkg/snapshot/storage.go b/pkg/snapshot/storage.go index e93ef1a6..1cc7c818 100644 --- a/pkg/snapshot/storage.go +++ b/pkg/snapshot/storage.go @@ -463,12 +463,25 @@ func AttachDevice(ctx context.Context, params *AttachDeviceParams) (devName stri time.Sleep(10 * time.Millisecond) break // retry } - devName = device - break + goto waitDevReady + } + } + return "", fmt.Errorf("timeout to find device for snID: %s, lastErr: %w", snID, e) + +waitDevReady: + // Wait for /dev/sdX block device node to be fully ready. + // After sysfs timeout is set, udev may still be creating the device node. + for _, wait := range []time.Duration{5, 10, 20, 50, 100, 100, 100, 100, 100, 100} { + f, err := os.Open(devName) + if err == nil { + f.Close() + log.G(ctx).Infof("Device has been created. {id: %s: dev: %s}", snID, devName) + return devName, nil } + e = fmt.Errorf("block device %s not ready yet: %w", devName, err) + time.Sleep(wait * time.Millisecond) } - log.G(ctx).Infof("Device has been created. {id: %s: dev: %s}", snID, devName) - return devName, nil + return "", fmt.Errorf("block device %s not ready after retries", devName) } // attachAndMountBlockDevice From 21ce731ab918dbeb83933cc4e39454cd89e69f8d Mon Sep 17 00:00:00 2001 From: "zhuangbowei.zbw" Date: Wed, 7 Jan 2026 18:46:44 +0800 Subject: [PATCH 3/5] pkg/snapshot: extend device waiting timeout to 5s Signed-off-by: zhuangbowei.zbw --- pkg/snapshot/storage.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/snapshot/storage.go b/pkg/snapshot/storage.go index 1cc7c818..5fb35bc0 100644 --- a/pkg/snapshot/storage.go +++ b/pkg/snapshot/storage.go @@ -51,7 +51,9 @@ import ( ) const ( - maxAttachAttempts = 50 + // maxAttachAttempts is the number of 10ms-spaced polls waiting for a + // device node or a target to show up, i.e. a 5s timeout. + maxAttachAttempts = 500 // hba number used to create tcmu devices in configfs // all overlaybd devices are configured in /sys/kernel/config/target/core/user_999999999/ From 6ad24ba88cb0f41e2dce15603cd4534019ae9816 Mon Sep 17 00:00:00 2001 From: "zhuangbowei.zbw" Date: Thu, 14 May 2026 16:15:52 +0800 Subject: [PATCH 4/5] pkg/snapshot: drop per-call log of Stat and Usage Signed-off-by: zhuangbowei.zbw --- pkg/snapshot/overlay.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/snapshot/overlay.go b/pkg/snapshot/overlay.go index 6fe307fa..6188b794 100644 --- a/pkg/snapshot/overlay.go +++ b/pkg/snapshot/overlay.go @@ -280,7 +280,6 @@ func NewSnapshotter(bootConfig *BootConfig, opts ...Opt) (snapshots.Snapshotter, // Stat returns the info for an active or committed snapshot by the key. func (o *snapshotter) Stat(ctx context.Context, key string) (_ snapshots.Info, retErr error) { - log.G(ctx).Infof("Stat (key: %s)", key) start := time.Now() defer func() { if retErr != nil { @@ -335,7 +334,6 @@ func (o *snapshotter) Update(ctx context.Context, info snapshots.Info, fieldpath // Usage returns the resources taken by the snapshot identified by key. func (o *snapshotter) Usage(ctx context.Context, key string) (_ snapshots.Usage, retErr error) { - log.G(ctx).Infof("Usage (key: %s)", key) start := time.Now() defer func() { if retErr != nil { From 0f498a5a3e72c436e9e360cd43e961833ec31c64 Mon Sep 17 00:00:00 2001 From: "zhuangbowei.zbw" Date: Fri, 15 May 2026 17:25:26 +0800 Subject: [PATCH 5/5] pkg/snapshot: keep unlabeled initial layer read-only Signed-off-by: zhuangbowei.zbw --- pkg/snapshot/overlay.go | 43 +++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/pkg/snapshot/overlay.go b/pkg/snapshot/overlay.go index 6188b794..1b224dd2 100644 --- a/pkg/snapshot/overlay.go +++ b/pkg/snapshot/overlay.go @@ -373,31 +373,40 @@ func (o *snapshotter) getWritableType(ctx context.Context, id string, info snaps defer func() { log.G(ctx).Infof("snapshot R/W label: %s", mode) }() - // check image type (OCIv1 or overlaybd) - if id != "" { - if _, err := o.loadBackingStoreConfig(id); err != nil { - log.G(ctx).Debugf("[%s] is not an overlaybd image.", id) + + parseMode := func(m string) string { + switch m { + case "dir": + return RwDir + case "dev": + return RwDev + default: return RoDir } - } else { - log.G(ctx).Debugf("empty snID get. It should be an initial layer.") } - // overlaybd - rwMode := func(m string) string { - if m == "dir" { - return RwDir - } - if m == "dev" { - return RwDev + + // check image type (OCIv1 or overlaybd) + if id == "" { + log.G(ctx).Debugf("empty snID get. It should be an initial layer.") + // An initial layer without an explicit R/W label is prepared for + // pulling an image rather than for a container rootfs, keep it + // read-only instead of falling back to the global rwMode. + if m, ok := info.Labels[label.SupportReadWriteMode]; ok { + return parseMode(m) } return RoDir } - m, ok := info.Labels[label.SupportReadWriteMode] - if !ok { - return rwMode(o.rwMode) + + if _, err := o.loadBackingStoreConfig(id); err != nil { + log.G(ctx).Debugf("[%s] is not an overlaybd image.", id) + return RoDir } - return rwMode(m) + // overlaybd + if m, ok := info.Labels[label.SupportReadWriteMode]; ok { + return parseMode(m) + } + return parseMode(o.rwMode) } func (o *snapshotter) checkTurboOCI(labels map[string]string) (bool, string, string) {