mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-08 15:41:15 +02:00
mount: add -volumeName to name the disk explicitly (#11165)
* mount: let volumeName take an explicit override volumeName only ever derived the disk's label from -filer.path, -dir, or the filer address, so a name that happened to collide with something else - e.g. a UNC share's own name - could not be changed without moving what was mounted. Give it an override parameter that wins over all three; nothing passes one yet. * mount: add -volumeName to name the disk explicitly Windows has no equivalent of the "weed fuse" -o passthrough that lets a Linux or macOS mount override its derived volname, so a name picked up from -dir - e.g. a UNC share's own name - could not be changed short of moving what was mounted. -volumeName overrides it on every platform. * mount: document -volumeName * mount: scope -volumeName's help text to macOS and Windows Linux has no volume-label mount option for -volumeName to feed, so the flag's own description says where it applies instead of leaving that unstated. * mount: forward -volumeName through the weed fuse option parser weed fuse (the /etc/fstab helper) turns -o key=value into the same MountOptions weed mount takes, but volumeName had no case, so it fell through to being forwarded as a literal, unrecognized FUSE option instead of ever reaching mountOptions.volumeName. * mount: apply -volumeName to FsName on Linux and FreeBSD FsName only ever took the filer address and -filer.path, so -volumeName had nothing to override there and silently did nothing; the skipAutofs case still forces "fuse", since that name is what util-linux/mount requires to recognize the pseudo filesystem.
This commit is contained in:
@@ -124,6 +124,8 @@ func runFuse(cmd *Command, args []string) bool {
|
||||
mountOptions.filer = ¶meter.value
|
||||
case "filer.path":
|
||||
mountOptions.filerMountRootPath = ¶meter.value
|
||||
case "volumeName":
|
||||
mountOptions.volumeName = ¶meter.value
|
||||
case "dirAutoCreate":
|
||||
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
||||
mountOptions.dirAutoCreate = &parsed
|
||||
|
||||
@@ -36,3 +36,32 @@ func TestRunFuseDoesNotSkipOptionAfterConcurrentWriters(t *testing.T) {
|
||||
"child=1,concurrentWriters=2,concurrentReaders=bad,umask=bad",
|
||||
})
|
||||
}
|
||||
|
||||
func TestRunFuseSetsVolumeName(t *testing.T) {
|
||||
oldVolumeName := mountOptions.volumeName
|
||||
oldConcurrentReaders := mountOptions.concurrentReaders
|
||||
oldDir := mountOptions.dir
|
||||
defer func() {
|
||||
gotVolumeName := mountOptions.volumeName
|
||||
mountOptions.volumeName = oldVolumeName
|
||||
mountOptions.concurrentReaders = oldConcurrentReaders
|
||||
mountOptions.dir = oldDir
|
||||
|
||||
recovered := recover()
|
||||
if recovered == nil {
|
||||
t.Fatal("expected invalid concurrentReaders option to be parsed")
|
||||
}
|
||||
if gotVolumeName == nil {
|
||||
t.Fatal("expected -o volumeName=MyDisk to set mountOptions.volumeName, got nil")
|
||||
}
|
||||
if *gotVolumeName != "MyDisk" {
|
||||
t.Fatalf("expected -o volumeName=MyDisk to set mountOptions.volumeName, got %q", *gotVolumeName)
|
||||
}
|
||||
}()
|
||||
|
||||
runFuse(cmdMount, []string{
|
||||
"/mnt",
|
||||
"-o",
|
||||
"volumeName=MyDisk,concurrentReaders=bad",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ type MountOptions struct {
|
||||
filer *string
|
||||
filerMountRootPath *string
|
||||
dir *string
|
||||
volumeName *string
|
||||
dirAutoCreate *bool
|
||||
collection *string
|
||||
collectionQuota *int
|
||||
@@ -92,6 +93,7 @@ func init() {
|
||||
mountOptions.filer = cmdMount.Flag.String("filer", "localhost:8888", "comma-separated weed filer location")
|
||||
mountOptions.filerMountRootPath = cmdMount.Flag.String("filer.path", "/", "mount this remote path from filer server")
|
||||
mountOptions.dir = cmdMount.Flag.String("dir", ".", "mount weed filer to this directory")
|
||||
mountOptions.volumeName = cmdMount.Flag.String("volumeName", "", "name the mount shown by the platform (Finder/Explorer, or \"mount\"/\"df\" on Linux and FreeBSD), overriding the name taken from -filer.path or -dir")
|
||||
mountOptions.dirAutoCreate = cmdMount.Flag.Bool("dirAutoCreate", false, "auto create the directory to mount to")
|
||||
mountOptions.collection = cmdMount.Flag.String("collection", "", "collection to create the files")
|
||||
mountOptions.collectionQuota = cmdMount.Flag.Int("collectionQuotaMB", 0, "quota for the collection")
|
||||
@@ -188,6 +190,8 @@ var cmdMount = &Command{
|
||||
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.
|
||||
-volumeName overrides whatever name either of those would otherwise give it,
|
||||
including what Linux and FreeBSD show for the mount in "mount" and "df".
|
||||
|
||||
`,
|
||||
}
|
||||
|
||||
@@ -278,10 +278,14 @@ 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, 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)
|
||||
// Explorer. An explicit override always wins; failing that, 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, override string) string {
|
||||
name := override
|
||||
if name == "" {
|
||||
name = lastSegment(filerMountRootPath)
|
||||
}
|
||||
if name == "" {
|
||||
name = lastSegment(dir)
|
||||
}
|
||||
|
||||
@@ -10,8 +10,24 @@ func Test_volumeName(t *testing.T) {
|
||||
filer string
|
||||
filerMountRootPath string
|
||||
dir string
|
||||
override string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "an override outranks the mounted path and the mount point",
|
||||
filer: "127.0.0.1:8888",
|
||||
filerMountRootPath: "/buckets/videos",
|
||||
dir: `\\seaweedfs\Images`,
|
||||
override: "MyDisk",
|
||||
expected: "MyDisk",
|
||||
},
|
||||
{
|
||||
name: "an override still gets commas replaced",
|
||||
filer: "127.0.0.1:8888",
|
||||
filerMountRootPath: "/",
|
||||
override: "My, Disk",
|
||||
expected: "My+ Disk",
|
||||
},
|
||||
{
|
||||
name: "a drive letter leaves only the filer to fall back on",
|
||||
filer: "127.0.0.1:8888",
|
||||
@@ -80,8 +96,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, tt.dir); got != tt.expected {
|
||||
t.Errorf("volumeName(%q, %q, %q) = %q, want %q", tt.filer, tt.filerMountRootPath, tt.dir, got, tt.expected)
|
||||
if got := volumeName(tt.filer, tt.filerMountRootPath, tt.dir, tt.override); got != tt.expected {
|
||||
t.Errorf("volumeName(%q, %q, %q, %q) = %q, want %q", tt.filer, tt.filerMountRootPath, tt.dir, tt.override, got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -118,6 +118,9 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
|
||||
// When autofs/systemd-mount is used, FsName must be "fuse" so util-linux/mount can recognize
|
||||
// it as a pseudo filesystem. Otherwise, preserve the descriptive name for mount/df output.
|
||||
fsName := serverFriendlyName + ":" + filerMountRootPath
|
||||
if *option.volumeName != "" {
|
||||
fsName = *option.volumeName
|
||||
}
|
||||
if skipAutofs {
|
||||
fsName = "fuse"
|
||||
}
|
||||
@@ -179,7 +182,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, dir))
|
||||
fuseMountOptions.Options = append(fuseMountOptions.Options, "volname="+volumeName(*option.filer, filerMountRootPath, dir, *option.volumeName))
|
||||
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
|
||||
|
||||
@@ -104,7 +104,7 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
|
||||
}
|
||||
|
||||
host := winfsp.New(seaweedFileSystem, winfsp.Options{
|
||||
VolumeName: volumeName(*option.filer, *option.filerMountRootPath, dir),
|
||||
VolumeName: volumeName(*option.filer, *option.filerMountRootPath, dir, *option.volumeName),
|
||||
Uid: ownedByMounter,
|
||||
Gid: ownedByMounter,
|
||||
CacheTimeout: windowsCacheTimeout,
|
||||
|
||||
Reference in New Issue
Block a user