Commit e65a2a77 authored by Lucas Manning's avatar Lucas Manning

Fix loopback file locking methods to correctly use the file handle.

Change-Id: I3a67066a6660481bdab81278a91027755973b496
parent 615a0a7e
...@@ -793,7 +793,7 @@ func (b *rawBridge) SetLk(cancel <-chan struct{}, input *fuse.LkIn) fuse.Status ...@@ -793,7 +793,7 @@ func (b *rawBridge) SetLk(cancel <-chan struct{}, input *fuse.LkIn) fuse.Status
if lops, ok := n.ops.(NodeSetlker); ok { if lops, ok := n.ops.(NodeSetlker); ok {
return errnoToStatus(lops.Setlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags)) return errnoToStatus(lops.Setlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags))
} }
if sl, ok := n.ops.(FileSetlker); ok { if sl, ok := f.file.(FileSetlker); ok {
return errnoToStatus(sl.Setlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Owner, &input.Lk, input.LkFlags)) return errnoToStatus(sl.Setlk(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Owner, &input.Lk, input.LkFlags))
} }
return fuse.ENOTSUP return fuse.ENOTSUP
...@@ -803,7 +803,7 @@ func (b *rawBridge) SetLkw(cancel <-chan struct{}, input *fuse.LkIn) fuse.Status ...@@ -803,7 +803,7 @@ func (b *rawBridge) SetLkw(cancel <-chan struct{}, input *fuse.LkIn) fuse.Status
if lops, ok := n.ops.(NodeSetlkwer); ok { if lops, ok := n.ops.(NodeSetlkwer); ok {
return errnoToStatus(lops.Setlkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags)) return errnoToStatus(lops.Setlkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, f.file, input.Owner, &input.Lk, input.LkFlags))
} }
if sl, ok := n.ops.(FileSetlkwer); ok { if sl, ok := f.file.(FileSetlkwer); ok {
return errnoToStatus(sl.Setlkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Owner, &input.Lk, input.LkFlags)) return errnoToStatus(sl.Setlkw(&fuse.Context{Caller: input.Caller, Cancel: cancel}, input.Owner, &input.Lk, input.LkFlags))
} }
return fuse.ENOTSUP return fuse.ENOTSUP
......
...@@ -57,6 +57,7 @@ func (tc *testCase) Clean() { ...@@ -57,6 +57,7 @@ func (tc *testCase) Clean() {
type testOptions struct { type testOptions struct {
entryCache bool entryCache bool
enableLocks bool
attrCache bool attrCache bool
suppressDebug bool suppressDebug bool
testDir string testDir string
...@@ -112,6 +113,7 @@ func newTestCase(t *testing.T, opts *testOptions) *testCase { ...@@ -112,6 +113,7 @@ func newTestCase(t *testing.T, opts *testOptions) *testCase {
mOpts := &fuse.MountOptions{ mOpts := &fuse.MountOptions{
DirectMount: opts.directMount, DirectMount: opts.directMount,
DirectMountStrict: opts.directMountStrict, DirectMountStrict: opts.directMountStrict,
EnableLocks: opts.enableLocks,
} }
if !opts.suppressDebug { if !opts.suppressDebug {
mOpts.Debug = testutil.VerboseTest() mOpts.Debug = testutil.VerboseTest()
...@@ -390,7 +392,10 @@ func TestPosix(t *testing.T) { ...@@ -390,7 +392,10 @@ func TestPosix(t *testing.T) {
t.Run(nm, func(t *testing.T) { t.Run(nm, func(t *testing.T) {
tc := newTestCase(t, &testOptions{ tc := newTestCase(t, &testOptions{
suppressDebug: noisy[nm], suppressDebug: noisy[nm],
attrCache: true, entryCache: true}) attrCache: true,
entryCache: true,
enableLocks: true,
})
defer tc.Clean() defer tc.Clean()
fn(t, tc.mntDir) fn(t, tc.mntDir)
...@@ -429,7 +434,7 @@ func TestOpenDirectIO(t *testing.T) { ...@@ -429,7 +434,7 @@ func TestOpenDirectIO(t *testing.T) {
// //
// Note: Run as // Note: Run as
// //
// TMPDIR=/var/tmp go test -run TestFsstress // TMPDIR=/var/tmp go test -run TestFsstress
// //
// to make sure the backing filesystem is ext4. /tmp is tmpfs on modern Linux // to make sure the backing filesystem is ext4. /tmp is tmpfs on modern Linux
// distributions, and tmpfs does not reuse inode numbers, hiding the problem. // distributions, and tmpfs does not reuse inode numbers, hiding the problem.
......
...@@ -16,6 +16,7 @@ import ( ...@@ -16,6 +16,7 @@ import (
"testing" "testing"
"github.com/hanwen/go-fuse/v2/fuse" "github.com/hanwen/go-fuse/v2/fuse"
"golang.org/x/sys/unix"
) )
// All holds a map of all test functions // All holds a map of all test functions
...@@ -41,6 +42,8 @@ var All = map[string]func(*testing.T, string){ ...@@ -41,6 +42,8 @@ var All = map[string]func(*testing.T, string){
"OpenAt": OpenAt, "OpenAt": OpenAt,
"Fallocate": Fallocate, "Fallocate": Fallocate,
"DirSeek": DirSeek, "DirSeek": DirSeek,
"FcntlFlockSetLk": FcntlFlockSetLk,
"FcntlFlockLocksFile": FcntlFlockLocksFile,
} }
func DirectIO(t *testing.T, mnt string) { func DirectIO(t *testing.T, mnt string) {
...@@ -631,3 +634,67 @@ func Fallocate(t *testing.T, mnt string) { ...@@ -631,3 +634,67 @@ func Fallocate(t *testing.T, mnt string) {
fi.Size()) fi.Size())
} }
} }
func FcntlFlockSetLk(t *testing.T, mnt string) {
for i, cmd := range []int{syscall.F_SETLK, syscall.F_SETLKW} {
filename := mnt + fmt.Sprintf("/file%d", i)
f1, err := os.Create(filename)
if err != nil {
t.Fatalf("Open failed: %v", err)
}
defer f1.Close()
wlk := syscall.Flock_t{
Type: syscall.F_WRLCK,
Start: 0,
Len: 0,
}
if err := syscall.FcntlFlock(f1.Fd(), cmd, &wlk); err != nil {
t.Fatalf("FcntlFlock failed: %v", err)
}
f2, err := os.OpenFile(filename, os.O_RDWR, 0766)
if err != nil {
t.Fatalf("Open failed: %v", err)
}
defer f2.Close()
lk := syscall.Flock_t{}
if err := syscall.FcntlFlock(f2.Fd(), unix.F_OFD_GETLK, &lk); err != nil {
t.Errorf("FcntlFlock failed: %v", err)
}
if lk.Type != syscall.F_WRLCK {
t.Errorf("got lk.Type=%v, want %v", lk.Type, syscall.F_WRLCK)
}
}
}
func FcntlFlockLocksFile(t *testing.T, mnt string) {
filename := mnt + "/test"
f1, err := os.Create(filename)
if err != nil {
t.Fatalf("Open failed: %v", err)
}
defer f1.Close()
wlk := syscall.Flock_t{
Type: syscall.F_WRLCK,
Start: 0,
Len: 0,
}
if err := syscall.FcntlFlock(f1.Fd(), syscall.F_SETLK, &wlk); err != nil {
t.Fatalf("FcntlFlock failed: %v", err)
}
f2, err := os.OpenFile(filename, os.O_RDWR, 0766)
if err != nil {
t.Fatalf("Open failed: %v", err)
}
defer f2.Close()
rlk := syscall.Flock_t{
Type: syscall.F_RDLCK,
Start: 0,
Len: 0,
}
if err := syscall.FcntlFlock(f2.Fd(), syscall.F_SETLK, &rlk); err != syscall.EAGAIN {
t.Errorf("FcntlFlock returned %v, expected EAGAIN", err)
}
}
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