Skip to content

Commit 05c69f1

Browse files
committed
overlay: check if metacopy is happening
In the overlay driver, check if metacopy is enabled, and report it along with other status information. Signed-off-by: Nalin Dahyabhai <[email protected]>
1 parent 263351e commit 05c69f1

File tree

2 files changed

+79
-4
lines changed

2 files changed

+79
-4
lines changed

drivers/overlay/check.go

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"path/filepath"
1111
"syscall"
1212

13+
"github.com/containers/storage/pkg/ioutils"
14+
"github.com/containers/storage/pkg/mount"
1315
"github.com/containers/storage/pkg/system"
1416
"github.com/pkg/errors"
1517
"github.com/sirupsen/logrus"
@@ -57,10 +59,11 @@ func doesSupportNativeDiff(d, mountOpts string) error {
5759
}
5860

5961
opts := fmt.Sprintf("lowerdir=%s:%s,upperdir=%s,workdir=%s", path.Join(td, "l2"), path.Join(td, "l1"), path.Join(td, "l3"), path.Join(td, "work"))
60-
if mountOpts != "" {
61-
opts = fmt.Sprintf("%s,%s", opts, mountOpts)
62+
flags, data := mount.ParseOptions(mountOpts)
63+
if data != "" {
64+
opts = fmt.Sprintf("%s,%s", opts, data)
6265
}
63-
if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", 0, opts); err != nil {
66+
if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", uintptr(flags), opts); err != nil {
6467
return errors.Wrap(err, "failed to mount overlay")
6568
}
6669
defer func() {
@@ -103,3 +106,60 @@ func doesSupportNativeDiff(d, mountOpts string) error {
103106

104107
return nil
105108
}
109+
110+
// doesMetacopy checks if the filesystem is going to optimize changes to
111+
// metadata by using nodes marked with an "overlay.metacopy" attribute to avoid
112+
// copying up a file from a lower layer unless/until its contents are being
113+
// modified
114+
func doesMetacopy(d, mountOpts string) (bool, error) {
115+
td, err := ioutil.TempDir(d, "metacopy-check")
116+
if err != nil {
117+
return false, err
118+
}
119+
defer func() {
120+
if err := os.RemoveAll(td); err != nil {
121+
logrus.Warnf("Failed to remove check directory %v: %v", td, err)
122+
}
123+
}()
124+
125+
// Make directories l1, l2, work, merged
126+
if err := os.MkdirAll(filepath.Join(td, "l1"), 0755); err != nil {
127+
return false, err
128+
}
129+
if err := ioutils.AtomicWriteFile(filepath.Join(td, "l1", "f"), []byte{0xff}, 0700); err != nil {
130+
return false, err
131+
}
132+
if err := os.MkdirAll(filepath.Join(td, "l2"), 0755); err != nil {
133+
return false, err
134+
}
135+
if err := os.Mkdir(filepath.Join(td, "work"), 0755); err != nil {
136+
return false, err
137+
}
138+
if err := os.Mkdir(filepath.Join(td, "merged"), 0755); err != nil {
139+
return false, err
140+
}
141+
// Mount using the mandatory options and configured options
142+
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", path.Join(td, "l1"), path.Join(td, "l2"), path.Join(td, "work"))
143+
flags, data := mount.ParseOptions(mountOpts)
144+
if data != "" {
145+
opts = fmt.Sprintf("%s,%s", opts, data)
146+
}
147+
if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", uintptr(flags), opts); err != nil {
148+
return false, errors.Wrap(err, "failed to mount overlay for metacopy check")
149+
}
150+
defer func() {
151+
if err := unix.Unmount(filepath.Join(td, "merged"), 0); err != nil {
152+
logrus.Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err)
153+
}
154+
}()
155+
// Make a change that only impacts the inode, and check if the pulled-up copy is marked
156+
// as a metadata-only copy
157+
if err := os.Chmod(filepath.Join(td, "merged", "f"), 0600); err != nil {
158+
return false, errors.Wrap(err, "error changing permissions on file for metacopy check")
159+
}
160+
metacopy, err := system.Lgetxattr(filepath.Join(td, "l2", "f"), "trusted.overlay.metacopy")
161+
if err != nil {
162+
return false, errors.Wrap(err, "metacopy flag was not set on file in upper layer")
163+
}
164+
return metacopy != nil, nil
165+
}

drivers/overlay/overlay.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ type Driver struct {
105105
options overlayOptions
106106
naiveDiff graphdriver.DiffDriver
107107
supportsDType bool
108+
usingMetacopy bool
108109
locker *locker.Locker
109110
convert map[string]bool
110111
}
@@ -174,6 +175,18 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
174175
}
175176
}
176177

178+
usingMetacopy, err := doesMetacopy(home, opts.mountOptions)
179+
if err == nil {
180+
if usingMetacopy {
181+
logrus.Debugf("overlay test mount indicated that metacopy is being used")
182+
} else {
183+
logrus.Debugf("overlay test mount indicated that metacopy is not being used")
184+
}
185+
} else {
186+
logrus.Warnf("overlay test mount did not indicate whether or not metacopy is being used: %v", err)
187+
return nil, err
188+
}
189+
177190
if !opts.skipMountHome {
178191
if err := mount.MakePrivate(home); err != nil {
179192
return nil, err
@@ -193,6 +206,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
193206
gidMaps: gidMaps,
194207
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
195208
supportsDType: supportsDType,
209+
usingMetacopy: usingMetacopy,
196210
locker: locker.New(),
197211
options: *opts,
198212
convert: make(map[string]bool),
@@ -212,7 +226,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
212226
return nil, fmt.Errorf("Storage option overlay.size only supported for backingFS XFS. Found %v", backingFs)
213227
}
214228

215-
logrus.Debugf("backingFs=%s, projectQuotaSupported=%v, useNativeDiff=%v", backingFs, projectQuotaSupported, !d.useNaiveDiff())
229+
logrus.Debugf("backingFs=%s, projectQuotaSupported=%v, useNativeDiff=%v, usingMetacopy=%v", backingFs, projectQuotaSupported, !d.useNaiveDiff(), d.usingMetacopy)
216230

217231
return d, nil
218232
}
@@ -375,6 +389,7 @@ func (d *Driver) Status() [][2]string {
375389
{"Backing Filesystem", backingFs},
376390
{"Supports d_type", strconv.FormatBool(d.supportsDType)},
377391
{"Native Overlay Diff", strconv.FormatBool(!d.useNaiveDiff())},
392+
{"Using metacopy", strconv.FormatBool(d.usingMetacopy)},
378393
}
379394
}
380395

0 commit comments

Comments
 (0)