mountlib: fix VFS instance leaks on mount failures and unmounts

This commit is contained in:
Hakan İSMAİL
2026-08-18 09:03:12 +01:00
committed by Nick Craig-Wood
parent f425f8d466
commit 45ddf3a5f2
5 changed files with 27 additions and 19 deletions
-2
View File
@@ -170,8 +170,6 @@ func mount(VFS *vfs.VFS, mountPath string, opt *mountlib.Options) (<-chan error,
// unmount // unmount
unmount := func() error { unmount := func() error {
// Shutdown the VFS
fsys.VFS.Shutdown()
var umountOK bool var umountOK bool
if fsys.destroyed.Load() != 0 { if fsys.destroyed.Load() != 0 {
fs.Debugf(nil, "Not calling host.Unmount as mount already Destroyed") fs.Debugf(nil, "Not calling host.Unmount as mount already Destroyed")
-2
View File
@@ -103,8 +103,6 @@ func mount(VFS *vfs.VFS, mountpoint string, opt *mountlib.Options) (<-chan error
}() }()
unmount := func() error { unmount := func() error {
// Shutdown the VFS
filesys.VFS.Shutdown()
return fuse.Unmount(mountpoint) return fuse.Unmount(mountpoint)
} }
-2
View File
@@ -241,8 +241,6 @@ func mount(VFS *vfs.VFS, mountpoint string, opt *mountlib.Options) (<-chan error
// } // }
umount := func() error { umount := func() error {
// Shutdown the VFS
fsys.VFS.Shutdown()
return server.Unmount() return server.Unmount()
} }
+16
View File
@@ -220,6 +220,16 @@ type MountPoint struct {
MountFn MountFn MountFn MountFn
UnmountFn UnmountFn UnmountFn UnmountFn
ErrChan <-chan error ErrChan <-chan error
vfsShutdownOnce sync.Once
}
// shutdownVFS shuts down the VFS instance exactly once
func (m *MountPoint) shutdownVFS() {
m.vfsShutdownOnce.Do(func() {
if m.VFS != nil {
m.VFS.Shutdown()
}
})
} }
// NewMountPoint makes a new mounting structure // NewMountPoint makes a new mounting structure
@@ -386,6 +396,7 @@ func (m *MountPoint) Mount() (mountDaemon *os.Process, err error) {
var actualMountpoint string var actualMountpoint string
m.ErrChan, m.UnmountFn, actualMountpoint, err = m.MountFn(m.VFS, m.MountPoint, &m.MountOpt) m.ErrChan, m.UnmountFn, actualMountpoint, err = m.MountFn(m.VFS, m.MountPoint, &m.MountOpt)
if err != nil { if err != nil {
m.shutdownVFS()
if len(os.Args) > 0 && strings.HasPrefix(os.Args[0], "/snap/") { if len(os.Args) > 0 && strings.HasPrefix(os.Args[0], "/snap/") {
return nil, fmt.Errorf("mounting is not supported when running from snap") return nil, fmt.Errorf("mounting is not supported when running from snap")
} }
@@ -404,6 +415,7 @@ func (m *MountPoint) Wait() error {
var finaliseOnce sync.Once var finaliseOnce sync.Once
finalise := func() { finalise := func() {
finaliseOnce.Do(func() { finaliseOnce.Do(func() {
defer m.shutdownVFS()
// Unmount only if directory was mounted by rclone, e.g. don't unmount autofs hooks. // Unmount only if directory was mounted by rclone, e.g. don't unmount autofs hooks.
if err := CheckMountReady(m.MountPoint); err != nil { if err := CheckMountReady(m.MountPoint); err != nil {
fs.Debugf(m.MountPoint, "Unmounted externally. Just exit now.") fs.Debugf(m.MountPoint, "Unmounted externally. Just exit now.")
@@ -431,5 +443,9 @@ func (m *MountPoint) Wait() error {
// Unmount the specified mountpoint // Unmount the specified mountpoint
func (m *MountPoint) Unmount() (err error) { func (m *MountPoint) Unmount() (err error) {
defer m.shutdownVFS()
if m.UnmountFn != nil {
return m.UnmountFn() return m.UnmountFn()
} }
return nil
}
-2
View File
@@ -117,7 +117,6 @@ func mount(VFS *vfs.VFS, mountpoint string, opt *mountlib.Options) (asyncerrors
out, umountErr = exec.Command(cmd[0], cmd[1:]...).CombinedOutput() out, umountErr = exec.Command(cmd[0], cmd[1:]...).CombinedOutput()
} }
shutdownErr := s.Shutdown() shutdownErr := s.Shutdown()
VFS.Shutdown()
if umountErr != nil { if umountErr != nil {
out = bytes.TrimSpace(out) out = bytes.TrimSpace(out)
return fmt.Errorf("%s: failed to umount the NFS volume %e", out, umountErr) return fmt.Errorf("%s: failed to umount the NFS volume %e", out, umountErr)
@@ -130,7 +129,6 @@ func mount(VFS *vfs.VFS, mountpoint string, opt *mountlib.Options) (asyncerrors
nfs.OnUnmountFunc = func() { nfs.OnUnmountFunc = func() {
s.UnmountedExternally = true s.UnmountedExternally = true
errChan <- nil errChan <- nil
VFS.Shutdown()
} }
actualMountpoint = mountpoint actualMountpoint = mountpoint