vendor: update c/storage to 26c561f9

update c/storage to commit 26c561f9a64585d9a25d340e1ae5479eca8008a1.

It contains an important fix for partial pulls.

[NO NEW TESTS NEEDED]

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano
2022-02-17 14:52:32 +01:00
parent c018c0f3c7
commit 38811823c1
16 changed files with 208 additions and 93 deletions

2
go.mod
View File

@ -17,7 +17,7 @@ require (
github.com/containers/image/v5 v5.19.1 github.com/containers/image/v5 v5.19.1
github.com/containers/ocicrypt v1.1.2 github.com/containers/ocicrypt v1.1.2
github.com/containers/psgo v1.7.2 github.com/containers/psgo v1.7.2
github.com/containers/storage v1.38.2 github.com/containers/storage v1.38.3-0.20220214113600-26c561f9a645
github.com/coreos/go-systemd/v22 v22.3.2 github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3 github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
github.com/cyphar/filepath-securejoin v0.2.3 github.com/cyphar/filepath-securejoin v0.2.3

6
go.sum
View File

@ -343,8 +343,9 @@ github.com/containers/psgo v1.7.2 h1:WbCvsY9w+nCv3j4der0mbD3PSRUv/W8l+G0YrZrdSDc
github.com/containers/psgo v1.7.2/go.mod h1:SLpqxsPOHtTqRygjutCPXmeU2PoEFzV3gzJplN4BMx0= github.com/containers/psgo v1.7.2/go.mod h1:SLpqxsPOHtTqRygjutCPXmeU2PoEFzV3gzJplN4BMx0=
github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c+Q/45RlH6r4= github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c+Q/45RlH6r4=
github.com/containers/storage v1.38.0/go.mod h1:lBzt28gAk5ADZuRtwdndRJyqX22vnRaXmlF+7ktfMYc= github.com/containers/storage v1.38.0/go.mod h1:lBzt28gAk5ADZuRtwdndRJyqX22vnRaXmlF+7ktfMYc=
github.com/containers/storage v1.38.2 h1:8bAIxnVBGKzMw5EWCivVj24bztQT6IkDp4uHiyhnzwE=
github.com/containers/storage v1.38.2/go.mod h1:INP0RPLHWBxx+pTsO5uiHlDUGHDFvWZPWprAbAlQWPQ= github.com/containers/storage v1.38.2/go.mod h1:INP0RPLHWBxx+pTsO5uiHlDUGHDFvWZPWprAbAlQWPQ=
github.com/containers/storage v1.38.3-0.20220214113600-26c561f9a645 h1:2zzCKvfSq9T9zHGVWBygnYMdkBBmEsqXFa9gvWT4AFk=
github.com/containers/storage v1.38.3-0.20220214113600-26c561f9a645/go.mod h1:ugJrnJvpb6LrUshIYF/9g9YP9D4VTCYP+wShSiuqxN4=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 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/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
@ -935,8 +936,9 @@ github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM=
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/mountinfo v0.6.0 h1:gUDhXQx58YNrpHlK4nSL+7y2pxFZkUcXqzFDKWdC0Oo=
github.com/moby/sys/mountinfo v0.6.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc=

View File

@ -1 +1 @@
1.38.2 1.38.2+dev

View File

@ -324,6 +324,12 @@ func (r *containerStore) Create(id string, names []string, image, layer, metadat
fmt.Sprintf("the container name \"%s\" is already in use by \"%s\". You have to remove that container to be able to reuse that name.", name, r.byname[name].ID)) fmt.Sprintf("the container name \"%s\" is already in use by \"%s\". You have to remove that container to be able to reuse that name.", name, r.byname[name].ID))
} }
} }
if err := hasOverlappingRanges(options.UIDMap); err != nil {
return nil, err
}
if err := hasOverlappingRanges(options.GIDMap); err != nil {
return nil, err
}
if err == nil { if err == nil {
container = &Container{ container = &Container{
ID: id, ID: id,

View File

@ -1,3 +1,4 @@
//go:build linux
// +build linux // +build linux
package overlay package overlay
@ -1166,6 +1167,9 @@ func (d *Driver) Remove(id string) error {
// under each layer has a symlink created for it under the linkDir. If the symlink does not // under each layer has a symlink created for it under the linkDir. If the symlink does not
// exist, it creates them // exist, it creates them
func (d *Driver) recreateSymlinks() error { func (d *Driver) recreateSymlinks() error {
// We have at most 3 corrective actions per layer, so 10 iterations is plenty.
const maxIterations = 10
// List all the directories under the home directory // List all the directories under the home directory
dirs, err := ioutil.ReadDir(d.home) dirs, err := ioutil.ReadDir(d.home)
if err != nil { if err != nil {
@ -1183,6 +1187,7 @@ func (d *Driver) recreateSymlinks() error {
// Keep looping as long as we take some corrective action in each iteration // Keep looping as long as we take some corrective action in each iteration
var errs *multierror.Error var errs *multierror.Error
madeProgress := true madeProgress := true
iterations := 0
for madeProgress { for madeProgress {
errs = nil errs = nil
madeProgress = false madeProgress = false
@ -1233,7 +1238,12 @@ func (d *Driver) recreateSymlinks() error {
if len(targetComponents) != 3 || targetComponents[0] != ".." || targetComponents[2] != "diff" { if len(targetComponents) != 3 || targetComponents[0] != ".." || targetComponents[2] != "diff" {
errs = multierror.Append(errs, errors.Errorf("link target of %q looks weird: %q", link, target)) errs = multierror.Append(errs, errors.Errorf("link target of %q looks weird: %q", link, target))
// force the link to be recreated on the next pass // force the link to be recreated on the next pass
os.Remove(filepath.Join(linksDir, link.Name())) if err := os.Remove(filepath.Join(linksDir, link.Name())); err != nil {
if !os.IsNotExist(err) {
errs = multierror.Append(errs, errors.Wrapf(err, "removing link %q", link))
} // else dont report any error, but also dont set madeProgress.
continue
}
madeProgress = true madeProgress = true
continue continue
} }
@ -1250,6 +1260,11 @@ func (d *Driver) recreateSymlinks() error {
madeProgress = true madeProgress = true
} }
} }
iterations++
if iterations >= maxIterations {
errs = multierror.Append(errs, fmt.Errorf("Reached %d iterations in overlay graph drivers recreateSymlink, giving up", iterations))
break
}
} }
if errs != nil { if errs != nil {
return errs.ErrorOrNil() return errs.ErrorOrNil()

View File

@ -55,4 +55,6 @@ var (
ErrStoreIsReadOnly = types.ErrStoreIsReadOnly ErrStoreIsReadOnly = types.ErrStoreIsReadOnly
// ErrNotSupported is returned when the requested functionality is not supported. // ErrNotSupported is returned when the requested functionality is not supported.
ErrNotSupported = types.ErrNotSupported ErrNotSupported = types.ErrNotSupported
// ErrInvalidMappings is returned when the specified mappings are invalid.
ErrInvalidMappings = types.ErrInvalidMappings
) )

View File

@ -16,7 +16,7 @@ require (
github.com/klauspost/pgzip v1.2.5 github.com/klauspost/pgzip v1.2.5
github.com/mattn/go-shellwords v1.0.12 github.com/mattn/go-shellwords v1.0.12
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible
github.com/moby/sys/mountinfo v0.5.0 github.com/moby/sys/mountinfo v0.6.0
github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/runc v1.1.0 github.com/opencontainers/runc v1.1.0
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417

View File

@ -466,8 +466,9 @@ github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQ
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/mountinfo v0.6.0 h1:gUDhXQx58YNrpHlK4nSL+7y2pxFZkUcXqzFDKWdC0Oo=
github.com/moby/sys/mountinfo v0.6.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=

View File

@ -1,6 +1,9 @@
package storage package storage
import ( import (
"fmt"
"strings"
"github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/idtools"
"github.com/google/go-intervals/intervalset" "github.com/google/go-intervals/intervalset"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -218,3 +221,45 @@ func maxInt(a, b int) int {
} }
return a return a
} }
func hasOverlappingRanges(mappings []idtools.IDMap) error {
hostIntervals := intervalset.Empty()
containerIntervals := intervalset.Empty()
var conflicts []string
for _, m := range mappings {
c := interval{start: m.ContainerID, end: m.ContainerID + m.Size}
h := interval{start: m.HostID, end: m.HostID + m.Size}
added := false
overlaps := false
containerIntervals.IntervalsBetween(c, func(x intervalset.Interval) bool {
overlaps = true
return false
})
if overlaps {
conflicts = append(conflicts, fmt.Sprintf("%v:%v:%v", m.ContainerID, m.HostID, m.Size))
added = true
}
containerIntervals.Add(intervalset.NewSet([]intervalset.Interval{c}))
hostIntervals.IntervalsBetween(h, func(x intervalset.Interval) bool {
overlaps = true
return false
})
if overlaps && !added {
conflicts = append(conflicts, fmt.Sprintf("%v:%v:%v", m.ContainerID, m.HostID, m.Size))
}
hostIntervals.Add(intervalset.NewSet([]intervalset.Interval{h}))
}
if conflicts != nil {
if len(conflicts) == 1 {
return errors.Wrapf(ErrInvalidMappings, "the specified UID and/or GID mapping %s conflicts with other mappings", conflicts[0])
}
return errors.Wrapf(ErrInvalidMappings, "the specified UID and/or GID mappings %s conflict with other mappings", strings.Join(conflicts, ", "))
}
return nil
}

View File

@ -108,35 +108,32 @@ func (c *layersCache) load() error {
} }
bigData, err := c.store.LayerBigData(r.ID, cacheKey) bigData, err := c.store.LayerBigData(r.ID, cacheKey)
if err != nil { // if the cache areadly exists, read and use it
if errors.Cause(err) == os.ErrNotExist { if err == nil {
defer bigData.Close()
metadata, err := readMetadataFromCache(bigData)
if err == nil {
c.addLayer(r.ID, metadata)
continue continue
} }
logrus.Warningf("Error reading cache file for layer %q: %v", r.ID, err)
} else if errors.Cause(err) != os.ErrNotExist {
return err return err
} }
defer bigData.Close()
metadata, err := readMetadataFromCache(bigData)
if err != nil {
logrus.Warningf("Error reading cache file for layer %q: %v", r.ID, err)
}
if metadata != nil {
c.addLayer(r.ID, metadata)
continue
}
// otherwise create it from the layer TOC.
manifestReader, err := c.store.LayerBigData(r.ID, bigDataKey) manifestReader, err := c.store.LayerBigData(r.ID, bigDataKey)
if err != nil { if err != nil {
continue continue
} }
defer manifestReader.Close() defer manifestReader.Close()
manifest, err := ioutil.ReadAll(manifestReader) manifest, err := ioutil.ReadAll(manifestReader)
if err != nil { if err != nil {
return fmt.Errorf("open manifest file for layer %q: %w", r.ID, err) return fmt.Errorf("open manifest file for layer %q: %w", r.ID, err)
} }
metadata, err = writeCache(manifest, r.ID, c.store) metadata, err := writeCache(manifest, r.ID, c.store)
if err == nil { if err == nil {
c.addLayer(r.ID, metadata) c.addLayer(r.ID, metadata)
} }

View File

@ -12,109 +12,109 @@ type ThinpoolOptionsConfig struct {
// grown. This is specified in terms of % of pool size. So a value of // grown. This is specified in terms of % of pool size. So a value of
// 20 means that when threshold is hit, pool will be grown by 20% of // 20 means that when threshold is hit, pool will be grown by 20% of
// existing pool size. // existing pool size.
AutoExtendPercent string `toml:"autoextend_percent"` AutoExtendPercent string `toml:"autoextend_percent,omitempty"`
// AutoExtendThreshold determines the pool extension threshold in terms // AutoExtendThreshold determines the pool extension threshold in terms
// of percentage of pool size. For example, if threshold is 60, that // of percentage of pool size. For example, if threshold is 60, that
// means when pool is 60% full, threshold has been hit. // means when pool is 60% full, threshold has been hit.
AutoExtendThreshold string `toml:"autoextend_threshold"` AutoExtendThreshold string `toml:"autoextend_threshold,omitempty"`
// BaseSize specifies the size to use when creating the base device, // BaseSize specifies the size to use when creating the base device,
// which limits the size of images and containers. // which limits the size of images and containers.
BaseSize string `toml:"basesize"` BaseSize string `toml:"basesize,omitempty"`
// BlockSize specifies a custom blocksize to use for the thin pool. // BlockSize specifies a custom blocksize to use for the thin pool.
BlockSize string `toml:"blocksize"` BlockSize string `toml:"blocksize,omitempty"`
// DirectLvmDevice specifies a custom block storage device to use for // DirectLvmDevice specifies a custom block storage device to use for
// the thin pool. // the thin pool.
DirectLvmDevice string `toml:"directlvm_device"` DirectLvmDevice string `toml:"directlvm_device,omitempty"`
// DirectLvmDeviceForcewipes device even if device already has a // DirectLvmDeviceForcewipes device even if device already has a
// filesystem // filesystem
DirectLvmDeviceForce string `toml:"directlvm_device_force"` DirectLvmDeviceForce string `toml:"directlvm_device_force,omitempty"`
// Fs specifies the filesystem type to use for the base device. // Fs specifies the filesystem type to use for the base device.
Fs string `toml:"fs"` Fs string `toml:"fs,omitempty"`
// log_level sets the log level of devicemapper. // log_level sets the log level of devicemapper.
LogLevel string `toml:"log_level"` LogLevel string `toml:"log_level,omitempty"`
// MetadataSize specifies the size of the metadata for the thinpool // MetadataSize specifies the size of the metadata for the thinpool
// It will be used with the `pvcreate --metadata` option. // It will be used with the `pvcreate --metadata` option.
MetadataSize string `toml:"metadatasize"` MetadataSize string `toml:"metadatasize,omitempty"`
// MinFreeSpace specifies the min free space percent in a thin pool // MinFreeSpace specifies the min free space percent in a thin pool
// require for new device creation to // require for new device creation to
MinFreeSpace string `toml:"min_free_space"` MinFreeSpace string `toml:"min_free_space,omitempty"`
// MkfsArg specifies extra mkfs arguments to be used when creating the // MkfsArg specifies extra mkfs arguments to be used when creating the
// basedevice. // basedevice.
MkfsArg string `toml:"mkfsarg"` MkfsArg string `toml:"mkfsarg,omitempty"`
// MountOpt specifies extra mount options used when mounting the thin // MountOpt specifies extra mount options used when mounting the thin
// devices. // devices.
MountOpt string `toml:"mountopt"` MountOpt string `toml:"mountopt,omitempty"`
// Size // Size
Size string `toml:"size"` Size string `toml:"size,omitempty"`
// UseDeferredDeletion marks device for deferred deletion // UseDeferredDeletion marks device for deferred deletion
UseDeferredDeletion string `toml:"use_deferred_deletion"` UseDeferredDeletion string `toml:"use_deferred_deletion,omitempty"`
// UseDeferredRemoval marks device for deferred removal // UseDeferredRemoval marks device for deferred removal
UseDeferredRemoval string `toml:"use_deferred_removal"` UseDeferredRemoval string `toml:"use_deferred_removal,omitempty"`
// XfsNoSpaceMaxRetriesFreeSpace specifies the maximum number of // XfsNoSpaceMaxRetriesFreeSpace specifies the maximum number of
// retries XFS should attempt to complete IO when ENOSPC (no space) // retries XFS should attempt to complete IO when ENOSPC (no space)
// error is returned by underlying storage device. // error is returned by underlying storage device.
XfsNoSpaceMaxRetries string `toml:"xfs_nospace_max_retries"` XfsNoSpaceMaxRetries string `toml:"xfs_nospace_max_retries,omitempty"`
} }
type AufsOptionsConfig struct { type AufsOptionsConfig struct {
// MountOpt specifies extra mount options used when mounting // MountOpt specifies extra mount options used when mounting
MountOpt string `toml:"mountopt"` MountOpt string `toml:"mountopt,omitempty"`
} }
type BtrfsOptionsConfig struct { type BtrfsOptionsConfig struct {
// MinSpace is the minimal spaces allocated to the device // MinSpace is the minimal spaces allocated to the device
MinSpace string `toml:"min_space"` MinSpace string `toml:"min_space,omitempty"`
// Size // Size
Size string `toml:"size"` Size string `toml:"size,omitempty"`
} }
type OverlayOptionsConfig struct { type OverlayOptionsConfig struct {
// IgnoreChownErrors is a flag for whether chown errors should be // IgnoreChownErrors is a flag for whether chown errors should be
// ignored when building an image. // ignored when building an image.
IgnoreChownErrors string `toml:"ignore_chown_errors"` IgnoreChownErrors string `toml:"ignore_chown_errors,omitempty"`
// MountOpt specifies extra mount options used when mounting // MountOpt specifies extra mount options used when mounting
MountOpt string `toml:"mountopt"` MountOpt string `toml:"mountopt,omitempty"`
// Alternative program to use for the mount of the file system // Alternative program to use for the mount of the file system
MountProgram string `toml:"mount_program"` MountProgram string `toml:"mount_program,omitempty"`
// Size // Size
Size string `toml:"size"` Size string `toml:"size,omitempty"`
// Inodes is used to set a maximum inodes of the container image. // Inodes is used to set a maximum inodes of the container image.
Inodes string `toml:"inodes"` Inodes string `toml:"inodes,omitempty"`
// Do not create a bind mount on the storage home // Do not create a bind mount on the storage home
SkipMountHome string `toml:"skip_mount_home"` SkipMountHome string `toml:"skip_mount_home,omitempty"`
// ForceMask indicates the permissions mask (e.g. "0755") to use for new // ForceMask indicates the permissions mask (e.g. "0755") to use for new
// files and directories // files and directories
ForceMask string `toml:"force_mask"` ForceMask string `toml:"force_mask,omitempty"`
} }
type VfsOptionsConfig struct { type VfsOptionsConfig struct {
// IgnoreChownErrors is a flag for whether chown errors should be // IgnoreChownErrors is a flag for whether chown errors should be
// ignored when building an image. // ignored when building an image.
IgnoreChownErrors string `toml:"ignore_chown_errors"` IgnoreChownErrors string `toml:"ignore_chown_errors,omitempty"`
} }
type ZfsOptionsConfig struct { type ZfsOptionsConfig struct {
// MountOpt specifies extra mount options used when mounting // MountOpt specifies extra mount options used when mounting
MountOpt string `toml:"mountopt"` MountOpt string `toml:"mountopt,omitempty"`
// Name is the File System name of the ZFS File system // Name is the File System name of the ZFS File system
Name string `toml:"fsname"` Name string `toml:"fsname,omitempty"`
// Size // Size
Size string `toml:"size"` Size string `toml:"size,omitempty"`
} }
// OptionsConfig represents the "storage.options" TOML config table. // OptionsConfig represents the "storage.options" TOML config table.
@ -122,82 +122,82 @@ type OptionsConfig struct {
// AdditionalImagesStores is the location of additional read/only // AdditionalImagesStores is the location of additional read/only
// Image stores. Usually used to access Networked File System // Image stores. Usually used to access Networked File System
// for shared image content // for shared image content
AdditionalImageStores []string `toml:"additionalimagestores"` AdditionalImageStores []string `toml:"additionalimagestores,omitempty"`
// AdditionalLayerStores is the location of additional read/only // AdditionalLayerStores is the location of additional read/only
// Layer stores. Usually used to access Networked File System // Layer stores. Usually used to access Networked File System
// for shared image content // for shared image content
// This API is experimental and can be changed without bumping the // This API is experimental and can be changed without bumping the
// major version number. // major version number.
AdditionalLayerStores []string `toml:"additionallayerstores"` AdditionalLayerStores []string `toml:"additionallayerstores,omitempty"`
// Size // Size
Size string `toml:"size"` Size string `toml:"size,omitempty"`
// RemapUIDs is a list of default UID mappings to use for layers. // RemapUIDs is a list of default UID mappings to use for layers.
RemapUIDs string `toml:"remap-uids"` RemapUIDs string `toml:"remap-uids,omitempty"`
// RemapGIDs is a list of default GID mappings to use for layers. // RemapGIDs is a list of default GID mappings to use for layers.
RemapGIDs string `toml:"remap-gids"` RemapGIDs string `toml:"remap-gids,omitempty"`
// IgnoreChownErrors is a flag for whether chown errors should be // IgnoreChownErrors is a flag for whether chown errors should be
// ignored when building an image. // ignored when building an image.
IgnoreChownErrors string `toml:"ignore_chown_errors"` IgnoreChownErrors string `toml:"ignore_chown_errors,omitempty"`
// ForceMask indicates the permissions mask (e.g. "0755") to use for new // ForceMask indicates the permissions mask (e.g. "0755") to use for new
// files and directories. // files and directories.
ForceMask os.FileMode `toml:"force_mask"` ForceMask os.FileMode `toml:"force_mask,omitempty"`
// RemapUser is the name of one or more entries in /etc/subuid which // RemapUser is the name of one or more entries in /etc/subuid which
// should be used to set up default UID mappings. // should be used to set up default UID mappings.
RemapUser string `toml:"remap-user"` RemapUser string `toml:"remap-user,omitempty"`
// RemapGroup is the name of one or more entries in /etc/subgid which // RemapGroup is the name of one or more entries in /etc/subgid which
// should be used to set up default GID mappings. // should be used to set up default GID mappings.
RemapGroup string `toml:"remap-group"` RemapGroup string `toml:"remap-group,omitempty"`
// RootAutoUsernsUser is the name of one or more entries in /etc/subuid and // RootAutoUsernsUser is the name of one or more entries in /etc/subuid and
// /etc/subgid which should be used to set up automatically a userns. // /etc/subgid which should be used to set up automatically a userns.
RootAutoUsernsUser string `toml:"root-auto-userns-user"` RootAutoUsernsUser string `toml:"root-auto-userns-user,omitempty"`
// AutoUsernsMinSize is the minimum size for a user namespace that is // AutoUsernsMinSize is the minimum size for a user namespace that is
// created automatically. // created automatically.
AutoUsernsMinSize uint32 `toml:"auto-userns-min-size"` AutoUsernsMinSize uint32 `toml:"auto-userns-min-size,omitempty"`
// AutoUsernsMaxSize is the maximum size for a user namespace that is // AutoUsernsMaxSize is the maximum size for a user namespace that is
// created automatically. // created automatically.
AutoUsernsMaxSize uint32 `toml:"auto-userns-max-size"` AutoUsernsMaxSize uint32 `toml:"auto-userns-max-size,omitempty"`
// Aufs container options to be handed to aufs drivers // Aufs container options to be handed to aufs drivers
Aufs struct{ AufsOptionsConfig } `toml:"aufs"` Aufs struct{ AufsOptionsConfig } `toml:"aufs,omitempty"`
// Btrfs container options to be handed to btrfs drivers // Btrfs container options to be handed to btrfs drivers
Btrfs struct{ BtrfsOptionsConfig } `toml:"btrfs"` Btrfs struct{ BtrfsOptionsConfig } `toml:"btrfs,omitempty"`
// Thinpool container options to be handed to thinpool drivers // Thinpool container options to be handed to thinpool drivers
Thinpool struct{ ThinpoolOptionsConfig } `toml:"thinpool"` Thinpool struct{ ThinpoolOptionsConfig } `toml:"thinpool,omitempty"`
// Overlay container options to be handed to overlay drivers // Overlay container options to be handed to overlay drivers
Overlay struct{ OverlayOptionsConfig } `toml:"overlay"` Overlay struct{ OverlayOptionsConfig } `toml:"overlay,omitempty"`
// Vfs container options to be handed to VFS drivers // Vfs container options to be handed to VFS drivers
Vfs struct{ VfsOptionsConfig } `toml:"vfs"` Vfs struct{ VfsOptionsConfig } `toml:"vfs,omitempty"`
// Zfs container options to be handed to ZFS drivers // Zfs container options to be handed to ZFS drivers
Zfs struct{ ZfsOptionsConfig } `toml:"zfs"` Zfs struct{ ZfsOptionsConfig } `toml:"zfs,omitempty"`
// Do not create a bind mount on the storage home // Do not create a bind mount on the storage home
SkipMountHome string `toml:"skip_mount_home"` SkipMountHome string `toml:"skip_mount_home,omitempty"`
// Alternative program to use for the mount of the file system // Alternative program to use for the mount of the file system
MountProgram string `toml:"mount_program"` MountProgram string `toml:"mount_program,omitempty"`
// MountOpt specifies extra mount options used when mounting // MountOpt specifies extra mount options used when mounting
MountOpt string `toml:"mountopt"` MountOpt string `toml:"mountopt,omitempty"`
// PullOptions specifies options to be handed to pull managers // PullOptions specifies options to be handed to pull managers
// This API is experimental and can be changed without bumping the major version number. // This API is experimental and can be changed without bumping the major version number.
PullOptions map[string]string `toml:"pull_options"` PullOptions map[string]string `toml:"pull_options,omitempty"`
// DisableVolatile doesn't allow volatile mounts when it is set. // DisableVolatile doesn't allow volatile mounts when it is set.
DisableVolatile bool `toml:"disable-volatile"` DisableVolatile bool `toml:"disable-volatile,omitempty"`
} }
// GetGraphDriverOptions returns the driver specific options // GetGraphDriverOptions returns the driver specific options

View File

@ -55,4 +55,6 @@ var (
ErrStoreIsReadOnly = errors.New("called a write method on a read-only store") ErrStoreIsReadOnly = errors.New("called a write method on a read-only store")
// ErrNotSupported is returned when the requested functionality is not supported. // ErrNotSupported is returned when the requested functionality is not supported.
ErrNotSupported = errors.New("not supported") ErrNotSupported = errors.New("not supported")
// ErrInvalidMappings is returned when the specified mappings are invalid.
ErrInvalidMappings = errors.New("invalid mappings specified")
) )

View File

@ -19,11 +19,11 @@ import (
// TOML-friendly explicit tables used for conversions. // TOML-friendly explicit tables used for conversions.
type TomlConfig struct { type TomlConfig struct {
Storage struct { Storage struct {
Driver string `toml:"driver"` Driver string `toml:"driver,omitempty"`
RunRoot string `toml:"runroot"` RunRoot string `toml:"runroot,omitempty"`
GraphRoot string `toml:"graphroot"` GraphRoot string `toml:"graphroot,omitempty"`
RootlessStoragePath string `toml:"rootless_storage_path"` RootlessStoragePath string `toml:"rootless_storage_path,omitempty"`
Options cfg.OptionsConfig `toml:"options"` Options cfg.OptionsConfig `toml:"options,omitempty"`
} `toml:"storage"` } `toml:"storage"`
} }
@ -431,11 +431,12 @@ func Save(conf TomlConfig, rootless bool) error {
if err != nil { if err != nil {
return err return err
} }
if err = os.Remove(configFile); !os.IsNotExist(err) {
if err = os.Remove(configFile); !os.IsNotExist(err) && err != nil {
return err return err
} }
f, err := os.Open(configFile) f, err := os.Create(configFile)
if err != nil { if err != nil {
return err return err
} }

View File

@ -7,6 +7,34 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
// MountedFast is a method of detecting a mount point without reading
// mountinfo from procfs. A caller can only trust the result if no error
// and sure == true are returned. Otherwise, other methods (e.g. parsing
// /proc/mounts) have to be used. If unsure, use Mounted instead (which
// uses MountedFast, but falls back to parsing mountinfo if needed).
//
// If a non-existent path is specified, an appropriate error is returned.
// In case the caller is not interested in this particular error, it should
// be handled separately using e.g. errors.Is(err, os.ErrNotExist).
//
// This function is only available on Linux. When available (since kernel
// v5.6), openat2(2) syscall is used to reliably detect all mounts. Otherwise,
// the implementation falls back to using stat(2), which can reliably detect
// normal (but not bind) mounts.
func MountedFast(path string) (mounted, sure bool, err error) {
// Root is always mounted.
if path == string(os.PathSeparator) {
return true, true, nil
}
path, err = normalizePath(path)
if err != nil {
return false, false, err
}
mounted, sure, err = mountedFast(path)
return
}
// mountedByOpenat2 is a method of detecting a mount that works for all kinds // mountedByOpenat2 is a method of detecting a mount that works for all kinds
// of mounts (incl. bind mounts), but requires a recent (v5.6+) linux kernel. // of mounts (incl. bind mounts), but requires a recent (v5.6+) linux kernel.
func mountedByOpenat2(path string) (bool, error) { func mountedByOpenat2(path string) (bool, error) {
@ -34,24 +62,40 @@ func mountedByOpenat2(path string) (bool, error) {
return false, &os.PathError{Op: "openat2", Path: path, Err: err} return false, &os.PathError{Op: "openat2", Path: path, Err: err}
} }
func mounted(path string) (bool, error) { // mountedFast is similar to MountedFast, except it expects a normalized path.
path, err := normalizePath(path) func mountedFast(path string) (mounted, sure bool, err error) {
if err != nil { // Root is always mounted.
return false, err if path == string(os.PathSeparator) {
return true, true, nil
} }
// Try a fast path, using openat2() with RESOLVE_NO_XDEV. // Try a fast path, using openat2() with RESOLVE_NO_XDEV.
mounted, err := mountedByOpenat2(path) mounted, err = mountedByOpenat2(path)
if err == nil { if err == nil {
return mounted, nil return mounted, true, nil
} }
// Another fast path: compare st.st_dev fields. // Another fast path: compare st.st_dev fields.
mounted, err = mountedByStat(path) mounted, err = mountedByStat(path)
// This does not work for bind mounts, so false negative // This does not work for bind mounts, so false negative
// is possible, therefore only trust if return is true. // is possible, therefore only trust if return is true.
if mounted && err == nil { if mounted && err == nil {
return true, true, nil
}
return
}
func mounted(path string) (bool, error) {
path, err := normalizePath(path)
if err != nil {
return false, err
}
mounted, sure, err := mountedFast(path)
if sure && err == nil {
return mounted, nil return mounted, nil
} }
// Fallback to parsing mountinfo // Fallback to parsing mountinfo.
return mountedByMountinfo(path) return mountedByMountinfo(path)
} }

View File

@ -13,9 +13,9 @@ func GetMounts(f FilterFunc) ([]*Info, error) {
// Mounted determines if a specified path is a mount point. In case of any // Mounted determines if a specified path is a mount point. In case of any
// error, false (and an error) is returned. // error, false (and an error) is returned.
// //
// The non-existent path returns an error. If a caller is not interested // If a non-existent path is specified, an appropriate error is returned.
// in this particular error, it should handle it separately using e.g. // In case the caller is not interested in this particular error, it should
// errors.Is(err, os.ErrNotExist). // be handled separately using e.g. errors.Is(err, os.ErrNotExist).
func Mounted(path string) (bool, error) { func Mounted(path string) (bool, error) {
// root is always mounted // root is always mounted
if path == string(os.PathSeparator) { if path == string(os.PathSeparator) {

4
vendor/modules.txt vendored
View File

@ -231,7 +231,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process github.com/containers/psgo/internal/process
# github.com/containers/storage v1.38.2 # github.com/containers/storage v1.38.3-0.20220214113600-26c561f9a645
## explicit ## explicit
github.com/containers/storage github.com/containers/storage
github.com/containers/storage/drivers github.com/containers/storage/drivers
@ -491,7 +491,7 @@ github.com/mistifyio/go-zfs
github.com/mitchellh/mapstructure github.com/mitchellh/mapstructure
# github.com/moby/sys/mount v0.2.0 # github.com/moby/sys/mount v0.2.0
github.com/moby/sys/mount github.com/moby/sys/mount
# github.com/moby/sys/mountinfo v0.5.0 # github.com/moby/sys/mountinfo v0.6.0
github.com/moby/sys/mountinfo github.com/moby/sys/mountinfo
# github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 # github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
## explicit ## explicit