Commit 8deb92ef authored by Felix Lechner's avatar Felix Lechner

Cherry-pick fix for --idle and its test for Berto. (Follow-up to: #939544)

parent 46c6ec75
From 0a4db7d9e9801a416602b52281537991ba1463c0 Mon Sep 17 00:00:00 2001
From: Jakob Unterwurzacher <jakobunt@gmail.com>
Date: Sun, 8 Sep 2019 16:29:20 +0200
Subject: [PATCH] Fix -idle unmounting despite activity
Fixes https://github.com/rfjakob/gocryptfs/issues/421
---
internal/fusefrontend/fs.go | 13 ++++++++-----
mount.go | 10 +++++-----
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go
index 2c40942..fe37d10 100644
--- a/internal/fusefrontend/fs.go
+++ b/internal/fusefrontend/fs.go
@@ -6,6 +6,7 @@ package fusefrontend
import (
"os"
"sync"
+ "sync/atomic"
"syscall"
"time"
@@ -50,11 +51,11 @@ type FS struct {
// "gocryptfs -fsck" reads from the channel to also catch these transparently-
// mitigated corruptions.
MitigatedCorruptions chan string
- // Track accesses to the filesystem so that we can know when to autounmount.
- // An access is considered to have happened on every call to encryptPath,
- // which is called as part of every filesystem operation.
- // (This flag uses a uint32 so that it can be reset with CompareAndSwapUint32.)
- AccessedSinceLastCheck uint32
+ // This flag is set to zero each time fs.isFiltered() is called
+ // (uint32 so that it can be reset with CompareAndSwapUint32).
+ // When -idle was used when mounting, idleMonitor() sets it to 1
+ // periodically.
+ IsIdle uint32
dirCache dirCacheStruct
}
@@ -662,6 +663,8 @@ func (fs *FS) reportMitigatedCorruption(item string) {
//
// Prevents name clashes with internal files when file names are not encrypted
func (fs *FS) isFiltered(path string) bool {
+ atomic.StoreUint32(&fs.IsIdle, 0)
+
if !fs.args.PlaintextNames {
return false
}
diff --git a/mount.go b/mount.go
index eeeffe8..446708e 100644
--- a/mount.go
+++ b/mount.go
@@ -181,18 +181,18 @@ func idleMonitor(idleTimeout time.Duration, fs *fusefrontend.FS, srv *fuse.Serve
timeoutCycles := int(math.Ceil(float64(idleTimeout) / float64(sleepTimeBetweenChecks)))
idleCount := 0
for {
- // Atomically check whether the access flag is set and reset it to 0 if so.
- recentAccess := atomic.CompareAndSwapUint32(&fs.AccessedSinceLastCheck, 1, 0)
+ // Atomically check whether the flag is 0 and reset it to 1 if so.
+ isIdle := !atomic.CompareAndSwapUint32(&fs.IsIdle, 0, 1)
// Any form of current or recent access resets the idle counter.
openFileCount := openfiletable.CountOpenFiles()
- if recentAccess || openFileCount > 0 {
+ if !isIdle || openFileCount > 0 {
idleCount = 0
} else {
idleCount++
}
tlog.Debug.Printf(
- "Checking for idle (recentAccess = %t, open = %d): %s",
- recentAccess, openFileCount, time.Now().String())
+ "Checking for idle (isIdle = %t, open = %d): %s",
+ isIdle, openFileCount, time.Now().String())
if idleCount > 0 && idleCount%timeoutCycles == 0 {
tlog.Info.Printf("Filesystem idle; unmounting: %s", mountpoint)
unmount(srv, mountpoint)
--
2.23.0.rc1
From ce13851bbfceb02da0b36e743090c5fe54469b33 Mon Sep 17 00:00:00 2001
From: Jakob Unterwurzacher <jakobunt@gmail.com>
Date: Sun, 8 Sep 2019 16:16:18 +0200
Subject: [PATCH] tests: add TestNotIdle
Mount with idle timeout of 100ms read something every 10ms. The fs should
NOT get unmounted. Regression test for https://github.com/rfjakob/gocryptfs/issues/421
---
tests/cli/cli_test.go | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/tests/cli/cli_test.go b/tests/cli/cli_test.go
index da9d508..0461d3c 100644
--- a/tests/cli/cli_test.go
+++ b/tests/cli/cli_test.go
@@ -568,3 +568,44 @@ func TestIdle(t *testing.T) {
t.Error(err)
}
}
+
+// Mount with idle timeout of 100ms read something every 10ms. The fs should
+// NOT get unmounted. Regression test for https://github.com/rfjakob/gocryptfs/issues/421
+func TestNotIdle(t *testing.T) {
+ dir := test_helpers.InitFS(t)
+ mnt := dir + ".mnt"
+ err := os.Mkdir(mnt, 0700)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = test_helpers.Mount(dir, mnt, false, "-extpass", "echo test", "-i=100ms")
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = ioutil.WriteFile(mnt+"/foo", []byte("foo"), 0600)
+ if err != nil {
+ t.Fatal(err)
+ }
+ // Read every 10 milliseconds for a total of 1 second
+ for i := 1; i < 100; i++ {
+ _, err = ioutil.ReadFile(mnt + "/foo")
+ if err != nil {
+ t.Fatalf("iteration %d failed: %v", i, err)
+ }
+ time.Sleep(10 * time.Millisecond)
+ }
+ // Keep a file handle open for 1 second
+ fd, err := os.Open(mnt + "/foo")
+ if err != nil {
+ t.Fatal(err)
+ }
+ time.Sleep(1 * time.Second)
+ buf := make([]byte, 100)
+ _, err = fd.Read(buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ fd.Close()
+ // All good.
+ test_helpers.UnmountPanic(mnt)
+}
--
2.23.0.rc1
0001-Fix-idle-unmounting-despite-activity.patch
0001-tests-add-TestNotIdle.patch
fix-gocryptfs-manpage.patch
add-statfs-manpage.patch
001-disable-emulated-getdents.patch
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment