Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions plugins/snapshots/overlay/overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func NewSnapshotter(root string, opts ...Opt) (snapshots.Snapshotter, error) {
return nil, err
}

if !hasOption(config.mountOptions, "userxattr", false) {
if !hasOption(config.mountOptions, "userxattr") {
// figure out whether "userxattr" option is recognized by the kernel && needed
userxattr, err := overlayutils.NeedsUserXAttr(root)
if err != nil {
Expand All @@ -158,7 +158,9 @@ func NewSnapshotter(root string, opts ...Opt) (snapshots.Snapshotter, error) {
}
}

if !hasOption(config.mountOptions, "index", false) && supportsIndex() {
// Mount options are last-wins in the kernel, so appending "index=off"
// after a configured "index=on" would silently override it.
if !hasOption(config.mountOptions, "index") && supportsIndex() {
config.mountOptions = append(config.mountOptions, "index=off")
}

Expand All @@ -173,13 +175,14 @@ func NewSnapshotter(root string, opts ...Opt) (snapshots.Snapshotter, error) {
}, nil
}

func hasOption(options []string, key string, hasValue bool) bool {
// hasOption reports whether the "key" option is present in options, either
// as a bare flag ("userxattr") or in "key=value" form ("index=on").
func hasOption(options []string, key string) bool {
for _, option := range options {
if hasValue {
if strings.HasPrefix(option, key) && len(option) > len(key) && option[len(key)] == '=' {
return true
}
} else if option == key {
if option == key {
return true
}
if optionKey, _, ok := strings.Cut(option, "="); ok && optionKey == key {
return true
}
}
Expand Down
23 changes: 23 additions & 0 deletions plugins/snapshots/overlay/overlay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,29 @@ func newSnapshotterWithOpts(opts ...Opt) testsuite.SnapshotterFunc {
}
}

// NewSnapshotter must not auto-append "index=off" when the configuration
// already carries an index option: mount options are last-wins in the
// kernel, so the appended "index=off" would silently override a configured
// "index=on" — and combined with "nfs_export=on" it makes every overlay
// mount fail with EINVAL (nfs_export=on conflicts with an explicit
// index=off).
func TestOverlayConfiguredIndexNotOverridden(t *testing.T) {
if !supportsIndex() {
t.Skip("kernel does not expose the overlay index parameter")
}
sn, err := NewSnapshotter(t.TempDir(), WithMountOptions([]string{"index=on", "nfs_export=on"}))
if err != nil {
t.Fatal(err)
}
defer sn.Close()
options := sn.(*snapshotter).options
for _, opt := range options {
if opt == "index=off" {
t.Fatalf("configured index option overridden by auto-appended index=off (options: %v)", options)
}
}
}

func TestOverlay(t *testing.T) {
testutil.RequiresRoot(t)
optTestCases := map[string][]Opt{
Expand Down
Loading