aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJakob Unterwurzacher2023-06-02 14:24:44 +0200
committerJakob Unterwurzacher2023-06-05 14:28:58 +0200
commit964f0c190932e5dc53b05ec69ccda6e8d33a73b6 (patch)
tree219f6c02123f0666c795b05e7f1c381690110c4c /tests
parent3058b7978fd8dabd3e8565c9be816b1367bd196a (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.go37
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")
+ }
+}