Skip to content

Commit 8cd40e1

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 453fa39 commit 8cd40e1

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
@@ -45,6 +45,7 @@ const upperdirKey = "containerd.io/snapshot/overlay.upperdir"
4545
type SnapshotterConfig struct {
4646
asyncRemove bool
4747
upperdirLabel bool
48+
mountOptions []string
4849
}
4950

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

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

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

115134
return &snapshotter{
116135
root: root,
117136
ms: ms,
118137
asyncRemove: config.asyncRemove,
119138
upperdirLabel: config.upperdirLabel,
120-
indexOff: supportsIndex(),
121-
userxattr: userxattr,
139+
options: config.mountOptions,
122140
}, nil
123141
}
124142

143+
func hasOption(options []string, key string, hasValue bool) bool {
144+
for _, option := range options {
145+
if hasValue {
146+
if strings.HasPrefix(option, key) && len(option) > len(key) && option[len(key)] == '=' {
147+
return true
148+
}
149+
} else if option == key {
150+
return true
151+
}
152+
}
153+
return false
154+
}
155+
125156
// Stat returns the info for an active or committed snapshot by name or
126157
// key.
127158
//
@@ -507,17 +538,8 @@ func (o *snapshotter) mounts(s storage.Snapshot) []mount.Mount {
507538
},
508539
}
509540
}
510-
var options []string
511-
512-
// set index=off when mount overlayfs
513-
if o.indexOff {
514-
options = append(options, "index=off")
515-
}
516-
517-
if o.userxattr {
518-
options = append(options, "userxattr")
519-
}
520541

542+
options := o.options
521543
if s.Kind == snapshots.KindActive {
522544
options = append(options,
523545
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
@@ -71,7 +71,7 @@ func TestOverlay(t *testing.T) {
7171
testOverlayOverlayRead(t, newSnapshotter)
7272
})
7373
t.Run("TestOverlayView", func(t *testing.T) {
74-
testOverlayView(t, newSnapshotter)
74+
testOverlayView(t, newSnapshotterWithOpts(append(opts, WithMountOptions([]string{"volatile"}))...))
7575
})
7676
})
7777
}
@@ -330,7 +330,7 @@ func testOverlayView(t *testing.T, newSnapshotter testsuite.SnapshotterFunc) {
330330
}
331331

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

snapshots/overlay/plugin/plugin.go

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

3841
func init() {
@@ -61,6 +64,10 @@ func init() {
6164
oOpts = append(oOpts, overlay.AsynchronousRemove)
6265
}
6366

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

0 commit comments

Comments
 (0)