Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 30 additions & 19 deletions pkg/snapshot/overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -375,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) {
Expand Down Expand Up @@ -1544,6 +1551,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)
Expand Down
25 changes: 20 additions & 5 deletions pkg/snapshot/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down Expand Up @@ -463,12 +465,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
Expand Down
Loading