aboutsummaryrefslogtreecommitdiff
path: root/mount.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2021-01-02 18:11:18 +0100
committerJakob Unterwurzacher2021-01-02 18:19:41 +0100
commitde108d3fc06dd9de404c497dfa9faa26956f43e3 (patch)
tree3f1044f2bdd7587cd34e321ba49c5f70d1cf03a0 /mount.go
parentc20c7992a06434dd4a9624a57aee608acfc33c12 (diff)
-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
Diffstat (limited to 'mount.go')
-rw-r--r--mount.go28
1 files changed, 21 insertions, 7 deletions
diff --git a/mount.go b/mount.go
index 9240afc..e4a36d1 100644
--- a/mount.go
+++ b/mount.go
@@ -175,11 +175,15 @@ func doMount(args *argContainer) {
const checksDuringTimeoutPeriod = 4
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(2*time.Minute))
- timeoutCycles := int(math.Ceil(float64(idleTimeout) / float64(sleepTimeBetweenChecks)))
+ timeoutCycles := int(math.Ceil(float64(idleTimeout) / float64(sleepNs)))
idleCount := 0
+ idleTime := func() time.Duration {
+ return time.Duration(sleepNs * uint64(idleCount))
+ }
for {
// Atomically check whether the flag is 0 and reset it to 1 if so.
isIdle := !atomic.CompareAndSwapUint32(&fs.IsIdle, 0, 1)
@@ -191,13 +195,21 @@ func idleMonitor(idleTimeout time.Duration, fs *fusefrontend.RootNode, srv *fuse
idleCount++
}
tlog.Debug.Printf(
- "Checking for idle (isIdle = %t, open = %d): %s",
- isIdle, openFileCount, time.Now().String())
+ "idleMonitor: idle for %v (idleCount = %d, isIdle = %t, open = %d)",
+ idleTime(), idleCount, isIdle, openFileCount)
if idleCount > 0 && idleCount%timeoutCycles == 0 {
- tlog.Info.Printf("Filesystem idle; unmounting: %s", mountpoint)
- unmount(srv, mountpoint)
+ tlog.Info.Printf("idleMonitor: filesystem idle; unmounting: %s", 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) {
err := srv.Unmount()
if err != nil {