From 3a6a96203411c41c8a8d7718aa14245d53d86241 Mon Sep 17 00:00:00 2001 From: Nick Cooper Date: Thu, 16 Apr 2015 17:51:04 +1000 Subject: [PATCH] add context to debug --- debug.go | 6 +- fs/fstestutil/debug.go | 5 +- fs/fstestutil/mounted.go | 5 +- fs/serve.go | 220 +++++++++++++++++++-------------------- fuse.go | 126 +++++++++++----------- hellofs/hello.go | 2 +- 6 files changed, 185 insertions(+), 179 deletions(-) diff --git a/debug.go b/debug.go index be9f900d..4c7d2ae5 100644 --- a/debug.go +++ b/debug.go @@ -2,6 +2,8 @@ package fuse import ( "runtime" + + "golang.org/x/net/context" ) func stack() string { @@ -9,7 +11,7 @@ func stack() string { return string(buf[:runtime.Stack(buf, false)]) } -func nop(msg interface{}) {} +func nop(ctx context.Context, msg interface{}) {} // Debug is called to output debug messages, including protocol // traces. The default behavior is to do nothing. @@ -18,4 +20,4 @@ func nop(msg interface{}) {} // safe to marshal to JSON. // // Implementations must not retain msg. -var Debug func(msg interface{}) = nop +var Debug func(ctx context.Context, msg interface{}) = nop diff --git a/fs/fstestutil/debug.go b/fs/fstestutil/debug.go index df44a0c6..8e85fba2 100644 --- a/fs/fstestutil/debug.go +++ b/fs/fstestutil/debug.go @@ -6,6 +6,7 @@ import ( "strconv" "bazil.org/fuse" + "golang.org/x/net/context" ) type flagDebug bool @@ -18,7 +19,7 @@ func (f *flagDebug) IsBoolFlag() bool { return true } -func nop(msg interface{}) {} +func nop(ctx context.Context, msg interface{}) {} func (f *flagDebug) Set(s string) error { v, err := strconv.ParseBool(s) @@ -38,7 +39,7 @@ func (f *flagDebug) String() string { return strconv.FormatBool(bool(*f)) } -func logMsg(msg interface{}) { +func logMsg(ctx context.Context, msg interface{}) { log.Printf("FUSE: %s\n", msg) } diff --git a/fs/fstestutil/mounted.go b/fs/fstestutil/mounted.go index 5c30011d..26a69bee 100644 --- a/fs/fstestutil/mounted.go +++ b/fs/fstestutil/mounted.go @@ -10,6 +10,7 @@ import ( "bazil.org/fuse" "bazil.org/fuse/fs" + "golang.org/x/net/context" ) // Mount contains information about the mount for the test to use. @@ -75,7 +76,7 @@ func Mounted(srv *fs.Server, options ...fuse.MountOption) (*Mount, error) { } go func() { defer close(done) - serveErr <- srv.Serve(c) + serveErr <- srv.Serve(context.Background(), c) }() select { @@ -105,7 +106,7 @@ func MountedT(t testing.TB, filesys fs.FS, options ...fuse.MountOption) (*Mount, FS: filesys, } if debug { - srv.Debug = func(msg interface{}) { + srv.Debug = func(ctx context.Context, msg interface{}) { t.Logf("FUSE: %s", msg) } } diff --git a/fs/serve.go b/fs/serve.go index ef376816..7a367064 100644 --- a/fs/serve.go +++ b/fs/serve.go @@ -314,13 +314,13 @@ type Server struct { // calls to Serve. // // See fuse.Debug for the rules that log functions must follow. - Debug func(msg interface{}) + Debug func(ctx context.Context, msg interface{}) } // Serve serves the FUSE connection by making calls to the methods // of fs and the Nodes and Handles it makes available. It returns only // when the connection has been closed or an unexpected error occurs. -func (s *Server) Serve(c *fuse.Conn) error { +func (s *Server) Serve(ctx context.Context, c *fuse.Conn) error { sc := serveConn{ fs: s.FS, debug: s.Debug, @@ -342,7 +342,7 @@ func (s *Server) Serve(c *fuse.Conn) error { sc.handle = append(sc.handle, nil) for { - req, err := c.ReadRequest() + req, err := c.ReadRequest(ctx) if err != nil { if err == io.EOF { break @@ -350,18 +350,18 @@ func (s *Server) Serve(c *fuse.Conn) error { return err } - go sc.serve(req) + go sc.serve(ctx, req) } return nil } // Serve serves a FUSE connection with the default settings. See // Server.Serve. -func Serve(c *fuse.Conn, fs FS) error { +func Serve(ctx context.Context, c *fuse.Conn, fs FS) error { server := Server{ FS: fs, } - return server.Serve(c) + return server.Serve(ctx, c) } type nothing struct{} @@ -375,7 +375,7 @@ type serveConn struct { freeNode []fuse.NodeID freeHandle []fuse.HandleID nodeGen uint64 - debug func(msg interface{}) + debug func(ctx context.Context, msg interface{}) dynamicInode func(parent uint64, name string) uint64 } @@ -485,7 +485,7 @@ func (n *nodeRefcountDropBug) String() string { return fmt.Sprintf("bug: trying to drop %d of %d references to %v", n.N, n.Refs, n.Node) } -func (c *serveConn) dropNode(id fuse.NodeID, n uint64) (forget bool) { +func (c *serveConn) dropNode(ctx context.Context, id fuse.NodeID, n uint64) (forget bool) { c.meta.Lock() defer c.meta.Unlock() snode := c.node[id] @@ -494,7 +494,7 @@ func (c *serveConn) dropNode(id fuse.NodeID, n uint64) (forget bool) { // this should only happen if refcounts kernel<->us disagree // *and* two ForgetRequests for the same node race each other; // this indicates a bug somewhere - c.debug(nodeRefcountDropBug{N: n, Node: id}) + c.debug(ctx, nodeRefcountDropBug{N: n, Node: id}) // we may end up triggering Forget twice, but that's better // than not even once, and that's the best we can do @@ -502,7 +502,7 @@ func (c *serveConn) dropNode(id fuse.NodeID, n uint64) (forget bool) { } if n > snode.refs { - c.debug(nodeRefcountDropBug{N: n, Refs: snode.refs, Node: id}) + c.debug(ctx, nodeRefcountDropBug{N: n, Refs: snode.refs, Node: id}) n = snode.refs } @@ -536,14 +536,14 @@ func (m missingHandle) String() string { } // Returns nil for invalid handles. -func (c *serveConn) getHandle(id fuse.HandleID) (shandle *serveHandle) { +func (c *serveConn) getHandle(ctx context.Context, id fuse.HandleID) (shandle *serveHandle) { c.meta.Lock() defer c.meta.Unlock() if id < fuse.HandleID(len(c.handle)) { shandle = c.handle[uint(id)] } if shandle == nil { - c.debug(missingHandle{ + c.debug(ctx, missingHandle{ Handle: id, MaxHandle: fuse.HandleID(len(c.handle)), }) @@ -638,13 +638,13 @@ func (m *renameNewDirNodeNotFound) String() string { return fmt.Sprintf("In RenameRequest (request %#x), node %d not found", m.Request.Hdr().ID, m.In.NewDir) } -func (c *serveConn) serve(r fuse.Request) { - ctx, cancel := context.WithCancel(context.Background()) +func (c *serveConn) serve(ctx context.Context, r fuse.Request) { + ctx, cancel := context.WithCancel(ctx) defer cancel() req := &serveRequest{Request: r, cancel: cancel} - c.debug(request{ + c.debug(ctx, request{ Op: opName(r), Request: r.Hdr(), In: r, @@ -659,7 +659,7 @@ func (c *serveConn) serve(r fuse.Request) { } if snode == nil { c.meta.Unlock() - c.debug(response{ + c.debug(ctx, response{ Op: opName(r), Request: logResponseHeader{ID: hdr.ID}, Error: fuse.ESTALE.ErrnoName(), @@ -670,7 +670,7 @@ func (c *serveConn) serve(r fuse.Request) { MaxNode: fuse.NodeID(len(c.node)), }, }) - r.RespondError(fuse.ESTALE) + r.RespondError(ctx, fuse.ESTALE) return } node = snode.node @@ -710,7 +710,7 @@ func (c *serveConn) serve(r fuse.Request) { } else { msg.Out = resp } - c.debug(msg) + c.debug(ctx, msg) c.meta.Lock() delete(c.req, hdr.ID) @@ -723,7 +723,7 @@ func (c *serveConn) serve(r fuse.Request) { // It would be inappropriate to return ENOSYS for other operations in this // switch that might only be unavailable in some contexts, not all. done(fuse.ENOSYS) - r.RespondError(fuse.ENOSYS) + r.RespondError(ctx, fuse.ENOSYS) // FS operations. case *fuse.InitRequest: @@ -734,24 +734,24 @@ func (c *serveConn) serve(r fuse.Request) { if fs, ok := c.fs.(FSIniter); ok { if err := fs.Init(ctx, r, s); err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } } done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.StatfsRequest: s := &fuse.StatfsResponse{} if fs, ok := c.fs.(FSStatfser); ok { if err := fs.Statfs(ctx, r, s); err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } } done(s) - r.Respond(s) + r.Respond(ctx, s) // Node operations. case *fuse.GetattrRequest: @@ -759,7 +759,7 @@ func (c *serveConn) serve(r fuse.Request) { if n, ok := node.(NodeGetattrer); ok { if err := n.Getattr(ctx, r, s); err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } } else { @@ -767,18 +767,18 @@ func (c *serveConn) serve(r fuse.Request) { s.Attr = snode.attr() } done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.SetattrRequest: s := &fuse.SetattrResponse{} if n, ok := node.(NodeSetattrer); ok { if err := n.Setattr(ctx, r, s); err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } done(s) - r.Respond(s) + r.Respond(ctx, s) break } @@ -787,47 +787,47 @@ func (c *serveConn) serve(r fuse.Request) { } s.Attr = snode.attr() done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.SymlinkRequest: s := &fuse.SymlinkResponse{} n, ok := node.(NodeSymlinker) if !ok { done(fuse.EIO) // XXX or EPERM like Mkdir? - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) break } n2, err := n.Symlink(ctx, r) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } c.saveLookup(&s.LookupResponse, snode, r.NewName, n2) done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.ReadlinkRequest: n, ok := node.(NodeReadlinker) if !ok { done(fuse.EIO) /// XXX or EPERM? - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) break } target, err := n.Readlink(ctx, r) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } done(target) - r.Respond(target) + r.Respond(ctx, target) case *fuse.LinkRequest: n, ok := node.(NodeLinker) if !ok { done(fuse.EIO) /// XXX or EPERM? - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) break } c.meta.Lock() @@ -837,51 +837,51 @@ func (c *serveConn) serve(r fuse.Request) { } c.meta.Unlock() if oldNode == nil { - c.debug(logLinkRequestOldNodeNotFound{ + c.debug(ctx, logLinkRequestOldNodeNotFound{ Request: r.Hdr(), In: r, }) done(fuse.EIO) - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) break } n2, err := n.Link(ctx, r, oldNode.node) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } s := &fuse.LookupResponse{} c.saveLookup(s, snode, r.NewName, n2) done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.RemoveRequest: n, ok := node.(NodeRemover) if !ok { done(fuse.EIO) /// XXX or EPERM? - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) break } err := n.Remove(ctx, r) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } done(nil) - r.Respond() + r.Respond(ctx, ) case *fuse.AccessRequest: if n, ok := node.(NodeAccesser); ok { if err := n.Access(ctx, r); err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } } done(nil) - r.Respond() + r.Respond(ctx, ) case *fuse.LookupRequest: var n2 Node @@ -893,35 +893,35 @@ func (c *serveConn) serve(r fuse.Request) { n2, err = n.Lookup(ctx, r, s) } else { done(fuse.ENOENT) - r.RespondError(fuse.ENOENT) + r.RespondError(ctx, fuse.ENOENT) break } if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } c.saveLookup(s, snode, r.Name, n2) done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.MkdirRequest: s := &fuse.MkdirResponse{} n, ok := node.(NodeMkdirer) if !ok { done(fuse.EPERM) - r.RespondError(fuse.EPERM) + r.RespondError(ctx, fuse.EPERM) break } n2, err := n.Mkdir(ctx, r) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } c.saveLookup(&s.LookupResponse, snode, r.Name, n2) done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.OpenRequest: s := &fuse.OpenResponse{} @@ -930,7 +930,7 @@ func (c *serveConn) serve(r fuse.Request) { hh, err := n.Open(ctx, r, s) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } h2 = hh @@ -939,106 +939,106 @@ func (c *serveConn) serve(r fuse.Request) { } s.Handle = c.saveHandle(h2, hdr.Node) done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.CreateRequest: n, ok := node.(NodeCreater) if !ok { // If we send back ENOSYS, FUSE will try mknod+open. done(fuse.EPERM) - r.RespondError(fuse.EPERM) + r.RespondError(ctx, fuse.EPERM) break } s := &fuse.CreateResponse{OpenResponse: fuse.OpenResponse{}} n2, h2, err := n.Create(ctx, r, s) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } c.saveLookup(&s.LookupResponse, snode, r.Name, n2) s.Handle = c.saveHandle(h2, hdr.Node) done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.GetxattrRequest: n, ok := node.(NodeGetxattrer) if !ok { done(fuse.ENOTSUP) - r.RespondError(fuse.ENOTSUP) + r.RespondError(ctx, fuse.ENOTSUP) break } s := &fuse.GetxattrResponse{} err := n.Getxattr(ctx, r, s) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } if r.Size != 0 && uint64(len(s.Xattr)) > uint64(r.Size) { done(fuse.ERANGE) - r.RespondError(fuse.ERANGE) + r.RespondError(ctx, fuse.ERANGE) break } done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.ListxattrRequest: n, ok := node.(NodeListxattrer) if !ok { done(fuse.ENOTSUP) - r.RespondError(fuse.ENOTSUP) + r.RespondError(ctx, fuse.ENOTSUP) break } s := &fuse.ListxattrResponse{} err := n.Listxattr(ctx, r, s) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } if r.Size != 0 && uint64(len(s.Xattr)) > uint64(r.Size) { done(fuse.ERANGE) - r.RespondError(fuse.ERANGE) + r.RespondError(ctx, fuse.ERANGE) break } done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.SetxattrRequest: n, ok := node.(NodeSetxattrer) if !ok { done(fuse.ENOTSUP) - r.RespondError(fuse.ENOTSUP) + r.RespondError(ctx, fuse.ENOTSUP) break } err := n.Setxattr(ctx, r) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } done(nil) - r.Respond() + r.Respond(ctx, ) case *fuse.RemovexattrRequest: n, ok := node.(NodeRemovexattrer) if !ok { done(fuse.ENOTSUP) - r.RespondError(fuse.ENOTSUP) + r.RespondError(ctx, fuse.ENOTSUP) break } err := n.Removexattr(ctx, r) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } done(nil) - r.Respond() + r.Respond(ctx, ) case *fuse.ForgetRequest: - forget := c.dropNode(hdr.Node, r.N) + forget := c.dropNode(ctx, hdr.Node, r.N) if forget { n, ok := node.(NodeForgetter) if ok { @@ -1046,14 +1046,14 @@ func (c *serveConn) serve(r fuse.Request) { } } done(nil) - r.Respond() + r.Respond(ctx, ) // Handle operations. case *fuse.ReadRequest: - shandle := c.getHandle(r.Handle) + shandle := c.getHandle(ctx, r.Handle) if shandle == nil { done(fuse.ESTALE) - r.RespondError(fuse.ESTALE) + r.RespondError(ctx, fuse.ESTALE) return } handle := shandle.handle @@ -1065,7 +1065,7 @@ func (c *serveConn) serve(r fuse.Request) { dirs, err := h.ReadDirAll(ctx) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } var data []byte @@ -1079,7 +1079,7 @@ func (c *serveConn) serve(r fuse.Request) { } fuseutil.HandleRead(r, s, shandle.readData) done(s) - r.Respond(s) + r.Respond(ctx, s) break } } else { @@ -1088,7 +1088,7 @@ func (c *serveConn) serve(r fuse.Request) { data, err := h.ReadAll(ctx) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } if data == nil { @@ -1098,30 +1098,30 @@ func (c *serveConn) serve(r fuse.Request) { } fuseutil.HandleRead(r, s, shandle.readData) done(s) - r.Respond(s) + r.Respond(ctx, s) break } h, ok := handle.(HandleReader) if !ok { fmt.Printf("NO READ FOR %T\n", handle) done(fuse.EIO) - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) break } if err := h.Read(ctx, r, s); err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } } done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.WriteRequest: - shandle := c.getHandle(r.Handle) + shandle := c.getHandle(ctx, r.Handle) if shandle == nil { done(fuse.ESTALE) - r.RespondError(fuse.ESTALE) + r.RespondError(ctx, fuse.ESTALE) return } @@ -1129,21 +1129,21 @@ func (c *serveConn) serve(r fuse.Request) { if h, ok := shandle.handle.(HandleWriter); ok { if err := h.Write(ctx, r, s); err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } done(s) - r.Respond(s) + r.Respond(ctx, s) break } done(fuse.EIO) - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) case *fuse.FlushRequest: - shandle := c.getHandle(r.Handle) + shandle := c.getHandle(ctx, r.Handle) if shandle == nil { done(fuse.ESTALE) - r.RespondError(fuse.ESTALE) + r.RespondError(ctx, fuse.ESTALE) return } handle := shandle.handle @@ -1151,18 +1151,18 @@ func (c *serveConn) serve(r fuse.Request) { if h, ok := handle.(HandleFlusher); ok { if err := h.Flush(ctx, r); err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } } done(nil) - r.Respond() + r.Respond(ctx, ) case *fuse.ReleaseRequest: - shandle := c.getHandle(r.Handle) + shandle := c.getHandle(ctx, r.Handle) if shandle == nil { done(fuse.ESTALE) - r.RespondError(fuse.ESTALE) + r.RespondError(ctx, fuse.ESTALE) return } handle := shandle.handle @@ -1173,19 +1173,19 @@ func (c *serveConn) serve(r fuse.Request) { if h, ok := handle.(HandleReleaser); ok { if err := h.Release(ctx, r); err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } } done(nil) - r.Respond() + r.Respond(ctx, ) case *fuse.DestroyRequest: if fs, ok := c.fs.(FSDestroyer); ok { fs.Destroy() } done(nil) - r.Respond() + r.Respond(ctx, ) case *fuse.RenameRequest: c.meta.Lock() @@ -1195,62 +1195,62 @@ func (c *serveConn) serve(r fuse.Request) { } c.meta.Unlock() if newDirNode == nil { - c.debug(renameNewDirNodeNotFound{ + c.debug(ctx, renameNewDirNodeNotFound{ Request: r.Hdr(), In: r, }) done(fuse.EIO) - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) break } n, ok := node.(NodeRenamer) if !ok { done(fuse.EIO) // XXX or EPERM like Mkdir? - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) break } err := n.Rename(ctx, r, newDirNode.node) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } done(nil) - r.Respond() + r.Respond(ctx, ) case *fuse.MknodRequest: n, ok := node.(NodeMknoder) if !ok { done(fuse.EIO) - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) break } n2, err := n.Mknod(ctx, r) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } s := &fuse.LookupResponse{} c.saveLookup(s, snode, r.Name, n2) done(s) - r.Respond(s) + r.Respond(ctx, s) case *fuse.FsyncRequest: n, ok := node.(NodeFsyncer) if !ok { done(fuse.EIO) - r.RespondError(fuse.EIO) + r.RespondError(ctx, fuse.EIO) break } err := n.Fsync(ctx, r) if err != nil { done(err) - r.RespondError(err) + r.RespondError(ctx, err) break } done(nil) - r.Respond() + r.Respond(ctx, ) case *fuse.InterruptRequest: c.meta.Lock() @@ -1261,23 +1261,23 @@ func (c *serveConn) serve(r fuse.Request) { } c.meta.Unlock() done(nil) - r.Respond() + r.Respond(ctx, ) /* case *FsyncdirRequest: done(ENOSYS) - r.RespondError(ENOSYS) + r.RespondError(ctx, ENOSYS) case *GetlkRequest, *SetlkRequest, *SetlkwRequest: done(ENOSYS) - r.RespondError(ENOSYS) + r.RespondError(ctx, ENOSYS) case *BmapRequest: done(ENOSYS) - r.RespondError(ENOSYS) + r.RespondError(ctx, ENOSYS) case *SetvolnameRequest, *GetxtimesRequest, *ExchangeRequest: done(ENOSYS) - r.RespondError(ENOSYS) + r.RespondError(ctx, ENOSYS) */ } } diff --git a/fuse.go b/fuse.go index ea3190ad..26247c64 100644 --- a/fuse.go +++ b/fuse.go @@ -111,6 +111,8 @@ import ( "syscall" "time" "unsafe" + + "golang.org/x/net/context" ) // A Conn represents a connection to a mounted FUSE file system. @@ -170,7 +172,7 @@ type Request interface { Hdr() *Header // RespondError responds to the request with the given error. - RespondError(error) + RespondError(context.Context, error) String() string } @@ -215,8 +217,8 @@ func (h *Header) noResponse() { putMessage(h.msg) } -func (h *Header) respond(out *outHeader, n uintptr) { - h.Conn.respond(out, n) +func (h *Header) respond(ctx context.Context, out *outHeader, n uintptr) { + h.Conn.respond(ctx, out, n) putMessage(h.msg) } @@ -301,7 +303,7 @@ func (e Errno) MarshalText() ([]byte, error) { return []byte(s), nil } -func (h *Header) RespondError(err error) { +func (h *Header) RespondError(ctx context.Context, err error) { errno := DefaultErrno if ferr, ok := err.(ErrorNumber); ok { errno = ferr.Errno() @@ -309,7 +311,7 @@ func (h *Header) RespondError(err error) { // FUSE uses negative errors! // TODO: File bug report against OSXFUSE: positive error causes kernel panic. out := &outHeader{Error: -int32(errno), Unique: uint64(h.ID)} - h.respond(out, unsafe.Sizeof(*out)) + h.respond(ctx, out, unsafe.Sizeof(*out)) } // Maximum file write size we are prepared to receive from the kernel. @@ -453,7 +455,7 @@ func (c *Conn) fd() int { // // Caller must call either Request.Respond or Request.RespondError in // a reasonable time. Caller must not retain Request after that call. -func (c *Conn) ReadRequest() (Request, error) { +func (c *Conn) ReadRequest(ctx context.Context) (Request, error) { m := getMessage(c) loop: c.rio.RLock() @@ -504,7 +506,7 @@ loop: var req Request switch m.hdr.Opcode { default: - Debug(noOpcode{Opcode: m.hdr.Opcode}) + Debug(ctx, noOpcode{Opcode: m.hdr.Opcode}) goto unrecognized case opLookup: @@ -893,7 +895,7 @@ loop: return req, nil corrupt: - Debug(malformedMessage{}) + Debug(ctx, malformedMessage{}) putMessage(m) return nil, fmt.Errorf("fuse: malformed message") @@ -923,14 +925,14 @@ func errorString(err error) string { return err.Error() } -func (c *Conn) respond(out *outHeader, n uintptr) { +func (c *Conn) respond(ctx context.Context, out *outHeader, n uintptr) { c.wio.Lock() defer c.wio.Unlock() out.Len = uint32(n) msg := (*[1 << 30]byte)(unsafe.Pointer(out))[:n] nn, err := syscall.Write(c.fd(), msg) if nn != len(msg) || err != nil { - Debug(bugShortKernelWrite{ + Debug(ctx, bugShortKernelWrite{ Written: int64(nn), Length: int64(len(msg)), Error: errorString(err), @@ -982,7 +984,7 @@ func (r *InitResponse) String() string { } // Respond replies to the request with the given response. -func (r *InitRequest) Respond(resp *InitResponse) { +func (r *InitRequest) Respond(ctx context.Context, resp *InitResponse) { out := &initOut{ outHeader: outHeader{Unique: uint64(r.ID)}, Major: kernelVersion, @@ -996,7 +998,7 @@ func (r *InitRequest) Respond(resp *InitResponse) { if out.MaxWrite > maxWrite { out.MaxWrite = maxWrite } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A StatfsRequest requests information about the mounted file system. @@ -1011,7 +1013,7 @@ func (r *StatfsRequest) String() string { } // Respond replies to the request with the given response. -func (r *StatfsRequest) Respond(resp *StatfsResponse) { +func (r *StatfsRequest) Respond(ctx context.Context, resp *StatfsResponse) { out := &statfsOut{ outHeader: outHeader{Unique: uint64(r.ID)}, St: kstatfs{ @@ -1024,7 +1026,7 @@ func (r *StatfsRequest) Respond(resp *StatfsResponse) { Frsize: resp.Frsize, }, } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A StatfsResponse is the response to a StatfsRequest. @@ -1058,9 +1060,9 @@ func (r *AccessRequest) String() string { // Respond replies to the request indicating that access is allowed. // To deny access, use RespondError. -func (r *AccessRequest) Respond() { +func (r *AccessRequest) Respond(ctx context.Context) { out := &outHeader{Unique: uint64(r.ID)} - r.respond(out, unsafe.Sizeof(*out)) + r.respond(ctx, out, unsafe.Sizeof(*out)) } // An Attr is the metadata for a single file or directory. @@ -1141,14 +1143,14 @@ func (r *GetattrRequest) String() string { } // Respond replies to the request with the given response. -func (r *GetattrRequest) Respond(resp *GetattrResponse) { +func (r *GetattrRequest) Respond(ctx context.Context, resp *GetattrResponse) { out := &attrOut{ outHeader: outHeader{Unique: uint64(r.ID)}, AttrValid: uint64(resp.AttrValid / time.Second), AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond), Attr: resp.Attr.attr(), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A GetattrResponse is the response to a GetattrRequest. @@ -1185,13 +1187,13 @@ func (r *GetxattrRequest) String() string { } // Respond replies to the request with the given response. -func (r *GetxattrRequest) Respond(resp *GetxattrResponse) { +func (r *GetxattrRequest) Respond(ctx context.Context, resp *GetxattrResponse) { if r.Size == 0 { out := &getxattrOut{ outHeader: outHeader{Unique: uint64(r.ID)}, Size: uint32(len(resp.Xattr)), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } else { out := &outHeader{Unique: uint64(r.ID)} r.respondData(out, unsafe.Sizeof(*out), resp.Xattr) @@ -1221,13 +1223,13 @@ func (r *ListxattrRequest) String() string { } // Respond replies to the request with the given response. -func (r *ListxattrRequest) Respond(resp *ListxattrResponse) { +func (r *ListxattrRequest) Respond(ctx context.Context, resp *ListxattrResponse) { if r.Size == 0 { out := &getxattrOut{ outHeader: outHeader{Unique: uint64(r.ID)}, Size: uint32(len(resp.Xattr)), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } else { out := &outHeader{Unique: uint64(r.ID)} r.respondData(out, unsafe.Sizeof(*out), resp.Xattr) @@ -1264,9 +1266,9 @@ func (r *RemovexattrRequest) String() string { } // Respond replies to the request, indicating that the attribute was removed. -func (r *RemovexattrRequest) Respond() { +func (r *RemovexattrRequest) Respond(ctx context.Context) { out := &outHeader{Unique: uint64(r.ID)} - r.respond(out, unsafe.Sizeof(*out)) + r.respond(ctx, out, unsafe.Sizeof(*out)) } // A SetxattrRequest asks to set an extended attribute associated with a file. @@ -1309,9 +1311,9 @@ func (r *SetxattrRequest) String() string { } // Respond replies to the request, indicating that the extended attribute was set. -func (r *SetxattrRequest) Respond() { +func (r *SetxattrRequest) Respond(ctx context.Context) { out := &outHeader{Unique: uint64(r.ID)} - r.respond(out, unsafe.Sizeof(*out)) + r.respond(ctx, out, unsafe.Sizeof(*out)) } // A LookupRequest asks to look up the given name in the directory named by r.Node. @@ -1327,7 +1329,7 @@ func (r *LookupRequest) String() string { } // Respond replies to the request with the given response. -func (r *LookupRequest) Respond(resp *LookupResponse) { +func (r *LookupRequest) Respond(ctx context.Context, resp *LookupResponse) { out := &entryOut{ outHeader: outHeader{Unique: uint64(r.ID)}, Nodeid: uint64(resp.Node), @@ -1338,7 +1340,7 @@ func (r *LookupRequest) Respond(resp *LookupResponse) { AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond), Attr: resp.Attr.attr(), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A LookupResponse is the response to a LookupRequest. @@ -1368,13 +1370,13 @@ func (r *OpenRequest) String() string { } // Respond replies to the request with the given response. -func (r *OpenRequest) Respond(resp *OpenResponse) { +func (r *OpenRequest) Respond(ctx context.Context, resp *OpenResponse) { out := &openOut{ outHeader: outHeader{Unique: uint64(r.ID)}, Fh: uint64(resp.Handle), OpenFlags: uint32(resp.Flags), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A OpenResponse is the response to a OpenRequest. @@ -1402,7 +1404,7 @@ func (r *CreateRequest) String() string { } // Respond replies to the request with the given response. -func (r *CreateRequest) Respond(resp *CreateResponse) { +func (r *CreateRequest) Respond(ctx context.Context, resp *CreateResponse) { out := &createOut{ outHeader: outHeader{Unique: uint64(r.ID)}, @@ -1417,7 +1419,7 @@ func (r *CreateRequest) Respond(resp *CreateResponse) { Fh: uint64(resp.Handle), OpenFlags: uint32(resp.Flags), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A CreateResponse is the response to a CreateRequest. @@ -1445,7 +1447,7 @@ func (r *MkdirRequest) String() string { } // Respond replies to the request with the given response. -func (r *MkdirRequest) Respond(resp *MkdirResponse) { +func (r *MkdirRequest) Respond(ctx context.Context, resp *MkdirResponse) { out := &entryOut{ outHeader: outHeader{Unique: uint64(r.ID)}, Nodeid: uint64(resp.Node), @@ -1456,7 +1458,7 @@ func (r *MkdirRequest) Respond(resp *MkdirResponse) { AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond), Attr: resp.Attr.attr(), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A MkdirResponse is the response to a MkdirRequest. @@ -1484,7 +1486,7 @@ func (r *ReadRequest) String() string { } // Respond replies to the request with the given response. -func (r *ReadRequest) Respond(resp *ReadResponse) { +func (r *ReadRequest) Respond(ctx context.Context, resp *ReadResponse) { out := &outHeader{Unique: uint64(r.ID)} r.respondData(out, unsafe.Sizeof(*out), resp.Data) } @@ -1526,9 +1528,9 @@ func (r *ReleaseRequest) String() string { } // Respond replies to the request, indicating that the handle has been released. -func (r *ReleaseRequest) Respond() { +func (r *ReleaseRequest) Respond(ctx context.Context) { out := &outHeader{Unique: uint64(r.ID)} - r.respond(out, unsafe.Sizeof(*out)) + r.respond(ctx, out, unsafe.Sizeof(*out)) } // A DestroyRequest is sent by the kernel when unmounting the file system. @@ -1545,9 +1547,9 @@ func (r *DestroyRequest) String() string { } // Respond replies to the request. -func (r *DestroyRequest) Respond() { +func (r *DestroyRequest) Respond(ctx context.Context) { out := &outHeader{Unique: uint64(r.ID)} - r.respond(out, unsafe.Sizeof(*out)) + r.respond(ctx, out, unsafe.Sizeof(*out)) } // A ForgetRequest is sent by the kernel when forgetting about r.Node @@ -1564,7 +1566,7 @@ func (r *ForgetRequest) String() string { } // Respond replies to the request, indicating that the forgetfulness has been recorded. -func (r *ForgetRequest) Respond() { +func (r *ForgetRequest) Respond(ctx context.Context) { // Don't reply to forget messages. r.noResponse() } @@ -1683,12 +1685,12 @@ func (r *WriteRequest) MarshalJSON() ([]byte, error) { } // Respond replies to the request with the given response. -func (r *WriteRequest) Respond(resp *WriteResponse) { +func (r *WriteRequest) Respond(ctx context.Context, resp *WriteResponse) { out := &writeOut{ outHeader: outHeader{Unique: uint64(r.ID)}, Size: uint32(resp.Size), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A WriteResponse replies to a write indicating how many bytes were written. @@ -1774,14 +1776,14 @@ func (r *SetattrRequest) String() string { // Respond replies to the request with the given response, // giving the updated attributes. -func (r *SetattrRequest) Respond(resp *SetattrResponse) { +func (r *SetattrRequest) Respond(ctx context.Context, resp *SetattrResponse) { out := &attrOut{ outHeader: outHeader{Unique: uint64(r.ID)}, AttrValid: uint64(resp.AttrValid / time.Second), AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond), Attr: resp.Attr.attr(), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A SetattrResponse is the response to a SetattrRequest. @@ -1811,9 +1813,9 @@ func (r *FlushRequest) String() string { } // Respond replies to the request, indicating that the flush succeeded. -func (r *FlushRequest) Respond() { +func (r *FlushRequest) Respond(ctx context.Context) { out := &outHeader{Unique: uint64(r.ID)} - r.respond(out, unsafe.Sizeof(*out)) + r.respond(ctx, out, unsafe.Sizeof(*out)) } // A RemoveRequest asks to remove a file or directory from the @@ -1831,9 +1833,9 @@ func (r *RemoveRequest) String() string { } // Respond replies to the request, indicating that the file was removed. -func (r *RemoveRequest) Respond() { +func (r *RemoveRequest) Respond(ctx context.Context) { out := &outHeader{Unique: uint64(r.ID)} - r.respond(out, unsafe.Sizeof(*out)) + r.respond(ctx, out, unsafe.Sizeof(*out)) } // A SymlinkRequest is a request to create a symlink making NewName point to Target. @@ -1849,7 +1851,7 @@ func (r *SymlinkRequest) String() string { } // Respond replies to the request, indicating that the symlink was created. -func (r *SymlinkRequest) Respond(resp *SymlinkResponse) { +func (r *SymlinkRequest) Respond(ctx context.Context, resp *SymlinkResponse) { out := &entryOut{ outHeader: outHeader{Unique: uint64(r.ID)}, Nodeid: uint64(resp.Node), @@ -1860,7 +1862,7 @@ func (r *SymlinkRequest) Respond(resp *SymlinkResponse) { AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond), Attr: resp.Attr.attr(), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A SymlinkResponse is the response to a SymlinkRequest. @@ -1879,7 +1881,7 @@ func (r *ReadlinkRequest) String() string { return fmt.Sprintf("Readlink [%s]", &r.Header) } -func (r *ReadlinkRequest) Respond(target string) { +func (r *ReadlinkRequest) Respond(ctx context.Context, target string) { out := &outHeader{Unique: uint64(r.ID)} r.respondData(out, unsafe.Sizeof(*out), []byte(target)) } @@ -1897,7 +1899,7 @@ func (r *LinkRequest) String() string { return fmt.Sprintf("Link [%s] node %d to %q", &r.Header, r.OldNode, r.NewName) } -func (r *LinkRequest) Respond(resp *LookupResponse) { +func (r *LinkRequest) Respond(ctx context.Context, resp *LookupResponse) { out := &entryOut{ outHeader: outHeader{Unique: uint64(r.ID)}, Nodeid: uint64(resp.Node), @@ -1908,7 +1910,7 @@ func (r *LinkRequest) Respond(resp *LookupResponse) { AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond), Attr: resp.Attr.attr(), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A RenameRequest is a request to rename a file. @@ -1924,9 +1926,9 @@ func (r *RenameRequest) String() string { return fmt.Sprintf("Rename [%s] from %q to dirnode %d %q", &r.Header, r.OldName, r.NewDir, r.NewName) } -func (r *RenameRequest) Respond() { +func (r *RenameRequest) Respond(ctx context.Context) { out := &outHeader{Unique: uint64(r.ID)} - r.respond(out, unsafe.Sizeof(*out)) + r.respond(ctx, out, unsafe.Sizeof(*out)) } type MknodRequest struct { @@ -1942,7 +1944,7 @@ func (r *MknodRequest) String() string { return fmt.Sprintf("Mknod [%s] Name %q mode %v rdev %d", &r.Header, r.Name, r.Mode, r.Rdev) } -func (r *MknodRequest) Respond(resp *LookupResponse) { +func (r *MknodRequest) Respond(ctx context.Context, resp *LookupResponse) { out := &entryOut{ outHeader: outHeader{Unique: uint64(r.ID)}, Nodeid: uint64(resp.Node), @@ -1953,7 +1955,7 @@ func (r *MknodRequest) Respond(resp *LookupResponse) { AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond), Attr: resp.Attr.attr(), } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } type FsyncRequest struct { @@ -1970,9 +1972,9 @@ func (r *FsyncRequest) String() string { return fmt.Sprintf("Fsync [%s] Handle %v Flags %v", &r.Header, r.Handle, r.Flags) } -func (r *FsyncRequest) Respond() { +func (r *FsyncRequest) Respond(ctx context.Context) { out := &outHeader{Unique: uint64(r.ID)} - r.respond(out, unsafe.Sizeof(*out)) + r.respond(ctx, out, unsafe.Sizeof(*out)) } // An InterruptRequest is a request to interrupt another pending request. The @@ -1984,7 +1986,7 @@ type InterruptRequest struct { var _ = Request(&InterruptRequest{}) -func (r *InterruptRequest) Respond() { +func (r *InterruptRequest) Respond(ctx context.Context) { // nothing to do here r.noResponse() } @@ -2008,12 +2010,12 @@ func (r *XXXRequest) String() string { } // Respond replies to the request with the given response. -func (r *XXXRequest) Respond(resp *XXXResponse) { +func (r *XXXRequest) Respond(ctx context.Context, resp *XXXResponse) { out := &xxxOut{ outHeader: outHeader{Unique: uint64(r.ID)}, xxx, } - r.respond(&out.outHeader, unsafe.Sizeof(*out)) + r.respond(ctx, &out.outHeader, unsafe.Sizeof(*out)) } // A XXXResponse is the response to a XXXRequest. diff --git a/hellofs/hello.go b/hellofs/hello.go index 5d9febe7..65a0fa1e 100644 --- a/hellofs/hello.go +++ b/hellofs/hello.go @@ -41,7 +41,7 @@ func main() { } defer c.Close() - err = fs.Serve(c, FS{}) + err = fs.Serve(context.Background(), c, FS{}) if err != nil { log.Fatal(err) }