From e5399aaf3c10b03124e4b6855bb3dd5b9a1135cc Mon Sep 17 00:00:00 2001 From: Aditya R Date: Fri, 16 Jun 2023 14:27:08 +0530 Subject: [PATCH] vendor: bump c/storage to v1.46.2-0.20230616083707-cc0d208e5e1c Signed-off-by: Aditya R --- go.mod | 2 +- go.sum | 4 +- .../github.com/containers/storage/.cirrus.yml | 4 +- vendor/github.com/containers/storage/check.go | 143 +++++++++++++----- .../storage/drivers/overlay/overlay.go | 2 +- .../github.com/containers/storage/layers.go | 7 - vendor/github.com/containers/storage/store.go | 73 +++++++-- .../containers/storage/types/options.go | 1 + vendor/modules.txt | 2 +- 9 files changed, 176 insertions(+), 62 deletions(-) diff --git a/go.mod b/go.mod index e5e58071fb..238753a4da 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/containers/libhvee v0.0.5 github.com/containers/ocicrypt v1.1.7 github.com/containers/psgo v1.8.0 - github.com/containers/storage v1.46.2-0.20230613134951-e424b6649be3 + github.com/containers/storage v1.46.2-0.20230616083707-cc0d208e5e1c github.com/coreos/go-systemd/v22 v22.5.0 github.com/coreos/stream-metadata-go v0.4.2 github.com/crc-org/vfkit v0.0.5-0.20230602131541-3d57f09010c9 diff --git a/go.sum b/go.sum index d0f406910e..33eb75f192 100644 --- a/go.sum +++ b/go.sum @@ -257,8 +257,8 @@ github.com/containers/ocicrypt v1.1.7/go.mod h1:7CAhjcj2H8AYp5YvEie7oVSK2AhBY8Ns github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY= github.com/containers/psgo v1.8.0/go.mod h1:T8ZxnX3Ur4RvnhxFJ7t8xJ1F48RhiZB4rSrOaR/qGHc= github.com/containers/storage v1.43.0/go.mod h1:uZ147thiIFGdVTjMmIw19knttQnUCl3y9zjreHrg11s= -github.com/containers/storage v1.46.2-0.20230613134951-e424b6649be3 h1:nSCnnrCMocJDsNUU4EDPT8GkW7ToU43/QbXGRC+ciEs= -github.com/containers/storage v1.46.2-0.20230613134951-e424b6649be3/go.mod h1:pRp3lkRo2qodb/ltpnudoXggrviRmaCmU5a5GhTBae0= +github.com/containers/storage v1.46.2-0.20230616083707-cc0d208e5e1c h1:hJP+UF9OzDaThxavD5isFbAFxbvb25TdFtjohAhH/dc= +github.com/containers/storage v1.46.2-0.20230616083707-cc0d208e5e1c/go.mod h1:pRp3lkRo2qodb/ltpnudoXggrviRmaCmU5a5GhTBae0= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= diff --git a/vendor/github.com/containers/storage/.cirrus.yml b/vendor/github.com/containers/storage/.cirrus.yml index 5567bfbc9c..8ef38e2cd2 100644 --- a/vendor/github.com/containers/storage/.cirrus.yml +++ b/vendor/github.com/containers/storage/.cirrus.yml @@ -18,12 +18,12 @@ env: #### Cache-image names to test with (double-quotes around names are critical) ### FEDORA_NAME: "fedora-38" - DEBIAN_NAME: "debian-12" + DEBIAN_NAME: "debian-13" # GCE project where images live IMAGE_PROJECT: "libpod-218412" # VM Image built in containers/automation_images - IMAGE_SUFFIX: "c20230601t145439z-f38f37d12" + IMAGE_SUFFIX: "c20230614t132754z-f38f37d13" FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}" DEBIAN_CACHE_IMAGE_NAME: "debian-${IMAGE_SUFFIX}" diff --git a/vendor/github.com/containers/storage/check.go b/vendor/github.com/containers/storage/check.go index 81b5c3ab81..e58084fc7c 100644 --- a/vendor/github.com/containers/storage/check.go +++ b/vendor/github.com/containers/storage/check.go @@ -15,6 +15,7 @@ import ( drivers "github.com/containers/storage/drivers" "github.com/containers/storage/pkg/archive" + "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/ioutils" "github.com/containers/storage/types" "github.com/sirupsen/logrus" @@ -74,6 +75,13 @@ type CheckOptions struct { ContainerData bool // check that associated "big" data items are present and can be read } +// checkIgnore is used to tell functions that compare the contents of a mounted +// layer to the contents that we'd expect it to have to ignore certain +// discrepancies +type checkIgnore struct { + ownership, timestamps, permissions bool +} + // CheckMost returns a CheckOptions with mostly just "quick" checks enabled. func CheckMost() *CheckOptions { return &CheckOptions{ @@ -125,10 +133,20 @@ func RepairEverything() *RepairOptions { // Check returns a list of problems with what's in the store, as a whole. It can be very expensive // to call. func (s *store) Check(options *CheckOptions) (CheckReport, error) { - var ignoreChownErrors bool + var ignore checkIgnore for _, o := range s.graphOptions { - if strings.Contains(o, "ignore_chown_errors") { - ignoreChownErrors = true + if strings.Contains(o, "ignore_chown_errors=true") { + ignore.ownership = true + } + if strings.HasPrefix(o, "force_mask=") { + ignore.permissions = true + } + } + for o := range s.pullOptions { + if strings.Contains(o, "use_hard_links") { + if s.pullOptions[o] == "true" { + ignore.timestamps = true + } } } @@ -160,7 +178,7 @@ func (s *store) Check(options *CheckOptions) (CheckReport, error) { // Walk the list of layer stores, looking at each layer that we didn't see in a // previously-visited store. - if _, _, err := readAllLayerStores(s, func(store roLayerStore) (struct{}, bool, error) { + if _, _, err := readOrWriteAllLayerStores(s, func(store roLayerStore) (struct{}, bool, error) { layers, err := store.Layers() if err != nil { return struct{}{}, true, err @@ -315,7 +333,6 @@ func (s *store) Check(options *CheckOptions) (CheckReport, error) { } else { report.ROLayers[id] = append(report.ROLayers[id], err) } - return } if layer.UncompressedSize != -1 && counter.Count != layer.UncompressedSize { // We expected the diff to have a specific size, and @@ -329,7 +346,6 @@ func (s *store) Check(options *CheckOptions) (CheckReport, error) { } else { report.ROLayers[id] = append(report.ROLayers[id], err) } - return } }() } @@ -398,6 +414,11 @@ func (s *store) Check(options *CheckOptions) (CheckReport, error) { expectedCheckDirectory.headers(diffHeaders) } // Scan the directory tree under the mount point. + var idmap *idtools.IDMappings + if !s.canUseShifting(layer.UIDMap, layer.GIDMap) { + // we would have had to chown() layer contents to match ID maps + idmap = idtools.NewIDMappingsFromMaps(layer.UIDMap, layer.GIDMap) + } actualCheckDirectory, err := newCheckDirectoryFromDirectory(mountPoint) if err != nil { err := fmt.Errorf("scanning contents of %slayer %s: %w", readWriteDesc, id, err) @@ -409,7 +430,7 @@ func (s *store) Check(options *CheckOptions) (CheckReport, error) { return } // Every departure from our expectations is an error. - diffs := compareCheckDirectory(expectedCheckDirectory, actualCheckDirectory, ignoreChownErrors) + diffs := compareCheckDirectory(expectedCheckDirectory, actualCheckDirectory, idmap, ignore) for _, diff := range diffs { err := fmt.Errorf("%slayer %s: %s, %w", readWriteDesc, id, diff, ErrLayerContentModified) if isReadWrite { @@ -805,27 +826,33 @@ func (s *store) Repair(report CheckReport, options *RepairOptions) []error { } // compareFileInfo returns a string summarizing what's different between the two checkFileInfos -func compareFileInfo(a, b checkFileInfo, ignoreChownErrors bool) string { - if a.typeflag == b.typeflag && a.uid != b.uid && a.gid != b.gid && a.size != b.size && - (os.ModeType|os.ModePerm)&a.mode != (os.ModeType|os.ModePerm)&b.mode { - return "" - } +func compareFileInfo(a, b checkFileInfo, idmap *idtools.IDMappings, ignore checkIgnore) string { var comparison []string if a.typeflag != b.typeflag { comparison = append(comparison, fmt.Sprintf("filetype:%v→%v", a.typeflag, b.typeflag)) } - if a.uid != b.uid && ignoreChownErrors { + if idmap != nil && !idmap.Empty() { + mappedUID, mappedGID, err := idmap.ToContainer(idtools.IDPair{UID: b.uid, GID: b.gid}) + if err != nil { + return err.Error() + } + b.uid, b.gid = mappedUID, mappedGID + } + if a.uid != b.uid && !ignore.ownership { comparison = append(comparison, fmt.Sprintf("uid:%d→%d", a.uid, b.uid)) } - if a.gid != b.gid && ignoreChownErrors { + if a.gid != b.gid && !ignore.ownership { comparison = append(comparison, fmt.Sprintf("gid:%d→%d", a.gid, b.gid)) } if a.size != b.size { comparison = append(comparison, fmt.Sprintf("size:%d→%d", a.size, b.size)) } - if (os.ModeType|os.ModePerm)&a.mode != (os.ModeType|os.ModePerm)&b.mode { + if (os.ModeType|os.ModePerm)&a.mode != (os.ModeType|os.ModePerm)&b.mode && !ignore.permissions { comparison = append(comparison, fmt.Sprintf("mode:%04o→%04o", a.mode, b.mode)) } + if a.mtime != b.mtime && !ignore.timestamps { + comparison = append(comparison, fmt.Sprintf("mtime:0x%x→0x%x", a.mtime, b.mtime)) + } return strings.Join(comparison, ",") } @@ -835,6 +862,7 @@ type checkFileInfo struct { uid, gid int size int64 mode os.FileMode + mtime int64 // unix-style whole seconds } // checkDirectory is a node in a filesystem record, possibly the top @@ -845,7 +873,7 @@ type checkDirectory struct { } // newCheckDirectory creates an empty checkDirectory -func newCheckDirectory(uid, gid int, size int64, mode os.FileMode) *checkDirectory { +func newCheckDirectory(uid, gid int, size int64, mode os.FileMode, mtime int64) *checkDirectory { return &checkDirectory{ directory: make(map[string]*checkDirectory), file: make(map[string]checkFileInfo), @@ -855,6 +883,7 @@ func newCheckDirectory(uid, gid int, size int64, mode os.FileMode) *checkDirecto gid: gid, size: size, mode: mode, + mtime: mtime, }, } } @@ -862,7 +891,7 @@ func newCheckDirectory(uid, gid int, size int64, mode os.FileMode) *checkDirecto // newCheckDirectoryDefaults creates an empty checkDirectory with hardwired defaults for the UID // (0), GID (0), size (0) and permissions (0o555) func newCheckDirectoryDefaults() *checkDirectory { - return newCheckDirectory(0, 0, 0, 0o555) + return newCheckDirectory(0, 0, 0, 0o555, time.Now().Unix()) } // newCheckDirectoryFromDirectory creates a checkDirectory for an on-disk directory tree @@ -880,9 +909,6 @@ func newCheckDirectoryFromDirectory(dir string) (*checkDirectory, error) { if err != nil { return err } - if hdr.Typeflag == tar.TypeLink || hdr.Typeflag == tar.TypeRegA { - hdr.Typeflag = tar.TypeReg - } hdr.Name = filepath.ToSlash(rel) cd.header(hdr) return nil @@ -894,16 +920,23 @@ func newCheckDirectoryFromDirectory(dir string) (*checkDirectory, error) { } // add adds an item to a checkDirectory -func (c *checkDirectory) add(path string, typeflag byte, uid, gid int, size int64, mode os.FileMode) { +func (c *checkDirectory) add(path string, typeflag byte, uid, gid int, size int64, mode os.FileMode, mtime int64) { components := strings.Split(path, "/") if components[len(components)-1] == "" { components = components[:len(components)-1] } - if typeflag == tar.TypeLink || typeflag == tar.TypeRegA { - typeflag = tar.TypeReg + if components[0] == "." { + components = components[1:] + } + if typeflag != tar.TypeReg { + size = 0 } switch len(components) { case 0: + c.uid = uid + c.gid = gid + c.mode = mode + c.mtime = mtime return case 1: switch typeflag { @@ -911,7 +944,7 @@ func (c *checkDirectory) add(path string, typeflag byte, uid, gid int, size int6 delete(c.file, components[0]) // directory entries are mergers, not replacements if _, present := c.directory[components[0]]; !present { - c.directory[components[0]] = newCheckDirectory(uid, gid, size, mode) + c.directory[components[0]] = newCheckDirectory(uid, gid, size, mode, mtime) } else { c.directory[components[0]].checkFileInfo = checkFileInfo{ typeflag: tar.TypeDir, @@ -919,6 +952,7 @@ func (c *checkDirectory) add(path string, typeflag byte, uid, gid int, size int6 gid: gid, size: size, mode: mode, + mtime: mtime, } } default: @@ -930,6 +964,7 @@ func (c *checkDirectory) add(path string, typeflag byte, uid, gid int, size int6 gid: gid, size: size, mode: mode, + mtime: mtime, } case tar.TypeXGlobalHeader: // ignore, since even though it looks like a valid pathname, it doesn't end @@ -939,10 +974,10 @@ func (c *checkDirectory) add(path string, typeflag byte, uid, gid int, size int6 } subdirectory := c.directory[components[0]] if subdirectory == nil { - subdirectory = newCheckDirectory(uid, gid, size, mode) + subdirectory = newCheckDirectory(uid, gid, size, mode, mtime) c.directory[components[0]] = subdirectory } - subdirectory.add(strings.Join(components[1:], "/"), typeflag, uid, gid, size, mode) + subdirectory.add(strings.Join(components[1:], "/"), typeflag, uid, gid, size, mode, mtime) } // remove removes an item from a checkDirectory @@ -966,12 +1001,37 @@ func (c *checkDirectory) header(hdr *tar.Header) { if strings.HasPrefix(base, archive.WhiteoutPrefix) { if base == archive.WhiteoutOpaqueDir { c.remove(path.Clean(dir)) - c.add(path.Clean(dir), tar.TypeDir, hdr.Uid, hdr.Gid, hdr.Size, os.FileMode(hdr.Mode)) + c.add(path.Clean(dir), tar.TypeDir, hdr.Uid, hdr.Gid, hdr.Size, os.FileMode(hdr.Mode), hdr.ModTime.Unix()) } else { c.remove(path.Join(dir, base[len(archive.WhiteoutPrefix):])) } } else { - c.add(name, hdr.Typeflag, hdr.Uid, hdr.Gid, hdr.Size, os.FileMode(hdr.Mode)) + if hdr.Typeflag == tar.TypeLink { + // look up the attributes of the target of the hard link + // n.b. by convention, Linkname is always relative to the + // root directory of the archive, which is not always the + // same as being relative to hdr.Name + directory := c + for _, component := range strings.Split(path.Clean(hdr.Linkname), "/") { + if component == "." || component == ".." { + continue + } + if subdir, ok := directory.directory[component]; ok { + directory = subdir + continue + } + if file, ok := directory.file[component]; ok { + hdr.Typeflag = file.typeflag + hdr.Uid = file.uid + hdr.Gid = file.gid + hdr.Size = file.size + hdr.Mode = int64(file.mode) + hdr.ModTime = time.Unix(file.mtime, 0) + } + break + } + } + c.add(name, hdr.Typeflag, hdr.Uid, hdr.Gid, hdr.Size, os.FileMode(hdr.Mode), hdr.ModTime.Unix()) } } @@ -981,7 +1041,14 @@ func (c *checkDirectory) headers(hdrs []*tar.Header) { // sort the headers from the diff to ensure that whiteouts appear // before content when they both appear in the same directory, per // https://github.com/opencontainers/image-spec/blob/main/layer.md#whiteouts - sort.Slice(hdrs, func(i, j int) bool { + // and that hard links appear after other types of entries + sort.SliceStable(hdrs, func(i, j int) bool { + if hdrs[i].Typeflag != tar.TypeLink && hdrs[j].Typeflag == tar.TypeLink { + return true + } + if hdrs[i].Typeflag == tar.TypeLink && hdrs[j].Typeflag != tar.TypeLink { + return false + } idir, ifile := path.Split(hdrs[i].Name) jdir, jfile := path.Split(hdrs[j].Name) if idir != jdir { @@ -1016,7 +1083,7 @@ func (c *checkDirectory) names() []string { } // compareCheckSubdirectory walks two subdirectory trees and returns a list of differences -func compareCheckSubdirectory(path string, a, b *checkDirectory, ignoreChownErrors bool) []string { +func compareCheckSubdirectory(path string, a, b *checkDirectory, idmap *idtools.IDMappings, ignore checkIgnore) []string { var diff []string if a == nil { a = newCheckDirectoryDefaults() @@ -1028,20 +1095,20 @@ func compareCheckSubdirectory(path string, a, b *checkDirectory, ignoreChownErro if bdir, present := b.directory[aname]; !present { // directory was removed diff = append(diff, "-"+path+"/"+aname+"/") - diff = append(diff, compareCheckSubdirectory(path+"/"+aname, adir, nil, ignoreChownErrors)...) + diff = append(diff, compareCheckSubdirectory(path+"/"+aname, adir, nil, idmap, ignore)...) } else { // directory is in both trees; descend - if attributes := compareFileInfo(adir.checkFileInfo, bdir.checkFileInfo, ignoreChownErrors); attributes != "" { + if attributes := compareFileInfo(adir.checkFileInfo, bdir.checkFileInfo, idmap, ignore); attributes != "" { diff = append(diff, path+"/"+aname+"("+attributes+")") } - diff = append(diff, compareCheckSubdirectory(path+"/"+aname, adir, bdir, ignoreChownErrors)...) + diff = append(diff, compareCheckSubdirectory(path+"/"+aname, adir, bdir, idmap, ignore)...) } } for bname, bdir := range b.directory { if _, present := a.directory[bname]; !present { // directory added diff = append(diff, "+"+path+"/"+bname+"/") - diff = append(diff, compareCheckSubdirectory(path+"/"+bname, nil, bdir, ignoreChownErrors)...) + diff = append(diff, compareCheckSubdirectory(path+"/"+bname, nil, bdir, idmap, ignore)...) } } for aname, afile := range a.file { @@ -1050,7 +1117,7 @@ func compareCheckSubdirectory(path string, a, b *checkDirectory, ignoreChownErro diff = append(diff, "-"+path+"/"+aname) } else { // item is in both trees; compare - if attributes := compareFileInfo(afile, bfile, ignoreChownErrors); attributes != "" { + if attributes := compareFileInfo(afile, bfile, idmap, ignore); attributes != "" { diff = append(diff, path+"/"+aname+"("+attributes+")") } } @@ -1062,7 +1129,7 @@ func compareCheckSubdirectory(path string, a, b *checkDirectory, ignoreChownErro diff = append(diff, "+"+path+"/"+bname) continue } - if attributes := compareFileInfo(filetype, b.file[bname], ignoreChownErrors); attributes != "" { + if attributes := compareFileInfo(filetype, b.file[bname], idmap, ignore); attributes != "" { // non-directory replaced with non-directory diff = append(diff, "+"+path+"/"+bname+"("+attributes+")") } @@ -1071,8 +1138,8 @@ func compareCheckSubdirectory(path string, a, b *checkDirectory, ignoreChownErro } // compareCheckDirectory walks two directory trees and returns a sorted list of differences -func compareCheckDirectory(a, b *checkDirectory, ignoreChownErrors bool) []string { - diff := compareCheckSubdirectory("", a, b, ignoreChownErrors) +func compareCheckDirectory(a, b *checkDirectory, idmap *idtools.IDMappings, ignore checkIgnore) []string { + diff := compareCheckSubdirectory("", a, b, idmap, ignore) sort.Slice(diff, func(i, j int) bool { if strings.Compare(diff[i][1:], diff[j][1:]) < 0 { return true diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go index 5431da4e4e..6be5f663f4 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go @@ -1029,7 +1029,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disable } if imageStore != "" { if err2 := os.RemoveAll(workDirBase); err2 != nil { - logrus.Errorf("While recovering from a failure creating a layer, error deleting %#v: %v", dir, err2) + logrus.Errorf("While recovering from a failure creating a layer, error deleting %#v: %v", workDirBase, err2) } } } diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go index b0ee67b2e9..0e6cb782b5 100644 --- a/vendor/github.com/containers/storage/layers.go +++ b/vendor/github.com/containers/storage/layers.go @@ -314,9 +314,6 @@ type rwLayerStore interface { // Clean up unreferenced layers GarbageCollect() error - - // supportsShifting() returns true if the driver.Driver.SupportsShifting(). - supportsShifting() bool } type layerStore struct { @@ -2472,10 +2469,6 @@ func (r *layerStore) LayersByUncompressedDigest(d digest.Digest) ([]Layer, error return r.layersByDigestMap(r.byuncompressedsum, d) } -func (r *layerStore) supportsShifting() bool { - return r.driver.SupportsShifting() -} - func closeAll(closes ...func() error) (rErr error) { for _, f := range closes { if err := f(); err != nil { diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go index e754200896..14c1edd7f8 100644 --- a/vendor/github.com/containers/storage/store.go +++ b/vendor/github.com/containers/storage/store.go @@ -1216,6 +1216,54 @@ func writeToLayerStore[T any](s *store, fn func(store rwLayerStore) (T, error)) return fn(store) } +// readOrWriteAllLayerStores processes allLayerStores() in order: +// It locks the writeable store for writing and all others for reading, checks +// for updates, and calls +// +// (data, done, err) := fn(store) +// +// until the callback returns done == true, and returns the data from the callback. +// +// If reading or writing any layer store fails, it immediately returns ({}, true, err). +// +// If all layer stores are processed without setting done == true, it returns ({}, false, nil). +// +// Typical usage: +// +// if res, done, err := s.readOrWriteAllLayerStores(store, func(…) { +// … +// }; done { +// return res, err +// } +func readOrWriteAllLayerStores[T any](s *store, fn func(store roLayerStore) (T, bool, error)) (T, bool, error) { + var zeroRes T // A zero value of T + + rwLayerStore, roLayerStores, err := s.bothLayerStoreKinds() + if err != nil { + return zeroRes, true, err + } + + if err := rwLayerStore.startWriting(); err != nil { + return zeroRes, true, err + } + defer rwLayerStore.stopWriting() + if res, done, err := fn(rwLayerStore); done { + return res, true, err + } + + for _, s := range roLayerStores { + store := s + if err := store.startReading(); err != nil { + return zeroRes, true, err + } + defer store.stopReading() + if res, done, err := fn(store); done { + return res, true, err + } + } + return zeroRes, false, nil +} + // allImageStores returns a list of all image store objects used by the Store. // This is a convenience method for read-only users of the Store. func (s *store) allImageStores() []roImageStore { @@ -1319,10 +1367,13 @@ func (s *store) writeToAllStores(fn func(rlstore rwLayerStore) error) error { return fn(rlstore) } -// canUseShifting returns ??? -// store must be locked for writing. -func canUseShifting(store rwLayerStore, uidmap, gidmap []idtools.IDMap) bool { - if !store.supportsShifting() { +// canUseShifting returns true if we can use mount-time arguments (shifting) to +// avoid having to create a mapped top layer for a base image when we want to +// use it to create a container using ID mappings. +// On entry: +// - rlstore must be locked for writing +func (s *store) canUseShifting(uidmap, gidmap []idtools.IDMap) bool { + if !s.graphDriver.SupportsShifting() { return false } if uidmap != nil && !idtools.IsContiguous(uidmap) { @@ -1409,7 +1460,7 @@ func (s *store) PutLayer(id, parent string, names []string, mountLabel string, w OriginalDigest: options.OriginalDigest, UncompressedDigest: options.UncompressedDigest, } - if canUseShifting(rlstore, uidMap, gidMap) { + if s.canUseShifting(uidMap, gidMap) { layerOptions.IDMappingOptions = types.IDMappingOptions{HostUIDMapping: true, HostGIDMapping: true, UIDMap: nil, GIDMap: nil} } else { layerOptions.IDMappingOptions = types.IDMappingOptions{ @@ -1535,7 +1586,9 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, i }) } -// imageTopLayerForMapping does ??? +// imageTopLayerForMapping locates the layer that can take the place of the +// image's top layer as the shared parent layer for a one or more containers +// which are using ID mappings. // On entry: // - ristore must be locked EITHER for reading or writing // - s.imageStore must be locked for writing; it might be identical to ristore. @@ -1544,7 +1597,7 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, i func (s *store) imageTopLayerForMapping(image *Image, ristore roImageStore, rlstore rwLayerStore, lstores []roLayerStore, options types.IDMappingOptions) (*Layer, error) { layerMatchesMappingOptions := func(layer *Layer, options types.IDMappingOptions) bool { // If the driver supports shifting and the layer has no mappings, we can use it. - if canUseShifting(rlstore, options.UIDMap, options.GIDMap) && len(layer.UIDMap) == 0 && len(layer.GIDMap) == 0 { + if s.canUseShifting(options.UIDMap, options.GIDMap) && len(layer.UIDMap) == 0 && len(layer.GIDMap) == 0 { return true } // If we want host mapping, and the layer uses mappings, it's not the best match. @@ -1611,7 +1664,7 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore roImageStore, rlst // that lets us edit image metadata, so create a duplicate of the layer with the desired // mappings, and register it as an alternate top layer in the image. var layerOptions LayerOptions - if canUseShifting(rlstore, options.UIDMap, options.GIDMap) { + if s.canUseShifting(options.UIDMap, options.GIDMap) { layerOptions.IDMappingOptions = types.IDMappingOptions{ HostUIDMapping: true, HostGIDMapping: true, @@ -1764,7 +1817,7 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat // But in transient store mode, all container layers are volatile. Volatile: options.Volatile || s.transientStore, } - if canUseShifting(rlstore, uidMap, gidMap) { + if s.canUseShifting(uidMap, gidMap) { layerOptions.IDMappingOptions = types.IDMappingOptions{ HostUIDMapping: true, HostGIDMapping: true, @@ -2715,7 +2768,7 @@ func (s *store) mount(id string, options drivers.MountOpts) (string, error) { defer rlstore.stopWriting() if options.UidMaps != nil || options.GidMaps != nil { - options.DisableShifting = !canUseShifting(rlstore, options.UidMaps, options.GidMaps) + options.DisableShifting = !s.canUseShifting(options.UidMaps, options.GidMaps) } if rlstore.Exists(id) { diff --git a/vendor/github.com/containers/storage/types/options.go b/vendor/github.com/containers/storage/types/options.go index b6faf7e302..3ff00ac647 100644 --- a/vendor/github.com/containers/storage/types/options.go +++ b/vendor/github.com/containers/storage/types/options.go @@ -300,6 +300,7 @@ func getRootlessStorageOpts(rootlessUID int, systemOpts StoreOptions) (StoreOpti // present. if defaultConfigFileSet { opts.GraphDriverOptions = systemOpts.GraphDriverOptions + opts.ImageStore = systemOpts.ImageStore } else if opts.GraphDriverName == overlayDriver { for _, o := range systemOpts.GraphDriverOptions { if strings.Contains(o, "ignore_chown_errors") { diff --git a/vendor/modules.txt b/vendor/modules.txt index a64e2e8cef..4f3e1782b3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -287,7 +287,7 @@ github.com/containers/psgo/internal/dev github.com/containers/psgo/internal/host github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/process -# github.com/containers/storage v1.46.2-0.20230613134951-e424b6649be3 +# github.com/containers/storage v1.46.2-0.20230616083707-cc0d208e5e1c ## explicit; go 1.19 github.com/containers/storage github.com/containers/storage/drivers