From 292145303fab26addb46ccf34943950a6c0507ff Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Wed, 2 Sep 2026 21:36:40 -0700 Subject: [PATCH] mount: name the disk without changing what is mounted (#11114) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mount: name the disk after the mount point when the whole tree is mounted The mounted path was the only thing that named the disk, so a mount of the whole tree was labelled with the filer address and the only way to give it a name was to mount a subtree under that name — which hides everything outside it. Fall back to the mount point's own name first, so -dir=\\seaweedfs\Images labels the disk while -filer.path stays "/". Claude-Session: https://claude.ai/code/session_01Q9f8pWBXu1ceJvcQfYRQ7x --- weed/command/mount.go | 4 +++- weed/command/mount_common.go | 23 +++++++++++++++----- weed/command/mount_common_test.go | 36 ++++++++++++++++++++++++++++--- weed/command/mount_std.go | 2 +- weed/command/mount_windows.go | 2 +- 5 files changed, 56 insertions(+), 11 deletions(-) diff --git a/weed/command/mount.go b/weed/command/mount.go index c42dfcdcf..1cac8613e 100644 --- a/weed/command/mount.go +++ b/weed/command/mount.go @@ -201,7 +201,9 @@ var cmdMount = &Command{ Where the platform labels the disk, in Finder and in Explorer, the mounted path names it: -filer.path="/Image Disk" shows up as "Image Disk". Mounting - the whole tree labels it with the filer address instead. + the whole tree takes the name from the mount point instead, so + -dir=\\seaweedfs\Images labels the disk "Images" while still mounting + everything, and only a bare drive letter falls back to the filer address. RDMA Acceleration: For ultra-fast reads, enable RDMA acceleration with an RDMA sidecar: diff --git a/weed/command/mount_common.go b/weed/command/mount_common.go index c61912955..4c2ce7e2a 100644 --- a/weed/command/mount_common.go +++ b/weed/command/mount_common.go @@ -285,12 +285,25 @@ func resolveCacheDirs(option *MountOptions) (string, string) { } // volumeName labels the mount where the platform shows one, in Finder and in -// Explorer. The mounted path names the disk; the filer address, which every -// mount from one filer shares, is only the whole-tree fallback. -func volumeName(filer, filerMountRootPath string) string { - name := path.Base(filerMountRootPath) - if name == "/" || name == "." { +// Explorer. The mounted path names the disk, then the mount point; the filer +// address, which every mount from one filer shares, is the last resort. +func volumeName(filer, filerMountRootPath, dir string) string { + name := lastSegment(filerMountRootPath) + if name == "" { + name = lastSegment(dir) + } + if name == "" { name = filer } return strings.ReplaceAll(name, ",", "+") } + +// lastSegment is the name a path ends with, and "" for the ones that name no +// disk: the root, "." and a bare Windows drive letter. +func lastSegment(p string) string { + name := path.Base(strings.ReplaceAll(p, `\`, "/")) + if name == "/" || name == "." || strings.HasSuffix(name, ":") { + return "" + } + return name +} diff --git a/weed/command/mount_common_test.go b/weed/command/mount_common_test.go index b5b3226b7..a2982d4c9 100644 --- a/weed/command/mount_common_test.go +++ b/weed/command/mount_common_test.go @@ -9,12 +9,14 @@ func Test_volumeName(t *testing.T) { name string filer string filerMountRootPath string + dir string expected string }{ { - name: "whole tree falls back to the filer", + name: "a drive letter leaves only the filer to fall back on", filer: "127.0.0.1:8888", filerMountRootPath: "/", + dir: "S:", expected: "127.0.0.1:8888", }, { @@ -29,6 +31,34 @@ func Test_volumeName(t *testing.T) { filerMountRootPath: "/", expected: "127.0.0.1:8888+127.0.0.1:8889", }, + { + name: "a whole-tree mount takes the name of its network share", + filer: "127.0.0.1:8888", + filerMountRootPath: "/", + dir: `\\seaweedfs\Images`, + expected: "Images", + }, + { + name: "a whole-tree mount takes the name of its directory", + filer: "127.0.0.1:8888", + filerMountRootPath: "/", + dir: "/mnt/seaweedfs", + expected: "seaweedfs", + }, + { + name: "the mounted path outranks the mount point", + filer: "127.0.0.1:8888", + filerMountRootPath: "/buckets/videos", + dir: "/mnt/seaweedfs", + expected: "videos", + }, + { + name: "a relative mount point is not a name", + filer: "127.0.0.1:8888", + filerMountRootPath: "/", + dir: ".", + expected: "127.0.0.1:8888", + }, { name: "mounted directory names the disk", filer: "127.0.0.1:8888", @@ -50,8 +80,8 @@ func Test_volumeName(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := volumeName(tt.filer, tt.filerMountRootPath); got != tt.expected { - t.Errorf("volumeName(%q, %q) = %q, want %q", tt.filer, tt.filerMountRootPath, got, tt.expected) + if got := volumeName(tt.filer, tt.filerMountRootPath, tt.dir); got != tt.expected { + t.Errorf("volumeName(%q, %q, %q) = %q, want %q", tt.filer, tt.filerMountRootPath, tt.dir, got, tt.expected) } }) } diff --git a/weed/command/mount_std.go b/weed/command/mount_std.go index f29c51ddd..80e61f979 100644 --- a/weed/command/mount_std.go +++ b/weed/command/mount_std.go @@ -179,7 +179,7 @@ func RunMount(option *MountOptions, umask os.FileMode) bool { fuseMountOptions.Options = append(fuseMountOptions.Options, "novncache") } fuseMountOptions.Options = append(fuseMountOptions.Options, "slow_statfs") - fuseMountOptions.Options = append(fuseMountOptions.Options, "volname="+volumeName(*option.filer, filerMountRootPath)) + fuseMountOptions.Options = append(fuseMountOptions.Options, "volname="+volumeName(*option.filer, filerMountRootPath, dir)) fuseMountOptions.Options = append(fuseMountOptions.Options, fmt.Sprintf("iosize=%d", ioSizeMB*1024*1024)) } // Last, so an option given on the command line wins over the default diff --git a/weed/command/mount_windows.go b/weed/command/mount_windows.go index e32019f2e..316ad6736 100644 --- a/weed/command/mount_windows.go +++ b/weed/command/mount_windows.go @@ -104,7 +104,7 @@ func RunMount(option *MountOptions, umask os.FileMode) bool { } host := winfsp.New(seaweedFileSystem, winfsp.Options{ - VolumeName: volumeName(*option.filer, *option.filerMountRootPath), + VolumeName: volumeName(*option.filer, *option.filerMountRootPath, dir), Uid: ownedByMounter, Gid: ownedByMounter, CacheTimeout: windowsCacheTimeout,