瀏覽代碼

Unmount RWLayer during Commit

Needed for Diff on Windows. Don't remount it afterwards as the layer is
going to be released anyway.

Signed-off-by: Paul "TBBle" Hampson <Paul.Hampson@Pobox.com>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Paul "TBBle" Hampson 1 年之前
父節點
當前提交
0dc07ccc3a
共有 2 個文件被更改,包括 19 次插入6 次删除
  1. 16 0
      daemon/containerd/image_builder.go
  2. 3 6
      daemon/containerd/image_commit.go

+ 16 - 0
daemon/containerd/image_builder.go

@@ -350,6 +350,22 @@ func (rw *rwlayer) Commit() (_ builder.ROLayer, outErr error) {
 		}
 		}
 	}()
 	}()
 
 
+	// Unmount the layer, required by the containerd windows snapshotter.
+	// The windowsfilter graphdriver does this inside its own Diff method.
+	//
+	// The only place that calls this in-tree is (b *Builder) exportImage and
+	// that is called from the end of (b *Builder) performCopy which has a
+	// `defer rwLayer.Release()` pending.
+	//
+	// After the snapshotter.Commit the source snapshot is deleted anyway and
+	// it shouldn't be accessed afterwards.
+	if rw.root != "" {
+		if err := mount.UnmountAll(rw.root, 0); err != nil && !errors.Is(err, os.ErrNotExist) {
+			log.G(ctx).WithError(err).WithField("root", rw.root).Error("failed to unmount RWLayer")
+			return nil, err
+		}
+	}
+
 	err = snapshotter.Commit(ctx, key, rw.key)
 	err = snapshotter.Commit(ctx, key, rw.key)
 	if err != nil && !cerrdefs.IsAlreadyExists(err) {
 	if err != nil && !cerrdefs.IsAlreadyExists(err) {
 		return nil, err
 		return nil, err

+ 3 - 6
daemon/containerd/image_commit.go

@@ -264,18 +264,15 @@ func (i *ImageService) createDiff(ctx context.Context, name string, sn snapshots
 
 
 // applyDiffLayer will apply diff layer content created by createDiff into the snapshotter.
 // applyDiffLayer will apply diff layer content created by createDiff into the snapshotter.
 func (i *ImageService) applyDiffLayer(ctx context.Context, name string, containerID string, sn snapshots.Snapshotter, differ diff.Applier, diffDesc ocispec.Descriptor) (retErr error) {
 func (i *ImageService) applyDiffLayer(ctx context.Context, name string, containerID string, sn snapshots.Snapshotter, differ diff.Applier, diffDesc ocispec.Descriptor) (retErr error) {
-	var (
-		key    = uniquePart() + "-" + name
-		mounts []mount.Mount
-		err    error
-	)
+	// Let containerd know that this snapshot is only for diff-applying.
+	key := snapshots.UnpackKeyPrefix + "-" + uniquePart() + "-" + name
 
 
 	info, err := sn.Stat(ctx, containerID)
 	info, err := sn.Stat(ctx, containerID)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	mounts, err = sn.Prepare(ctx, key, info.Parent)
+	mounts, err := sn.Prepare(ctx, key, info.Parent)
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("failed to prepare snapshot: %w", err)
 		return fmt.Errorf("failed to prepare snapshot: %w", err)
 	}
 	}