diff options
author | Jakob Unterwurzacher | 2023-06-02 14:24:44 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2023-06-05 14:28:58 +0200 |
commit | 964f0c190932e5dc53b05ec69ccda6e8d33a73b6 (patch) | |
tree | 219f6c02123f0666c795b05e7f1c381690110c4c /tests | |
parent | 3058b7978fd8dabd3e8565c9be816b1367bd196a (diff) |
fusefrontend: sharedstorage: use byte-range lock on file header creation
Multiple hosts creating the same file at the same time could
have overwritten each other's file header, leading to data
corruption.
Fix the race by placing a byte-range lock on the file when
creating the file header.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/cluster/cluster_test.go | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/tests/cluster/cluster_test.go b/tests/cluster/cluster_test.go index 2e969ce..def03f1 100644 --- a/tests/cluster/cluster_test.go +++ b/tests/cluster/cluster_test.go @@ -10,8 +10,11 @@ import ( "math/rand" "os" "sync" + "syscall" "testing" + "golang.org/x/sys/unix" + "github.com/rfjakob/gocryptfs/v2/tests/test_helpers" ) @@ -109,3 +112,37 @@ func TestClusterConcurrentRW(t *testing.T) { go readThread(f2) wg.Wait() } + +// Check that byte-range locks work on an empty file +func TestFcntlFlock(t *testing.T) { + path := test_helpers.TmpDir + "/" + t.Name() + + fd1, err := syscall.Open(path, syscall.O_CREAT|syscall.O_WRONLY|syscall.O_EXCL, 0600) + if err != nil { + t.Fatal(err) + } + defer syscall.Close(fd1) + + // F_OFD_SETLK locks on the same fd always succeed, so we have to + // open a 2nd time. + fd2, err := syscall.Open(path, syscall.O_RDWR, 0) + if err != nil { + t.Fatal(err) + } + defer syscall.Close(fd2) + + lk := unix.Flock_t{ + Type: unix.F_WRLCK, + Whence: unix.SEEK_SET, + Start: 0, + Len: 0, + } + err = unix.FcntlFlock(uintptr(fd1), unix.F_OFD_SETLK, &lk) + if err != nil { + t.Fatal(err) + } + err = unix.FcntlFlock(uintptr(fd2), unix.F_OFD_SETLK, &lk) + if err == nil { + t.Fatal("double-lock succeeded but should have failed") + } +} |