Skip to content

Commit

Permalink
Add handle-specific attr and fsync interfaces
Browse files Browse the repository at this point in the history
Getattr and Setattr requests can either happen on a fs.Node or an
fs.Handle (depending on the call that initiated it e.g. truncate vs
ftruncate or stat vs fstat). Add HandleGetattrer and HandleSetattrer so
implementations can provide handle-specific overrides when those
operations are performed on an open file descriptor.

Also create HandleFsyncer and deprecate NodeFsyncer to resolve the TODO.

Resolves bazil#225.
  • Loading branch information
MikaelSmith committed Dec 12, 2019
1 parent 65cc252 commit 25f900d
Showing 1 changed file with 67 additions and 5 deletions.
72 changes: 67 additions & 5 deletions fs/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ type NodeMknoder interface {
Mknod(ctx context.Context, req *fuse.MknodRequest) (Node, error)
}

// TODO this should be on Handle not Node
// NodeFsyncer is deprecated. Use HandleFsyncer instead.
type NodeFsyncer interface {
Fsync(ctx context.Context, req *fuse.FsyncRequest) error
}
Expand Down Expand Up @@ -282,6 +282,32 @@ type HandleFlusher interface {
Flush(ctx context.Context, req *fuse.FlushRequest) error
}

type HandleFsyncer interface {
Fsync(ctx context.Context, req *fuse.FsyncRequest) error
}

type HandleGetattrer interface {
// Getattr obtains the standard metadata related to an open file handle.
// It should store that metadata in resp.
//
// If this method is not implemented, it will defer to NodeGetattrer.
Getattr(ctx context.Context, req *fuse.GetattrRequest, resp *fuse.GetattrResponse) error
}

type HandleSetattrer interface {
// Setattr sets the standard metadata related to an open file handle.
//
// If this method is not implemented, it will defer to NodeSetattrer.
//
// Note, this is also used to communicate changes in the size of
// the file, outside of Writes.
//
// req.Valid is a bitmask of what fields are actually being set.
// For example, the method should not change the mode of the file
// unless req.Valid.Mode() is true.
Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error
}

type HandleReadAller interface {
ReadAll(ctx context.Context) ([]byte, error)
}
Expand Down Expand Up @@ -926,6 +952,19 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode,
// Node operations.
case *fuse.GetattrRequest:
s := &fuse.GetattrResponse{}

// Try Getattr on the handle (if set) before falling back to node attributes.
if shandle := c.getHandle(r.Handle); shandle != nil {
if h, ok := shandle.handle.(HandleGetattrer); ok {
if err := h.Getattr(ctx, r, s); err != nil {
return err
}
done(s)
r.Respond(s)
return nil
}
}

if n, ok := node.(NodeGetattrer); ok {
if err := n.Getattr(ctx, r, s); err != nil {
return err
Expand All @@ -941,7 +980,19 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode,

case *fuse.SetattrRequest:
s := &fuse.SetattrResponse{}
if n, ok := node.(NodeSetattrer); ok {
var set bool

// Try Setattr on the handle (if set) before falling back to node attributes.
if shandle := c.getHandle(r.Handle); shandle != nil {
if h, ok := shandle.handle.(HandleSetattrer); ok {
if err := h.Setattr(ctx, r, s); err != nil {
return err
}
set = true
}
}

if n, ok := node.(NodeSetattrer); ok && !set {
if err := n.Setattr(ctx, r, s); err != nil {
return err
}
Expand Down Expand Up @@ -1359,14 +1410,25 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode,
return nil

case *fuse.FsyncRequest:
n, ok := node.(NodeFsyncer)
if !ok {
shandle := c.getHandle(r.Handle)
if shandle == nil {
return fuse.ESTALE
}
handle := shandle.handle

var err error
if h, ok := handle.(HandleFsyncer); ok {
err = h.Fsync(ctx, r)
} else if n, ok := node.(NodeFsyncer); ok {
err = n.Fsync(ctx, r)
} else {
return fuse.EIO
}
err := n.Fsync(ctx, r)

if err != nil {
return err
}

done(nil)
r.Respond()
return nil
Expand Down

0 comments on commit 25f900d

Please sign in to comment.