mountlib: fix VFS instance leaks on mount failures and unmounts
This commit is contained in:
committed by
Nick Craig-Wood
parent
f425f8d466
commit
45ddf3a5f2
@@ -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")
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user