Skip to content

Commit 43c3295

Browse files
authored
Merge pull request #350 from Aaron-ding-coder/z.d/dev
Fix: prevent snapshotter from deleting in-use devices during snapshot removal
2 parents 3371adc + 89c0790 commit 43c3295

4 files changed

Lines changed: 41 additions & 7 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ bin/
22
.vscode
33
vendor/
44
tmp_conv/
5-
tmp/
5+
tmp/
6+
.idea

pkg/snapshot/docker.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ func (o *snapshotter) RemoveDockerLayer(ctx context.Context, key string, initID
236236
if parentStype == storageTypeLocalBlock || parentStype == storageTypeRemoteBlock {
237237
if _, err := os.Stat(o.overlaybdBackstoreMarkFile(parentID)); err == nil {
238238
log.G(ctx).Infof("RemoveDockerLayer: destroying overlaybd device for parent %s", parentID)
239-
if err = o.UnmountAndDetachBlockDevice(ctx, parentID); err != nil {
239+
if err = o.UnmountAndDetachBlockDevice(ctx, parentID, parentInfo.Name, key); err != nil {
240240
log.G(ctx).Warnf("failed to destroy overlaybd device for parent %s: %v", parentID, err)
241241
// Don't block remove, device might still be in use by other containers
242242
}

pkg/snapshot/overlay.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ func (o *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
853853
} else if _, err := o.loadBackingStoreConfig(id); err != nil {
854854
log.G(ctx).Info("not an overlaybd writable layer")
855855
} else {
856-
if err := o.UnmountAndDetachBlockDevice(ctx, id); err != nil {
856+
if err := o.UnmountAndDetachBlockDevice(ctx, id, key, ""); err != nil {
857857
return fmt.Errorf("failed to destroy target device for snapshot %s: %w", key, err)
858858
}
859859

@@ -1047,7 +1047,7 @@ func (o *snapshotter) Remove(ctx context.Context, key string) (err error) {
10471047
if stype != storageTypeNormal {
10481048
_, err = os.Stat(o.overlaybdBackstoreMarkFile(id))
10491049
if err == nil {
1050-
err = o.UnmountAndDetachBlockDevice(ctx, id)
1050+
err = o.UnmountAndDetachBlockDevice(ctx, id, key, "")
10511051
if err != nil {
10521052
return mylog.TracedErrorf(ctx, "failed to destroy target device for snapshot %s: %w", key, err)
10531053
}
@@ -1071,7 +1071,12 @@ func (o *snapshotter) Remove(ctx context.Context, key string) (err error) {
10711071

10721072
log.G(ctx).Debugf("try to verify parent snapshots format.")
10731073
if st, err := o.identifySnapshotStorageType(ctx, s.ParentIDs[0], info); err == nil && st != storageTypeNormal {
1074-
err = o.UnmountAndDetachBlockDevice(ctx, s.ParentIDs[0])
1074+
// Get parent snapshot info for key and parent
1075+
_, parentInfo, _, err := storage.GetInfo(ctx, info.Parent)
1076+
if err != nil {
1077+
return mylog.TracedErrorf(ctx, "failed to get parent snapshot info for %s: %w", s.ParentIDs[0], err)
1078+
}
1079+
err = o.UnmountAndDetachBlockDevice(ctx, s.ParentIDs[0], parentInfo.Name, key)
10751080
if err != nil {
10761081
return mylog.TracedErrorf(ctx, "failed to destroy target device for snapshot %s: %w", key, err)
10771082
}

pkg/snapshot/storage.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,13 @@ func DetachDevice(ctx context.Context, snID string, tenant int) (err error) {
231231
}
232232

233233
// UnmountAndDetachBlockDevice will do nothing if the device is already destroyed
234-
func (o *snapshotter) UnmountAndDetachBlockDevice(ctx context.Context, snID string) (err error) {
234+
func (o *snapshotter) UnmountAndDetachBlockDevice(ctx context.Context, snID string, key string, upperDirKey string) (err error) {
235235
devName, err := os.ReadFile(o.overlaybdBackstoreMarkFile(snID))
236236
if err != nil {
237237
log.G(ctx).Errorf("read device name failed: %s, err: %v", o.overlaybdBackstoreMarkFile(snID), err)
238238
}
239239

240240
mountPoint := o.overlaybdMountpoint(snID)
241-
log.G(ctx).Debugf("check overlaybd mountpoint is in use: %s", mountPoint)
242241
busy, err := o.checkOverlaybdInUse(ctx, mountPoint)
243242
if err != nil {
244243
return err
@@ -247,6 +246,18 @@ func (o *snapshotter) UnmountAndDetachBlockDevice(ctx context.Context, snID stri
247246
log.G(ctx).Infof("device still in use.")
248247
return nil
249248
}
249+
250+
if upperDirKey != "" {
251+
inuse, err := checkIsParent(ctx, key, upperDirKey)
252+
if err != nil {
253+
return fmt.Errorf("failed to check whether snID %v check key %v err: %v", snID, key, err)
254+
}
255+
if inuse {
256+
log.G(ctx).Infof("device is parent to someone else, ignore umount")
257+
return nil
258+
}
259+
}
260+
250261
log.G(ctx).Infof("umount device, mountpoint: %s", mountPoint)
251262
if err := mount.UnmountAll(mountPoint, 0); err != nil {
252263
return fmt.Errorf("failed to umount %s: %w", mountPoint, err)
@@ -257,7 +268,24 @@ func (o *snapshotter) UnmountAndDetachBlockDevice(ctx context.Context, snID stri
257268
}
258269
log.G(ctx).Infof("destroy overlaybd device success(sn: %s): %s", snID, devName)
259270
return nil
271+
}
260272

273+
// checkIsParent checks if the given parent is a parent of any other active snapshot
274+
func checkIsParent(ctx context.Context, key, exclude string) (bool, error) {
275+
found := false
276+
if err := storage.WalkInfo(ctx, func(ctx context.Context, info snapshots.Info) error {
277+
if found {
278+
return nil
279+
}
280+
281+
if info.Name != exclude && info.Parent == key && (info.Kind == snapshots.KindActive || info.Kind == snapshots.KindView) {
282+
found = true
283+
}
284+
return nil
285+
}); err != nil {
286+
return false, err
287+
}
288+
return found, nil
261289
}
262290

263291
// IsErofsFilesystem determines whether the block device represented

0 commit comments

Comments
 (0)