fuse: add fsync support

Change-Id: Ia7351e70437df32b16648793dfc47d11ad8fdbea
This commit is contained in:
Brad Fitzpatrick 2012-03-18 18:25:09 -07:00
parent 1ea7c0c8c9
commit 9b9b837148
3 changed files with 79 additions and 6 deletions

View File

@ -545,7 +545,15 @@ func (c *Conn) ReadRequest() (Request, error) {
}
case opFsync:
panic("opFsync")
in := (*fsyncIn)(m.data())
if m.len() < unsafe.Sizeof(*in) {
goto corrupt
}
req = &FsyncRequest{
Header: m.Header(),
Handle: HandleID(in.Fh),
Flags: in.FsyncFlags,
}
case opSetxattr:
var size uint32
@ -1591,6 +1599,21 @@ func (r *MknodRequest) Respond(resp *LookupResponse) {
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
}
type FsyncRequest struct {
Header
Handle HandleID
Flags uint32
}
func (r *FsyncRequest) String() string {
return fmt.Sprintf("Fsync [%s] Handle %v Flags %v", &r.Header, r.Handle, r.Flags)
}
func (r *FsyncRequest) Respond() {
out := &outHeader{Unique: uint64(r.ID)}
r.Conn.respond(out, unsafe.Sizeof(*out))
}
/*{
// A XXXRequest xxx.

View File

@ -137,11 +137,12 @@ func (readAll1) test(path string, t *testing.T) {
readAll{}.test(path, t)
}
// Test Write calling basic Write.
// Test Write calling basic Write, with an fsync thrown in too.
type write struct {
file
data []byte
data []byte
gotfsync bool
}
func (w *write) Write(req *WriteRequest, resp *WriteResponse, intr Intr) Error {
@ -150,6 +151,11 @@ func (w *write) Write(req *WriteRequest, resp *WriteResponse, intr Intr) Error {
return nil
}
func (w *write) Fsync(r *FsyncRequest, intr Intr) Error {
w.gotfsync = true
return nil
}
func (w *write) test(path string, t *testing.T) {
log.Printf("pre-write Create")
f, err := os.Create(path)
@ -164,6 +170,15 @@ func (w *write) test(path string, t *testing.T) {
if n != len(hi) {
t.Fatalf("short write; n=%d; hi=%d", n, len(hi))
}
err = syscall.Fsync(int(f.Fd()))
if err != nil {
t.Fatalf("Fsync = %v", err)
}
if !w.gotfsync {
t.Errorf("never received expected fsync call")
}
log.Printf("pre-write Close")
err = f.Close()
if err != nil {
@ -179,7 +194,13 @@ func (w *write) test(path string, t *testing.T) {
type writeAll struct {
file
data []byte
data []byte
gotfsync bool
}
func (w *writeAll) Fsync(r *FsyncRequest, intr Intr) Error {
w.gotfsync = true
return nil
}
func (w *writeAll) WriteAll(data []byte, intr Intr) Error {
@ -259,7 +280,7 @@ func (f *mkdir1) test(path string, t *testing.T) {
}
}
// Test Create
// Test Create (and fsync)
type create1 struct {
dir
@ -280,6 +301,16 @@ func (f *create1) test(path string, t *testing.T) {
t.Errorf("create1 WriteFile: %v", err)
return
}
err = syscall.Fsync(int(ff.Fd()))
if err != nil {
t.Fatalf("Fsync = %v", err)
}
if !f.f.gotfsync {
t.Errorf("never received expected fsync call")
}
ff.Close()
if f.name != "foo" {
t.Errorf("create1 name=%q want foo", f.name)

View File

@ -930,7 +930,26 @@ func (c *Conn) serve(fs FS, r Request) {
done(s)
r.Respond(s)
/* case *FsyncRequest, *FsyncdirRequest:
case *FsyncRequest:
n, ok := node.(interface {
Fsync(r *FsyncRequest, intr Intr) Error
})
if !ok {
log.Printf("Node %T missing Fsync method", node)
done(EIO)
r.RespondError(EIO)
break
}
err := n.Fsync(r, intr)
if err != nil {
done(err)
r.RespondError(err)
break
}
done(nil)
r.Respond()
/* case *FsyncdirRequest:
done(ENOSYS)
r.RespondError(ENOSYS)