-idle: don't lazy-unmount
When a process has its working dir inside the mount, the only way we notice is that we get EBUSY when trying to unmount. We used to lazy-unmount in this case, but this means pulling the rug from under the process. For example, bash will start throwing cd: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory messages. Fixes https://github.com/rfjakob/gocryptfs/issues/533
This commit is contained in:
parent
c20c7992a0
commit
de108d3fc0
@ -241,6 +241,9 @@ Only for forward mode: automatically unmount the filesystem if it has been idle
|
|||||||
for the specified duration. Durations can be specified like "500s" or "2h45m".
|
for the specified duration. Durations can be specified like "500s" or "2h45m".
|
||||||
0 (the default) means stay mounted indefinitely.
|
0 (the default) means stay mounted indefinitely.
|
||||||
|
|
||||||
|
When a process has open files or its working directory in the mount,
|
||||||
|
this will keep it not idle indefinitely.
|
||||||
|
|
||||||
#### -kernel_cache
|
#### -kernel_cache
|
||||||
Enable the kernel_cache option of the FUSE filesystem, see fuse(8) for details.
|
Enable the kernel_cache option of the FUSE filesystem, see fuse(8) for details.
|
||||||
|
|
||||||
|
@ -192,6 +192,7 @@ Changelog
|
|||||||
|
|
||||||
vNEXT, in progress
|
vNEXT, in progress
|
||||||
* MANPAGE: Split options into sections acc. to where they apply ([#517](https://github.com/rfjakob/gocryptfs/issues/517))
|
* MANPAGE: Split options into sections acc. to where they apply ([#517](https://github.com/rfjakob/gocryptfs/issues/517))
|
||||||
|
* `-idle`: count cwd inside the mount as busy ([#533](https://github.com/rfjakob/gocryptfs/issues/533))
|
||||||
|
|
||||||
v2.0-beta2, 2020-11-14
|
v2.0-beta2, 2020-11-14
|
||||||
* Improve [performance](Documentation/performance.txt#L69)
|
* Improve [performance](Documentation/performance.txt#L69)
|
||||||
|
28
mount.go
28
mount.go
@ -175,11 +175,15 @@ func doMount(args *argContainer) {
|
|||||||
const checksDuringTimeoutPeriod = 4
|
const checksDuringTimeoutPeriod = 4
|
||||||
|
|
||||||
func idleMonitor(idleTimeout time.Duration, fs *fusefrontend.RootNode, srv *fuse.Server, mountpoint string) {
|
func idleMonitor(idleTimeout time.Duration, fs *fusefrontend.RootNode, srv *fuse.Server, mountpoint string) {
|
||||||
sleepTimeBetweenChecks := contentenc.MinUint64(
|
// sleepNs is the sleep time between checks, in nanoseconds.
|
||||||
|
sleepNs := contentenc.MinUint64(
|
||||||
uint64(idleTimeout/checksDuringTimeoutPeriod),
|
uint64(idleTimeout/checksDuringTimeoutPeriod),
|
||||||
uint64(2*time.Minute))
|
uint64(2*time.Minute))
|
||||||
timeoutCycles := int(math.Ceil(float64(idleTimeout) / float64(sleepTimeBetweenChecks)))
|
timeoutCycles := int(math.Ceil(float64(idleTimeout) / float64(sleepNs)))
|
||||||
idleCount := 0
|
idleCount := 0
|
||||||
|
idleTime := func() time.Duration {
|
||||||
|
return time.Duration(sleepNs * uint64(idleCount))
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
// Atomically check whether the flag is 0 and reset it to 1 if so.
|
// Atomically check whether the flag is 0 and reset it to 1 if so.
|
||||||
isIdle := !atomic.CompareAndSwapUint32(&fs.IsIdle, 0, 1)
|
isIdle := !atomic.CompareAndSwapUint32(&fs.IsIdle, 0, 1)
|
||||||
@ -191,13 +195,21 @@ func idleMonitor(idleTimeout time.Duration, fs *fusefrontend.RootNode, srv *fuse
|
|||||||
idleCount++
|
idleCount++
|
||||||
}
|
}
|
||||||
tlog.Debug.Printf(
|
tlog.Debug.Printf(
|
||||||
"Checking for idle (isIdle = %t, open = %d): %s",
|
"idleMonitor: idle for %v (idleCount = %d, isIdle = %t, open = %d)",
|
||||||
isIdle, openFileCount, time.Now().String())
|
idleTime(), idleCount, isIdle, openFileCount)
|
||||||
if idleCount > 0 && idleCount%timeoutCycles == 0 {
|
if idleCount > 0 && idleCount%timeoutCycles == 0 {
|
||||||
tlog.Info.Printf("Filesystem idle; unmounting: %s", mountpoint)
|
tlog.Info.Printf("idleMonitor: filesystem idle; unmounting: %s", mountpoint)
|
||||||
unmount(srv, mountpoint)
|
err := srv.Unmount()
|
||||||
|
if err != nil {
|
||||||
|
// We get "Device or resource busy" when a process has its
|
||||||
|
// working directory on the mount. Log the event at Info level
|
||||||
|
// so the user finds out why their filesystem does not get
|
||||||
|
// unmounted.
|
||||||
|
tlog.Info.Printf("idleMonitor: unmount failed: %v. Resetting idle time.", err)
|
||||||
|
idleCount = 0
|
||||||
}
|
}
|
||||||
time.Sleep(time.Duration(sleepTimeBetweenChecks))
|
}
|
||||||
|
time.Sleep(time.Duration(sleepNs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,6 +495,8 @@ func handleSigint(srv *fuse.Server, mountpoint string) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unmount() calls srv.Unmount(), and if that fails, calls "fusermount -u -z"
|
||||||
|
// (lazy unmount).
|
||||||
func unmount(srv *fuse.Server, mountpoint string) {
|
func unmount(srv *fuse.Server, mountpoint string) {
|
||||||
err := srv.Unmount()
|
err := srv.Unmount()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user