aboutsummaryrefslogtreecommitdiff
path: root/tests/cluster/poc_test.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2023-06-02 14:24:44 +0200
committerJakob Unterwurzacher2024-12-04 19:53:15 +0100
commit8f76d1ea0a63f546ad09fa70be1ed7b6a7d29fe6 (patch)
treeceeb1a1d902e55f1798c238af5595247201db929 /tests/cluster/poc_test.go
parent9529f5da0f608c7dbc7b7be095d89039d6a3a5b6 (diff)
fusefrontend: sharedstorage: use byte-range lock on file header creation
Multiple host writing to the same empty file at the same time could have overwritten each other's newly created 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/cluster/poc_test.go')
-rw-r--r--tests/cluster/poc_test.go47
1 files changed, 47 insertions, 0 deletions
diff --git a/tests/cluster/poc_test.go b/tests/cluster/poc_test.go
new file mode 100644
index 0000000..4d7182a
--- /dev/null
+++ b/tests/cluster/poc_test.go
@@ -0,0 +1,47 @@
+package cluster
+
+// poc_test.go contains proof of concept tests for the byte-range locking logic.
+// This goes directly to an underlying filesystem without going through gocryptfs.
+
+import (
+ "syscall"
+ "testing"
+
+ "golang.org/x/sys/unix"
+
+ "github.com/rfjakob/gocryptfs/v2/tests/test_helpers"
+)
+
+// Check that byte-range locks work on an empty file
+func TestPoCFcntlFlock(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")
+ }
+}