Commit e32d0aa0 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

nodefs: write loopbackFile using syscall directly, skipping os.File

parent 9fa9d995
...@@ -103,6 +103,7 @@ type Operations interface { ...@@ -103,6 +103,7 @@ type Operations interface {
StatFs(ctx context.Context, out *fuse.StatfsOut) fuse.Status StatFs(ctx context.Context, out *fuse.StatfsOut) fuse.Status
Access(ctx context.Context, mask uint32) fuse.Status Access(ctx context.Context, mask uint32) fuse.Status
// File locking // File locking
GetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status) GetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status)
SetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status) SetLk(ctx context.Context, f FileHandle, owner uint64, lk *fuse.FileLock, flags uint32) (status fuse.Status)
......
...@@ -7,20 +7,20 @@ package nodefs ...@@ -7,20 +7,20 @@ package nodefs
import ( import (
"context" "context"
// "time" // "time"
"os"
"sync" "sync"
"syscall" "syscall"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
) )
func newLoopbackFile(f *os.File) *loopbackFile { func newLoopbackFile(fd int) *loopbackFile {
return &loopbackFile{File: f} return &loopbackFile{fd: fd}
} }
// loopbackFile delegates all operations back to an underlying os.File. // loopbackFile delegates all operations back to an underlying file.
type loopbackFile struct { type loopbackFile struct {
File *os.File fd int
// os.File is not threadsafe. Although fd themselves are // os.File is not threadsafe. Although fd themselves are
// constant during the lifetime of an open file, the OS may // constant during the lifetime of an open file, the OS may
...@@ -34,21 +34,21 @@ func (f *loopbackFile) Read(ctx context.Context, buf []byte, off int64) (res fus ...@@ -34,21 +34,21 @@ func (f *loopbackFile) Read(ctx context.Context, buf []byte, off int64) (res fus
f.mu.Lock() f.mu.Lock()
// This is not racy by virtue of the kernel properly // This is not racy by virtue of the kernel properly
// synchronizing the open/write/close. // synchronizing the open/write/close.
r := fuse.ReadResultFd(f.File.Fd(), off, len(buf)) r := fuse.ReadResultFd(uintptr(f.fd), off, len(buf))
f.mu.Unlock() f.mu.Unlock()
return r, fuse.OK return r, fuse.OK
} }
func (f *loopbackFile) Write(ctx context.Context, data []byte, off int64) (uint32, fuse.Status) { func (f *loopbackFile) Write(ctx context.Context, data []byte, off int64) (uint32, fuse.Status) {
f.mu.Lock() f.mu.Lock()
n, err := f.File.WriteAt(data, off) n, err := syscall.Pwrite(f.fd, data, off)
f.mu.Unlock() f.mu.Unlock()
return uint32(n), fuse.ToStatus(err) return uint32(n), fuse.ToStatus(err)
} }
func (f *loopbackFile) Release() { func (f *loopbackFile) Release() {
f.mu.Lock() f.mu.Lock()
f.File.Close() syscall.Close(f.fd)
f.mu.Unlock() f.mu.Unlock()
} }
...@@ -58,7 +58,7 @@ func (f *loopbackFile) Flush(ctx context.Context) fuse.Status { ...@@ -58,7 +58,7 @@ func (f *loopbackFile) Flush(ctx context.Context) fuse.Status {
// Since Flush() may be called for each dup'd fd, we don't // Since Flush() may be called for each dup'd fd, we don't
// want to really close the file, we just want to flush. This // want to really close the file, we just want to flush. This
// is achieved by closing a dup'd fd. // is achieved by closing a dup'd fd.
newFd, err := syscall.Dup(int(f.File.Fd())) newFd, err := syscall.Dup(f.fd)
f.mu.Unlock() f.mu.Unlock()
if err != nil { if err != nil {
...@@ -70,7 +70,7 @@ func (f *loopbackFile) Flush(ctx context.Context) fuse.Status { ...@@ -70,7 +70,7 @@ func (f *loopbackFile) Flush(ctx context.Context) fuse.Status {
func (f *loopbackFile) Fsync(ctx context.Context, flags uint32) (status fuse.Status) { func (f *loopbackFile) Fsync(ctx context.Context, flags uint32) (status fuse.Status) {
f.mu.Lock() f.mu.Lock()
r := fuse.ToStatus(syscall.Fsync(int(f.File.Fd()))) r := fuse.ToStatus(syscall.Fsync(f.fd))
f.mu.Unlock() f.mu.Unlock()
return r return r
...@@ -85,7 +85,7 @@ const ( ...@@ -85,7 +85,7 @@ const (
func (f *loopbackFile) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status) { func (f *loopbackFile) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (status fuse.Status) {
flk := syscall.Flock_t{} flk := syscall.Flock_t{}
lk.ToFlockT(&flk) lk.ToFlockT(&flk)
status = fuse.ToStatus(syscall.FcntlFlock(f.File.Fd(), _OFD_GETLK, &flk)) status = fuse.ToStatus(syscall.FcntlFlock(uintptr(f.fd), _OFD_GETLK, &flk))
out.FromFlockT(&flk) out.FromFlockT(&flk)
return return
} }
...@@ -114,7 +114,7 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL ...@@ -114,7 +114,7 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL
if !blocking { if !blocking {
op |= syscall.LOCK_NB op |= syscall.LOCK_NB
} }
return fuse.ToStatus(syscall.Flock(int(f.File.Fd()), op)) return fuse.ToStatus(syscall.Flock(f.fd, op))
} else { } else {
flk := syscall.Flock_t{} flk := syscall.Flock_t{}
lk.ToFlockT(&flk) lk.ToFlockT(&flk)
...@@ -124,13 +124,13 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL ...@@ -124,13 +124,13 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL
} else { } else {
op = _OFD_SETLK op = _OFD_SETLK
} }
return fuse.ToStatus(syscall.FcntlFlock(f.File.Fd(), op, &flk)) return fuse.ToStatus(syscall.FcntlFlock(uintptr(f.fd), op, &flk))
} }
} }
func (f *loopbackFile) Truncate(ctx context.Context, size uint64) fuse.Status { func (f *loopbackFile) Truncate(ctx context.Context, size uint64) fuse.Status {
f.mu.Lock() f.mu.Lock()
r := fuse.ToStatus(syscall.Ftruncate(int(f.File.Fd()), int64(size))) r := fuse.ToStatus(syscall.Ftruncate(f.fd, int64(size)))
f.mu.Unlock() f.mu.Unlock()
return r return r
...@@ -138,7 +138,7 @@ func (f *loopbackFile) Truncate(ctx context.Context, size uint64) fuse.Status { ...@@ -138,7 +138,7 @@ func (f *loopbackFile) Truncate(ctx context.Context, size uint64) fuse.Status {
func (f *loopbackFile) Chmod(ctx context.Context, mode uint32) fuse.Status { func (f *loopbackFile) Chmod(ctx context.Context, mode uint32) fuse.Status {
f.mu.Lock() f.mu.Lock()
r := fuse.ToStatus(f.File.Chmod(os.FileMode(mode))) r := fuse.ToStatus(syscall.Fchmod(f.fd, mode))
f.mu.Unlock() f.mu.Unlock()
return r return r
...@@ -146,7 +146,7 @@ func (f *loopbackFile) Chmod(ctx context.Context, mode uint32) fuse.Status { ...@@ -146,7 +146,7 @@ func (f *loopbackFile) Chmod(ctx context.Context, mode uint32) fuse.Status {
func (f *loopbackFile) Chown(ctx context.Context, uid uint32, gid uint32) fuse.Status { func (f *loopbackFile) Chown(ctx context.Context, uid uint32, gid uint32) fuse.Status {
f.mu.Lock() f.mu.Lock()
r := fuse.ToStatus(f.File.Chown(int(uid), int(gid))) r := fuse.ToStatus(syscall.Fchown(f.fd, int(uid), int(gid)))
f.mu.Unlock() f.mu.Unlock()
return r return r
...@@ -155,7 +155,7 @@ func (f *loopbackFile) Chown(ctx context.Context, uid uint32, gid uint32) fuse.S ...@@ -155,7 +155,7 @@ func (f *loopbackFile) Chown(ctx context.Context, uid uint32, gid uint32) fuse.S
func (f *loopbackFile) GetAttr(ctx context.Context, a *fuse.AttrOut) fuse.Status { func (f *loopbackFile) GetAttr(ctx context.Context, a *fuse.AttrOut) fuse.Status {
st := syscall.Stat_t{} st := syscall.Stat_t{}
f.mu.Lock() f.mu.Lock()
err := syscall.Fstat(int(f.File.Fd()), &st) err := syscall.Fstat(f.fd, &st)
f.mu.Unlock() f.mu.Unlock()
if err != nil { if err != nil {
return fuse.ToStatus(err) return fuse.ToStatus(err)
......
...@@ -14,7 +14,7 @@ import ( ...@@ -14,7 +14,7 @@ import (
func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) fuse.Status { func (f *loopbackFile) Allocate(ctx context.Context, off uint64, sz uint64, mode uint32) fuse.Status {
f.mu.Lock() f.mu.Lock()
err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz)) err := syscall.Fallocate(f.fd, mode, int64(off), int64(sz))
f.mu.Unlock() f.mu.Unlock()
if err != nil { if err != nil {
return fuse.ToStatus(err) return fuse.ToStatus(err)
...@@ -28,7 +28,7 @@ func (f *loopbackFile) Utimens(ctx context.Context, a *time.Time, m *time.Time) ...@@ -28,7 +28,7 @@ func (f *loopbackFile) Utimens(ctx context.Context, a *time.Time, m *time.Time)
ts[0] = fuse.UtimeToTimespec(a) ts[0] = fuse.UtimeToTimespec(a)
ts[1] = fuse.UtimeToTimespec(m) ts[1] = fuse.UtimeToTimespec(m)
f.mu.Lock() f.mu.Lock()
err := futimens(int(f.File.Fd()), &ts) err := futimens(int(f.fd), &ts)
f.mu.Unlock() f.mu.Unlock()
return fuse.ToStatus(err) return fuse.ToStatus(err)
} }
...@@ -176,20 +176,20 @@ func idFromStat(st *syscall.Stat_t) FileID { ...@@ -176,20 +176,20 @@ func idFromStat(st *syscall.Stat_t) FileID {
func (n *loopbackNode) Create(ctx context.Context, name string, flags uint32, mode uint32) (inode *Inode, fh FileHandle, fuseFlags uint32, status fuse.Status) { func (n *loopbackNode) Create(ctx context.Context, name string, flags uint32, mode uint32) (inode *Inode, fh FileHandle, fuseFlags uint32, status fuse.Status) {
p := filepath.Join(n.path(), name) p := filepath.Join(n.path(), name)
f, err := os.OpenFile(p, int(flags)|os.O_CREATE, os.FileMode(mode)) fd, err := syscall.Open(p, int(flags)|os.O_CREATE, mode)
if err != nil { if err != nil {
return nil, nil, 0, fuse.ToStatus(err) return nil, nil, 0, fuse.ToStatus(err)
} }
st := syscall.Stat_t{} st := syscall.Stat_t{}
if err := syscall.Fstat(int(f.Fd()), &st); err != nil { if err := syscall.Fstat(fd, &st); err != nil {
f.Close() syscall.Close(fd)
return nil, nil, 0, fuse.ToStatus(err) return nil, nil, 0, fuse.ToStatus(err)
} }
node := n.rootNode.newLoopbackNode() node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(node, uint32(st.Mode), idFromStat(&st)) ch := n.inode().NewInode(node, uint32(st.Mode), idFromStat(&st))
lf := newLoopbackFile(f) lf := newLoopbackFile(fd)
n.mu.Lock() n.mu.Lock()
defer n.mu.Unlock() defer n.mu.Unlock()
n.openFiles[lf] = flags | syscall.O_CREAT n.openFiles[lf] = flags | syscall.O_CREAT
...@@ -252,7 +252,7 @@ func (n *loopbackNode) Readlink(ctx context.Context) (string, fuse.Status) { ...@@ -252,7 +252,7 @@ func (n *loopbackNode) Readlink(ctx context.Context) (string, fuse.Status) {
func (n *loopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, status fuse.Status) { func (n *loopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, status fuse.Status) {
p := n.path() p := n.path()
f, err := os.OpenFile(p, int(flags), 0) f, err := syscall.Open(p, int(flags), 0)
if err != nil { if err != nil {
return nil, 0, fuse.ToStatus(err) return nil, 0, fuse.ToStatus(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