diff --git a/third_party/code.google.com/p/rsc/fuse/fuse.go b/third_party/code.google.com/p/rsc/fuse/fuse.go index 25892a21c..8454f0d8f 100644 --- a/third_party/code.google.com/p/rsc/fuse/fuse.go +++ b/third_party/code.google.com/p/rsc/fuse/fuse.go @@ -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. diff --git a/third_party/code.google.com/p/rsc/fuse/fuse_test.go b/third_party/code.google.com/p/rsc/fuse/fuse_test.go index f7c73bd79..aa12c350c 100644 --- a/third_party/code.google.com/p/rsc/fuse/fuse_test.go +++ b/third_party/code.google.com/p/rsc/fuse/fuse_test.go @@ -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) diff --git a/third_party/code.google.com/p/rsc/fuse/serve.go b/third_party/code.google.com/p/rsc/fuse/serve.go index b53dbf4cd..dfd07531c 100644 --- a/third_party/code.google.com/p/rsc/fuse/serve.go +++ b/third_party/code.google.com/p/rsc/fuse/serve.go @@ -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)