Skip to content

Commit 0f4885c

Browse files
dmcgowanfuweid
authored andcommitted
Add configurable mount options to overlay
Allows default mount options to be provided through configuration. Signed-off-by: Derek McGowan <[email protected]> (cherry picked from commit d115129) Signed-off-by: Wei Fu <[email protected]>
1 parent 8804a27 commit 0f4885c

3 files changed

Lines changed: 53 additions & 21 deletions

File tree

snapshots/overlay/overlay.go

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const upperdirKey = "containerd.io/snapshot/overlay.upperdir"
4444
type SnapshotterConfig struct {
4545
asyncRemove bool
4646
upperdirLabel bool
47+
mountOptions []string
4748
}
4849

4950
// Opt is an option to configure the overlay snapshotter
@@ -67,13 +68,21 @@ func WithUpperdirLabel(config *SnapshotterConfig) error {
6768
return nil
6869
}
6970

71+
// WithMountOptions defines the default mount options used for the overlay mount.
72+
// NOTE: Options are not applied to bind mounts.
73+
func WithMountOptions(options []string) Opt {
74+
return func(config *SnapshotterConfig) error {
75+
config.mountOptions = append(config.mountOptions, options...)
76+
return nil
77+
}
78+
}
79+
7080
type snapshotter struct {
7181
root string
7282
ms *storage.MetaStore
7383
asyncRemove bool
7484
upperdirLabel bool
75-
indexOff bool
76-
userxattr bool // whether to enable "userxattr" mount option
85+
options []string
7786
}
7887

7988
// NewSnapshotter returns a Snapshotter which uses overlayfs. The overlayfs
@@ -105,22 +114,44 @@ func NewSnapshotter(root string, opts ...Opt) (snapshots.Snapshotter, error) {
105114
if err := os.Mkdir(filepath.Join(root, "snapshots"), 0700); err != nil && !os.IsExist(err) {
106115
return nil, err
107116
}
108-
// figure out whether "userxattr" option is recognized by the kernel && needed
109-
userxattr, err := overlayutils.NeedsUserXAttr(root)
110-
if err != nil {
111-
logrus.WithError(err).Warnf("cannot detect whether \"userxattr\" option needs to be used, assuming to be %v", userxattr)
117+
118+
if !hasOption(config.mountOptions, "userxattr", false) {
119+
// figure out whether "userxattr" option is recognized by the kernel && needed
120+
userxattr, err := overlayutils.NeedsUserXAttr(root)
121+
if err != nil {
122+
logrus.WithError(err).Warnf("cannot detect whether \"userxattr\" option needs to be used, assuming to be %v", userxattr)
123+
}
124+
if userxattr {
125+
config.mountOptions = append(config.mountOptions, "userxattr")
126+
}
127+
}
128+
129+
if !hasOption(config.mountOptions, "index", false) && supportsIndex() {
130+
config.mountOptions = append(config.mountOptions, "index=off")
112131
}
113132

114133
return &snapshotter{
115134
root: root,
116135
ms: ms,
117136
asyncRemove: config.asyncRemove,
118137
upperdirLabel: config.upperdirLabel,
119-
indexOff: supportsIndex(),
120-
userxattr: userxattr,
138+
options: config.mountOptions,
121139
}, nil
122140
}
123141

142+
func hasOption(options []string, key string, hasValue bool) bool {
143+
for _, option := range options {
144+
if hasValue {
145+
if strings.HasPrefix(option, key) && len(option) > len(key) && option[len(key)] == '=' {
146+
return true
147+
}
148+
} else if option == key {
149+
return true
150+
}
151+
}
152+
return false
153+
}
154+
124155
// Stat returns the info for an active or committed snapshot by name or
125156
// key.
126157
//
@@ -453,17 +484,8 @@ func (o *snapshotter) mounts(s storage.Snapshot) []mount.Mount {
453484
},
454485
}
455486
}
456-
var options []string
457-
458-
// set index=off when mount overlayfs
459-
if o.indexOff {
460-
options = append(options, "index=off")
461-
}
462-
463-
if o.userxattr {
464-
options = append(options, "userxattr")
465-
}
466487

488+
options := o.options
467489
if s.Kind == snapshots.KindActive {
468490
options = append(options,
469491
fmt.Sprintf("workdir=%s", o.workPath(s.ID)),

snapshots/overlay/overlay_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func TestOverlay(t *testing.T) {
7070
testOverlayOverlayRead(t, newSnapshotter)
7171
})
7272
t.Run("TestOverlayView", func(t *testing.T) {
73-
testOverlayView(t, newSnapshotter)
73+
testOverlayView(t, newSnapshotterWithOpts(append(opts, WithMountOptions([]string{"volatile"}))...))
7474
})
7575
})
7676
}
@@ -329,7 +329,7 @@ func testOverlayView(t *testing.T, newSnapshotter testsuite.SnapshotterFunc) {
329329
}
330330

331331
supportsIndex := supportsIndex()
332-
expectedOptions := 2
332+
expectedOptions := 3
333333
if !supportsIndex {
334334
expectedOptions--
335335
}
@@ -346,13 +346,16 @@ func testOverlayView(t *testing.T, newSnapshotter testsuite.SnapshotterFunc) {
346346
}
347347
lowers := getParents(ctx, o, root, "/tmp/view2")
348348
expected = fmt.Sprintf("lowerdir=%s:%s", lowers[0], lowers[1])
349-
optIdx := 1
349+
optIdx := 2
350350
if !supportsIndex {
351351
optIdx--
352352
}
353353
if userxattr {
354354
optIdx++
355355
}
356+
if m.Options[0] != "volatile" {
357+
t.Error("expected option first option to be provided option \"volatile\"")
358+
}
356359
if m.Options[optIdx] != expected {
357360
t.Errorf("expected option %q but received %q", expected, m.Options[optIdx])
358361
}

snapshots/overlay/plugin/plugin.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ type Config struct {
3232
RootPath string `toml:"root_path"`
3333
UpperdirLabel bool `toml:"upperdir_label"`
3434
SyncRemove bool `toml:"sync_remove"`
35+
36+
// MountOptions are options used for the overlay mount (not used on bind mounts)
37+
MountOptions []string `toml:"mount_options"`
3538
}
3639

3740
func init() {
@@ -60,6 +63,10 @@ func init() {
6063
oOpts = append(oOpts, overlay.AsynchronousRemove)
6164
}
6265

66+
if len(config.MountOptions) > 0 {
67+
oOpts = append(oOpts, overlay.WithMountOptions(config.MountOptions))
68+
}
69+
6370
ic.Meta.Exports["root"] = root
6471
return overlay.NewSnapshotter(root, oOpts...)
6572
},

0 commit comments

Comments
 (0)