Commit 64e13af4 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Use inode passed to Statfs throughout.

Changes to API:

- Statfs takes a *InHeader argument in the raw API
- Statfs moves to the FsNode API.
- Statfs takes a path argument in the FileSystem API.
parent 2e08b9e3
...@@ -19,7 +19,6 @@ import ( ...@@ -19,7 +19,6 @@ import (
type NodeFileSystem interface { type NodeFileSystem interface {
OnUnmount() OnUnmount()
OnMount(conn *FileSystemConnector) OnMount(conn *FileSystemConnector)
StatFs() *StatfsOut
Root() FsNode Root() FsNode
// Used for debug outputs // Used for debug outputs
...@@ -70,6 +69,8 @@ type FsNode interface { ...@@ -70,6 +69,8 @@ type FsNode interface {
Chown(file File, uid uint32, gid uint32, context *Context) (code Status) Chown(file File, uid uint32, gid uint32, context *Context) (code Status)
Truncate(file File, size uint64, context *Context) (code Status) Truncate(file File, size uint64, context *Context) (code Status)
Utimens(file File, atime uint64, mtime uint64, context *Context) (code Status) Utimens(file File, atime uint64, mtime uint64, context *Context) (code Status)
StatFs() *StatfsOut
} }
// A filesystem API that uses paths rather than inodes. A minimal // A filesystem API that uses paths rather than inodes. A minimal
...@@ -130,7 +131,7 @@ type FileSystem interface { ...@@ -130,7 +131,7 @@ type FileSystem interface {
Symlink(value string, linkName string, context *Context) (code Status) Symlink(value string, linkName string, context *Context) (code Status)
Readlink(name string, context *Context) (string, Status) Readlink(name string, context *Context) (string, Status)
StatFs() *StatfsOut StatFs(name string) *StatfsOut
} }
// A File object should be returned from FileSystem.Open and // A File object should be returned from FileSystem.Open and
...@@ -268,7 +269,7 @@ type RawFileSystem interface { ...@@ -268,7 +269,7 @@ type RawFileSystem interface {
// //
Ioctl(header *InHeader, input *IoctlIn) (output *IoctlOut, data []byte, code Status) Ioctl(header *InHeader, input *IoctlIn) (output *IoctlOut, data []byte, code Status)
StatFs() *StatfsOut StatFs(header *InHeader) *StatfsOut
// Provide callbacks for pushing notifications to the kernel. // Provide callbacks for pushing notifications to the kernel.
Init(params *RawFsInit) Init(params *RawFsInit)
......
...@@ -99,6 +99,6 @@ func (me *DefaultFileSystem) String() string { ...@@ -99,6 +99,6 @@ func (me *DefaultFileSystem) String() string {
return "DefaultFileSystem" return "DefaultFileSystem"
} }
func (me *DefaultFileSystem) StatFs() *StatfsOut { func (me *DefaultFileSystem) StatFs(name string) *StatfsOut {
return nil return nil
} }
...@@ -18,10 +18,6 @@ func (me *DefaultNodeFileSystem) OnMount(conn *FileSystemConnector) { ...@@ -18,10 +18,6 @@ func (me *DefaultNodeFileSystem) OnMount(conn *FileSystemConnector) {
} }
func (me *DefaultNodeFileSystem) StatFs() *StatfsOut {
return nil
}
func (me *DefaultNodeFileSystem) Root() FsNode { func (me *DefaultNodeFileSystem) Root() FsNode {
return new(DefaultFsNode) return new(DefaultFsNode)
} }
...@@ -37,6 +33,10 @@ type DefaultFsNode struct { ...@@ -37,6 +33,10 @@ type DefaultFsNode struct {
inode *Inode inode *Inode
} }
func (me *DefaultFsNode) StatFs() *StatfsOut {
return nil
}
func (me *DefaultFsNode) SetInode(node *Inode) { func (me *DefaultFsNode) SetInode(node *Inode) {
if me.inode != nil { if me.inode != nil {
panic("already have Inode") panic("already have Inode")
......
...@@ -3,7 +3,7 @@ package fuse ...@@ -3,7 +3,7 @@ package fuse
func (me *DefaultRawFileSystem) Init(init *RawFsInit) { func (me *DefaultRawFileSystem) Init(init *RawFsInit) {
} }
func (me *DefaultRawFileSystem) StatFs() *StatfsOut { func (me *DefaultRawFileSystem) StatFs(h *InHeader) *StatfsOut {
return nil return nil
} }
......
...@@ -327,8 +327,9 @@ func (me *FileSystemConnector) Read(header *InHeader, input *ReadIn, bp BufferPo ...@@ -327,8 +327,9 @@ func (me *FileSystemConnector) Read(header *InHeader, input *ReadIn, bp BufferPo
return opened.WithFlags.File.Read(input, bp) return opened.WithFlags.File.Read(input, bp)
} }
func (me *FileSystemConnector) StatFs() *StatfsOut { func (me *FileSystemConnector) StatFs(header *InHeader) *StatfsOut {
return me.rootNode.mountPoint.fs.StatFs() node := me.toInode(header.NodeId)
return node.FsNode().StatFs()
} }
func (me *FileSystemConnector) Flush(header *InHeader, input *FlushIn) Status { func (me *FileSystemConnector) Flush(header *InHeader, input *FlushIn) Status {
......
...@@ -170,9 +170,9 @@ func (me *LoopbackFileSystem) String() string { ...@@ -170,9 +170,9 @@ func (me *LoopbackFileSystem) String() string {
return fmt.Sprintf("LoopbackFileSystem(%s)", me.Root) return fmt.Sprintf("LoopbackFileSystem(%s)", me.Root)
} }
func (me *LoopbackFileSystem) StatFs() *StatfsOut { func (me *LoopbackFileSystem) StatFs(name string) *StatfsOut {
s := syscall.Statfs_t{} s := syscall.Statfs_t{}
errNo := syscall.Statfs(me.Root, &s) errNo := syscall.Statfs(me.GetPath(name), &s)
if errNo == 0 { if errNo == 0 {
return &StatfsOut{ return &StatfsOut{
......
...@@ -673,6 +673,13 @@ func TestIoctl(t *testing.T) { ...@@ -673,6 +673,13 @@ func TestIoctl(t *testing.T) {
ioctl(f.Fd(), 0x5401, 42) ioctl(f.Fd(), 0x5401, 42)
} }
func clearStatfs(s *syscall.Statfs_t) {
empty := syscall.Statfs_t{}
s.Type = 0
s.Fsid = empty.Fsid
s.Spare = empty.Spare
}
// This test is racy. If an external process consumes space while this // This test is racy. If an external process consumes space while this
// runs, we may see spurious differences between the two statfs() calls. // runs, we may see spurious differences between the two statfs() calls.
func TestStatFs(t *testing.T) { func TestStatFs(t *testing.T) {
...@@ -689,19 +696,44 @@ func TestStatFs(t *testing.T) { ...@@ -689,19 +696,44 @@ func TestStatFs(t *testing.T) {
s2 := syscall.Statfs_t{} s2 := syscall.Statfs_t{}
err = syscall.Statfs(ts.mnt, &s2) err = syscall.Statfs(ts.mnt, &s2)
s1.Type = 0 if err != 0 {
s2.Type = 0 t.Fatal("statfs mnt", err)
}
s1.Fsid = empty.Fsid clearStatfs(&s1)
s2.Fsid = empty.Fsid clearStatfs(&s2)
if fmt.Sprintf("%v", s2) != fmt.Sprintf("%v", s1) {
t.Error("Mismatch", s1, s2)
}
}
s1.Spare = empty.Spare func TestFStatFs(t *testing.T) {
s2.Spare = empty.Spare ts := NewTestCase(t)
defer ts.Cleanup()
if err != 0 { fOrig, err := os.OpenFile(ts.orig+"/file", os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0644)
t.Fatal("statfs mnt", err) CheckSuccess(err)
defer fOrig.Close()
empty := syscall.Statfs_t{}
s1 := empty
errno := syscall.Fstatfs(fOrig.Fd(), &s1)
if errno != 0 {
t.Fatal("statfs orig", err)
} }
fMnt, err := os.OpenFile(ts.mnt+"/file", os.O_RDWR, 0644)
CheckSuccess(err)
defer fMnt.Close()
s2 := empty
errno = syscall.Fstatfs(fMnt.Fd(), &s2)
if errno != 0 {
t.Fatal("statfs mnt", err)
}
clearStatfs(&s1)
clearStatfs(&s2)
if fmt.Sprintf("%v", s2) != fmt.Sprintf("%v", s1) { if fmt.Sprintf("%v", s2) != fmt.Sprintf("%v", s1) {
t.Error("Mismatch", s1, s2) t.Error("Mismatch", s1, s2)
} }
......
...@@ -280,7 +280,7 @@ func doRename(state *MountState, req *request) { ...@@ -280,7 +280,7 @@ func doRename(state *MountState, req *request) {
} }
func doStatFs(state *MountState, req *request) { func doStatFs(state *MountState, req *request) {
stat := state.fileSystem.StatFs() stat := state.fileSystem.StatFs(req.inHeader)
if stat != nil { if stat != nil {
req.outData = unsafe.Pointer(stat) req.outData = unsafe.Pointer(stat)
req.status = OK req.status = OK
......
...@@ -104,10 +104,6 @@ func (me *PathNodeFs) OnMount(conn *FileSystemConnector) { ...@@ -104,10 +104,6 @@ func (me *PathNodeFs) OnMount(conn *FileSystemConnector) {
me.fs.OnMount(me) me.fs.OnMount(me)
} }
func (me *PathNodeFs) StatFs() *StatfsOut {
return me.fs.StatFs()
}
func (me *PathNodeFs) Node(name string) *Inode { func (me *PathNodeFs) Node(name string) *Inode {
n, rest := me.LastNode(name) n, rest := me.LastNode(name)
if len(rest) > 0 { if len(rest) > 0 {
...@@ -362,6 +358,9 @@ func (me *pathInode) OnForget() { ...@@ -362,6 +358,9 @@ func (me *pathInode) OnForget() {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// FS operations // FS operations
func (me *pathInode) StatFs() *StatfsOut {
return me.fs.StatFs(me.GetPath())
}
func (me *pathInode) Readlink(c *Context) ([]byte, Status) { func (me *pathInode) Readlink(c *Context) ([]byte, Status) {
path := me.GetPath() path := me.GetPath()
......
...@@ -199,3 +199,10 @@ func (me *FlushIn) String() string { ...@@ -199,3 +199,10 @@ func (me *FlushIn) String() string {
func (me *AccessIn) String() string { func (me *AccessIn) String() string {
return fmt.Sprintf("{%s}", flagString(accessFlagName, int(me.Mask), "")) return fmt.Sprintf("{%s}", flagString(accessFlagName, int(me.Mask), ""))
} }
func (me *Kstatfs) String() string {
return fmt.Sprintf(
"{b%d f%d fs%d ff%d bs%d nl%d frs%d}",
me.Blocks, me.Bfree, me.Bavail, me.Files, me.Ffree,
me.Bsize, me.NameLen, me.Frsize)
}
...@@ -383,6 +383,6 @@ func (me *AutoUnionFs) OpenDir(name string, context *fuse.Context) (stream chan ...@@ -383,6 +383,6 @@ func (me *AutoUnionFs) OpenDir(name string, context *fuse.Context) (stream chan
return stream, status return stream, status
} }
func (me *AutoUnionFs) StatFs() *fuse.StatfsOut { func (me *AutoUnionFs) StatFs(name string) *fuse.StatfsOut {
return &fuse.StatfsOut{} return &fuse.StatfsOut{}
} }
...@@ -192,11 +192,6 @@ func (me *MemUnionFs) Root() fuse.FsNode { ...@@ -192,11 +192,6 @@ func (me *MemUnionFs) Root() fuse.FsNode {
return me.root return me.root
} }
func (me *MemUnionFs) StatFs() *fuse.StatfsOut {
backingFs := &fuse.LoopbackFileSystem{Root: me.backingStore}
return backingFs.StatFs()
}
func (me *MemUnionFs) newNode(isdir bool) *memNode { func (me *MemUnionFs) newNode(isdir bool) *memNode {
n := &memNode{ n := &memNode{
fs: me, fs: me,
...@@ -225,6 +220,11 @@ func (me *memNode) Deletable() bool { ...@@ -225,6 +220,11 @@ func (me *memNode) Deletable() bool {
return !me.changed && me.original == "" return !me.changed && me.original == ""
} }
func (me *memNode) StatFs() *fuse.StatfsOut {
backingFs := &fuse.LoopbackFileSystem{Root: me.fs.backingStore}
return backingFs.StatFs("")
}
func (me *memNode) touch() { func (me *memNode) touch() {
me.changed = true me.changed = true
me.info.Mtime_ns = time.Nanoseconds() me.info.Mtime_ns = time.Nanoseconds()
......
...@@ -970,8 +970,8 @@ func (me *UnionFs) String() string { ...@@ -970,8 +970,8 @@ func (me *UnionFs) String() string {
return fmt.Sprintf("UnionFs(%v)", names) return fmt.Sprintf("UnionFs(%v)", names)
} }
func (me *UnionFs) StatFs() *fuse.StatfsOut { func (me *UnionFs) StatFs(name string) *fuse.StatfsOut {
return me.fileSystems[0].StatFs() return me.fileSystems[0].StatFs("")
} }
type unionFsFile struct { type unionFsFile struct {
......
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