From 3bf3d290581f23a55515367ba8444e9c9d8ba9af Mon Sep 17 00:00:00 2001 From: 7y-9 Date: Tue, 16 Jun 2026 04:11:35 +0800 Subject: [PATCH] fix(command): preserve fuse option after writers (#9972) * fix(command): preserve fuse option after writers Problem: FUSE mount option parsing skipped the option immediately following concurrentWriters, so values such as concurrentReaders could be silently ignored. Root cause: runFuse incremented the options loop index inside the concurrentWriters case in addition to the loop increment. Co-authored-by: Codex * test: save and restore mountOptions pointers, not their values The fields are reassigned to fresh heap variables during runFuse, so dereferencing to back up/restore mutated throwaways instead of the flag-bound originals and could nil-panic on unset fields. --------- Co-authored-by: Codex Co-authored-by: Chris Lu --- weed/command/fuse_std.go | 1 - weed/command/fuse_std_test.go | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 weed/command/fuse_std_test.go diff --git a/weed/command/fuse_std.go b/weed/command/fuse_std.go index 2e4c88f87..1eb4ee072 100644 --- a/weed/command/fuse_std.go +++ b/weed/command/fuse_std.go @@ -165,7 +165,6 @@ func runFuse(cmd *Command, args []string) bool { panic(fmt.Errorf("dirIdleEvictSec: %s", err)) } case "concurrentWriters": - i++ if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil { intValue := int(parsed) mountOptions.concurrentWriters = &intValue diff --git a/weed/command/fuse_std_test.go b/weed/command/fuse_std_test.go new file mode 100644 index 000000000..64122bb3c --- /dev/null +++ b/weed/command/fuse_std_test.go @@ -0,0 +1,38 @@ +//go:build darwin || freebsd || linux + +package command + +import ( + "fmt" + "strings" + "testing" +) + +func TestRunFuseDoesNotSkipOptionAfterConcurrentWriters(t *testing.T) { + oldUmask := mountOptions.umaskString + oldWriters := mountOptions.concurrentWriters + oldReaders := mountOptions.concurrentReaders + oldFuseCommandPid := mountOptions.fuseCommandPid + oldDir := mountOptions.dir + defer func() { + mountOptions.umaskString = oldUmask + mountOptions.concurrentWriters = oldWriters + mountOptions.concurrentReaders = oldReaders + mountOptions.fuseCommandPid = oldFuseCommandPid + mountOptions.dir = oldDir + + recovered := recover() + if recovered == nil { + t.Fatal("expected invalid concurrentReaders option to be parsed") + } + if !strings.Contains(fmt.Sprint(recovered), "concurrentReaders") { + t.Fatalf("expected concurrentReaders parse error, got %v", recovered) + } + }() + + runFuse(cmdMount, []string{ + "/mnt", + "-o", + "child=1,concurrentWriters=2,concurrentReaders=bad,umask=bad", + }) +}