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>
This commit is contained in:
Paul "TBBle" Hampson 2023-09-24 17:23:49 +09:00 committed by Paweł Gronowski
parent a1f6b64e24
commit 0dc07ccc3a
No known key found for this signature in database
GPG key ID: B85EFCFE26DEF92A
2 changed files with 19 additions and 6 deletions

View file

@ -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)
if err != nil && !cerrdefs.IsAlreadyExists(err) {
return nil, err

View file

@ -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.
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)
if err != nil {
return err
}
mounts, err = sn.Prepare(ctx, key, info.Parent)
mounts, err := sn.Prepare(ctx, key, info.Parent)
if err != nil {
return fmt.Errorf("failed to prepare snapshot: %w", err)
}