Commit 8393ebf1 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Add fuse.Options.EnableLocks option.

This ensure VFS locking continues working, ensuring backward compatibility.
parent 32297eb3
......@@ -64,6 +64,7 @@ type MountOptions struct {
// Values shown in "df -T" and friends
// First column, "Filesystem"
FsName string
// Second column, "Type", will be shown as "fuse." + Name
Name string
......@@ -76,6 +77,10 @@ type MountOptions struct {
// If set, print debugging information.
Debug bool
// If set, ask kernel to forward file locks to FUSE. If using,
// you must implement the GetLk/SetLk/SetLkw methods.
EnableLocks bool
}
// RawFileSystem is an interface close to the FUSE wire protocol.
......
......@@ -8,7 +8,8 @@ import (
"github.com/hanwen/go-fuse/fuse"
)
// Mounts a filesystem with the given root node on the given directory
// Mounts a filesystem with the given root node on the given directory.
// Convenience wrapper around fuse.NewServer
func MountRoot(mountpoint string, root Node, opts *Options) (*fuse.Server, *FileSystemConnector, error) {
conn := NewFileSystemConnector(root, opts)
......
......@@ -83,7 +83,11 @@ func doInit(server *Server, req *request) {
server.reqMu.Lock()
server.kernelSettings = *input
server.kernelSettings.Flags = input.Flags & (CAP_ASYNC_READ | CAP_BIG_WRITES | CAP_FILE_OPS |
CAP_AUTO_INVAL_DATA | CAP_READDIRPLUS | CAP_NO_OPEN_SUPPORT | CAP_FLOCK_LOCKS | CAP_POSIX_LOCKS)
CAP_AUTO_INVAL_DATA | CAP_READDIRPLUS | CAP_NO_OPEN_SUPPORT)
if server.opts.EnableLocks {
server.kernelSettings.Flags |= CAP_FLOCK_LOCKS | CAP_POSIX_LOCKS
}
if input.Minor >= 13 {
server.setSplice()
......
......@@ -7,6 +7,7 @@
package test
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
......@@ -130,10 +131,15 @@ func TestFlockInvoked(t *testing.T) {
}
root := nodefs.NewDefaultNode()
s, _, err := nodefs.MountRoot(dir, root, opts)
conn := nodefs.NewFileSystemConnector(root, opts)
mountOpts := fuse.MountOptions{
EnableLocks: true
}
s, err := fuse.NewServer(conn.RawFS(), dir, &mountOpts)
if err != nil {
t.Fatalf("MountRoot: %v", err)
t.Fatal("NewServer", err)
}
go s.Serve()
if err := s.WaitMount(); err != nil {
t.Fatal("WaitMount", err)
......@@ -150,6 +156,7 @@ func TestFlockInvoked(t *testing.T) {
if node.SetLkInvoked() {
t.Fatalf("SetLk is invoked")
}
cmd := exec.Command(flock, "--nonblock", realPath, "echo", "locked")
out, err := cmd.CombinedOutput()
if err != nil {
......@@ -171,3 +178,58 @@ func TestFlockInvoked(t *testing.T) {
t.Fatalf("SetLkw is not invoked")
}
}
// Test that file system that don't implement locking are still
// handled in the VFS layer.
func TestNoLockSupport(t *testing.T) {
flock, err := exec.LookPath("flock")
if err != nil {
t.Skip("flock command not found.")
}
tmp, err := ioutil.TempDir("", "TestNoLockSupport")
if err != nil {
t.Fatal(err)
}
mnt, err := ioutil.TempDir("", "TestNoLockSupport")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmp)
defer os.RemoveAll(mnt)
opts := &nodefs.Options{
Owner: fuse.CurrentOwner(),
Debug: testutil.VerboseTest(),
}
root := nodefs.NewMemNodeFSRoot(tmp)
lock := fuse.FileLock{}
outLock := fuse.FileLock{}
ctx := fuse.Context{}
if status := root.GetLk(nil, uint64(1), &lock, uint32(0x0), &outLock, &ctx); status != fuse.ENOSYS {
t.Fatalf("MemNodeFs should not implement locking")
}
s, _, err := nodefs.MountRoot(mnt, root, opts)
if err != nil {
t.Fatalf("MountRoot: %v", err)
}
go s.Serve()
if err := s.WaitMount(); err != nil {
t.Fatalf("WaitMount: %v", err)
}
defer s.Unmount()
fn := mnt + "/file.txt"
if err := ioutil.WriteFile(fn, []byte("content"), 0644); err != nil {
t.Fatalf("WriteFile: %v", err)
}
cmd := exec.Command(flock, "--nonblock", fn, "echo", "locked")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("flock %v: %v", err, string(out))
}
}
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