mirror of
https://github.com/containers/skopeo.git
synced 2025-09-26 04:35:14 +00:00
update github.com/containers/{image,storage}
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
206
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
206
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
@@ -85,18 +85,20 @@ const (
|
||||
)
|
||||
|
||||
type overlayOptions struct {
|
||||
imageStores []string
|
||||
quota quota.Quota
|
||||
mountProgram string
|
||||
ostreeRepo string
|
||||
skipMountHome bool
|
||||
mountOptions string
|
||||
imageStores []string
|
||||
quota quota.Quota
|
||||
mountProgram string
|
||||
ostreeRepo string
|
||||
skipMountHome bool
|
||||
mountOptions string
|
||||
ignoreChownErrors bool
|
||||
}
|
||||
|
||||
// Driver contains information about the home directory and the list of active mounts that are created using this driver.
|
||||
type Driver struct {
|
||||
name string
|
||||
home string
|
||||
runhome string
|
||||
uidMaps []idtools.IDMap
|
||||
gidMaps []idtools.IDMap
|
||||
ctr *graphdriver.RefCounter
|
||||
@@ -125,8 +127,8 @@ func init() {
|
||||
// Init returns the a native diff driver for overlay filesystem.
|
||||
// If overlay filesystem is not supported on the host, a wrapped graphdriver.ErrNotSupported is returned as error.
|
||||
// If an overlay filesystem is not supported over an existing filesystem then a wrapped graphdriver.ErrIncompatibleFS is returned.
|
||||
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
|
||||
opts, err := parseOptions(options)
|
||||
func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) {
|
||||
opts, err := parseOptions(options.DriverOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -148,7 +150,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
}
|
||||
}
|
||||
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -157,32 +159,72 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
if err := idtools.MkdirAllAs(path.Join(home, linkDir), 0700, rootUID, rootGID); err != nil && !os.IsExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
runhome := filepath.Join(options.RunRoot, filepath.Base(home))
|
||||
if err := idtools.MkdirAllAs(runhome, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var usingMetacopy bool
|
||||
var supportsDType bool
|
||||
if opts.mountProgram != "" {
|
||||
supportsDType = true
|
||||
} else {
|
||||
supportsDType, err = supportsOverlay(home, fsMagic, rootUID, rootGID)
|
||||
if err != nil {
|
||||
os.Remove(filepath.Join(home, linkDir))
|
||||
os.Remove(home)
|
||||
patherr, ok := err.(*os.PathError)
|
||||
if ok && patherr.Err == syscall.ENOSPC {
|
||||
return nil, err
|
||||
}
|
||||
return nil, errors.Wrap(err, "kernel does not support overlay fs")
|
||||
}
|
||||
usingMetacopy, err = doesMetacopy(home, opts.mountOptions)
|
||||
feature := "overlay"
|
||||
overlayCacheResult, overlayCacheText, err := cachedFeatureCheck(runhome, feature)
|
||||
if err == nil {
|
||||
if usingMetacopy {
|
||||
logrus.Debugf("overlay test mount indicated that metacopy is being used")
|
||||
if overlayCacheResult {
|
||||
logrus.Debugf("cached value indicated that overlay is supported")
|
||||
} else {
|
||||
logrus.Debugf("overlay test mount indicated that metacopy is not being used")
|
||||
logrus.Debugf("cached value indicated that overlay is not supported")
|
||||
}
|
||||
supportsDType = overlayCacheResult
|
||||
if !supportsDType {
|
||||
return nil, errors.New(overlayCacheText)
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("overlay test mount did not indicate whether or not metacopy is being used: %v", err)
|
||||
return nil, err
|
||||
supportsDType, err = supportsOverlay(home, fsMagic, rootUID, rootGID)
|
||||
if err != nil {
|
||||
os.Remove(filepath.Join(home, linkDir))
|
||||
os.Remove(home)
|
||||
patherr, ok := err.(*os.PathError)
|
||||
if ok && patherr.Err == syscall.ENOSPC {
|
||||
return nil, err
|
||||
}
|
||||
err = errors.Wrap(err, "kernel does not support overlay fs")
|
||||
if err2 := cachedFeatureRecord(runhome, feature, false, err.Error()); err2 != nil {
|
||||
return nil, errors.Wrapf(err2, "error recording overlay not being supported (%v)", err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if err = cachedFeatureRecord(runhome, feature, supportsDType, ""); err != nil {
|
||||
return nil, errors.Wrap(err, "error recording overlay support status")
|
||||
}
|
||||
}
|
||||
|
||||
feature = fmt.Sprintf("metacopy(%s)", opts.mountOptions)
|
||||
metacopyCacheResult, _, err := cachedFeatureCheck(runhome, feature)
|
||||
if err == nil {
|
||||
if metacopyCacheResult {
|
||||
logrus.Debugf("cached value indicated that metacopy is being used")
|
||||
} else {
|
||||
logrus.Debugf("cached value indicated that metacopy is not being used")
|
||||
}
|
||||
usingMetacopy = metacopyCacheResult
|
||||
} else {
|
||||
usingMetacopy, err = doesMetacopy(home, opts.mountOptions)
|
||||
if err == nil {
|
||||
if usingMetacopy {
|
||||
logrus.Debugf("overlay test mount indicated that metacopy is being used")
|
||||
} else {
|
||||
logrus.Debugf("overlay test mount indicated that metacopy is not being used")
|
||||
}
|
||||
if err = cachedFeatureRecord(runhome, feature, usingMetacopy, ""); err != nil {
|
||||
return nil, errors.Wrap(err, "error recording metacopy-being-used status")
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("overlay test mount did not indicate whether or not metacopy is being used: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,8 +243,9 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
d := &Driver{
|
||||
name: "overlay",
|
||||
home: home,
|
||||
uidMaps: uidMaps,
|
||||
gidMaps: gidMaps,
|
||||
runhome: runhome,
|
||||
uidMaps: options.UIDMaps,
|
||||
gidMaps: options.GIDMaps,
|
||||
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
|
||||
supportsDType: supportsDType,
|
||||
usingMetacopy: usingMetacopy,
|
||||
@@ -211,8 +254,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
convert: make(map[string]bool),
|
||||
}
|
||||
|
||||
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, d)
|
||||
|
||||
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, graphdriver.NewNaiveLayerIDMapUpdater(d))
|
||||
if backingFs == "xfs" {
|
||||
// Try to enable project quota support over xfs.
|
||||
if d.quotaCtl, err = quota.NewControl(home); err == nil {
|
||||
@@ -280,6 +322,12 @@ func parseOptions(options []string) (*overlayOptions, error) {
|
||||
return nil, fmt.Errorf("overlay: ostree_repo specified but support for ostree is missing")
|
||||
}
|
||||
o.ostreeRepo = val
|
||||
case ".ignore_chown_errors", "overlay2.ignore_chown_errors", "overlay.ignore_chown_errors":
|
||||
logrus.Debugf("overlay: ignore_chown_errors=%s", val)
|
||||
o.ignoreChownErrors, err = strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case "overlay2.skip_mount_home", "overlay.skip_mount_home", ".skip_mount_home":
|
||||
logrus.Debugf("overlay: skip_mount_home=%s", val)
|
||||
o.skipMountHome, err = strconv.ParseBool(val)
|
||||
@@ -293,6 +341,36 @@ func parseOptions(options []string) (*overlayOptions, error) {
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func cachedFeatureSet(feature string, set bool) string {
|
||||
if set {
|
||||
return fmt.Sprintf("%s-true", feature)
|
||||
}
|
||||
return fmt.Sprintf("%s-false", feature)
|
||||
}
|
||||
|
||||
func cachedFeatureCheck(runhome, feature string) (supported bool, text string, err error) {
|
||||
content, err := ioutil.ReadFile(filepath.Join(runhome, cachedFeatureSet(feature, true)))
|
||||
if err == nil {
|
||||
return true, string(content), nil
|
||||
}
|
||||
content, err = ioutil.ReadFile(filepath.Join(runhome, cachedFeatureSet(feature, false)))
|
||||
if err == nil {
|
||||
return false, string(content), nil
|
||||
}
|
||||
return false, "", err
|
||||
}
|
||||
|
||||
func cachedFeatureRecord(runhome, feature string, supported bool, text string) (err error) {
|
||||
f, err := os.Create(filepath.Join(runhome, cachedFeatureSet(feature, supported)))
|
||||
if f != nil {
|
||||
if text != "" {
|
||||
fmt.Fprintf(f, "%s", text)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGID int) (supportsDType bool, err error) {
|
||||
// We can try to modprobe overlay first
|
||||
|
||||
@@ -369,10 +447,24 @@ func (d *Driver) useNaiveDiff() bool {
|
||||
useNaiveDiffOnly = true
|
||||
return
|
||||
}
|
||||
feature := fmt.Sprintf("native-diff(%s)", d.options.mountOptions)
|
||||
nativeDiffCacheResult, nativeDiffCacheText, err := cachedFeatureCheck(d.runhome, feature)
|
||||
if err == nil {
|
||||
if nativeDiffCacheResult {
|
||||
logrus.Debugf("cached value indicated that native-diff is usable")
|
||||
} else {
|
||||
logrus.Debugf("cached value indicated that native-diff is not being used")
|
||||
logrus.Warn(nativeDiffCacheText)
|
||||
}
|
||||
useNaiveDiffOnly = !nativeDiffCacheResult
|
||||
return
|
||||
}
|
||||
if err := doesSupportNativeDiff(d.home, d.options.mountOptions); err != nil {
|
||||
logrus.Warnf("Not using native diff for overlay, this may cause degraded performance for building images: %v", err)
|
||||
nativeDiffCacheText = fmt.Sprintf("Not using native diff for overlay, this may cause degraded performance for building images: %v", err)
|
||||
logrus.Warn(nativeDiffCacheText)
|
||||
useNaiveDiffOnly = true
|
||||
}
|
||||
cachedFeatureRecord(d.runhome, feature, !useNaiveDiffOnly, nativeDiffCacheText)
|
||||
})
|
||||
return useNaiveDiffOnly
|
||||
}
|
||||
@@ -748,7 +840,6 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
||||
return "", err
|
||||
}
|
||||
|
||||
diffDir := path.Join(dir, "diff")
|
||||
lowers, err := ioutil.ReadFile(path.Join(dir, lowerFile))
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return "", err
|
||||
@@ -824,7 +915,22 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
||||
relLowers = append(relLowers, path.Join(id, "empty"))
|
||||
}
|
||||
|
||||
// user namespace requires this to move a directory from lower to upper.
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
diffDir := path.Join(dir, "diff")
|
||||
if err := idtools.MkdirAs(diffDir, 0755, rootUID, rootGID); err != nil && !os.IsExist(err) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
mergedDir := path.Join(dir, "merged")
|
||||
// Create the driver merged dir
|
||||
if err := idtools.MkdirAs(mergedDir, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) {
|
||||
return "", err
|
||||
}
|
||||
if count := d.ctr.Increment(mergedDir); count > 1 {
|
||||
return mergedDir, nil
|
||||
}
|
||||
@@ -893,17 +999,6 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
|
||||
return "", fmt.Errorf("error creating overlay mount to %s: %v", mountTarget, err)
|
||||
}
|
||||
|
||||
// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
|
||||
// user namespace requires this to move a directory from lower to upper.
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return mergedDir, nil
|
||||
}
|
||||
|
||||
@@ -915,7 +1010,7 @@ func (d *Driver) Put(id string) error {
|
||||
if _, err := os.Stat(dir); err != nil {
|
||||
return err
|
||||
}
|
||||
mountpoint := path.Join(d.dir(id), "merged")
|
||||
mountpoint := path.Join(dir, "merged")
|
||||
if count := d.ctr.Decrement(mountpoint); count > 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -925,6 +1020,11 @@ func (d *Driver) Put(id string) error {
|
||||
if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil {
|
||||
logrus.Debugf("Failed to unmount %s overlay: %s - %v", id, mountpoint, err)
|
||||
}
|
||||
|
||||
if err := unix.Rmdir(mountpoint); err != nil && !os.IsNotExist(err) {
|
||||
logrus.Debugf("Failed to remove mountpoint %s overlay: %s - %v", id, mountpoint, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -967,11 +1067,16 @@ func (d *Driver) getWhiteoutFormat() archive.WhiteoutFormat {
|
||||
}
|
||||
|
||||
// ApplyDiff applies the new layer into a root
|
||||
func (d *Driver) ApplyDiff(id string, idMappings *idtools.IDMappings, parent string, mountLabel string, diff io.Reader) (size int64, err error) {
|
||||
func (d *Driver) ApplyDiff(id, parent string, options graphdriver.ApplyDiffOpts) (size int64, err error) {
|
||||
|
||||
if !d.isParent(id, parent) {
|
||||
return d.naiveDiff.ApplyDiff(id, idMappings, parent, mountLabel, diff)
|
||||
if d.options.ignoreChownErrors {
|
||||
options.IgnoreChownErrors = d.options.ignoreChownErrors
|
||||
}
|
||||
return d.naiveDiff.ApplyDiff(id, parent, options)
|
||||
}
|
||||
|
||||
idMappings := options.Mappings
|
||||
if idMappings == nil {
|
||||
idMappings = &idtools.IDMappings{}
|
||||
}
|
||||
@@ -980,11 +1085,12 @@ func (d *Driver) ApplyDiff(id string, idMappings *idtools.IDMappings, parent str
|
||||
|
||||
logrus.Debugf("Applying tar in %s", applyDir)
|
||||
// Overlay doesn't need the parent id to apply the diff
|
||||
if err := untar(diff, applyDir, &archive.TarOptions{
|
||||
UIDMaps: idMappings.UIDs(),
|
||||
GIDMaps: idMappings.GIDs(),
|
||||
WhiteoutFormat: d.getWhiteoutFormat(),
|
||||
InUserNS: rsystem.RunningInUserNS(),
|
||||
if err := untar(options.Diff, applyDir, &archive.TarOptions{
|
||||
UIDMaps: idMappings.UIDs(),
|
||||
GIDMaps: idMappings.GIDs(),
|
||||
IgnoreChownErrors: d.options.ignoreChownErrors,
|
||||
WhiteoutFormat: d.getWhiteoutFormat(),
|
||||
InUserNS: rsystem.RunningInUserNS(),
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user