作者:rsrsp
项目:fus
func (c *serveConn) serve(fs FS, r fuse.Request) {
intr := make(Intr)
req := &serveRequest{Request: r, Intr: intr}
fuse.Debugf("<- %s", req)
var node Node
var snode *serveNode
c.meta.Lock()
hdr := r.Hdr()
if id := hdr.Node; id != 0 {
if id < fuse.NodeID(len(c.node)) {
snode = c.node[uint(id)]
}
if snode == nil {
c.meta.Unlock()
println("missing node", id, len(c.node), snode)
fuse.Debugf("-> %#x %v", hdr.ID, fuse.ESTALE)
r.RespondError(fuse.ESTALE)
return
}
node = snode.node
}
if c.req[hdr.ID] != nil {
// This happens with OSXFUSE. Assume it's okay and
// that we'll never see an interrupt for this one.
// Otherwise everything wedges. TODO: Report to OSXFUSE?
intr = nil
} else {
c.req[hdr.ID] = req
}
c.meta.Unlock()
// Call this before responding.
// After responding is too late: we might get another request
// with the same ID and be very confused.
done := func(resp interface{}) {
fuse.Debugf("-> %#x %v", hdr.ID, resp)
c.meta.Lock()
c.req[hdr.ID] = nil
c.meta.Unlock()
}
switch r := r.(type) {
default:
// Note: To FUSE, ENOSYS means "this server never implements this 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)
// FS operations.
case *fuse.InitRequest:
s := &fuse.InitResponse{
MaxWrite: 4096,
}
if fs, ok := fs.(FSIniter); ok {
if err := fs.Init(r, s, intr); err != nil {
done(err)
r.RespondError(err)
break
}
}
done(s)
r.Respond(s)
case *fuse.StatfsRequest:
s := &fuse.StatfsResponse{}
if fs, ok := fs.(FSStatfser); ok {
if err := fs.Statfs(r, s, intr); err != nil {
done(err)
r.RespondError(err)
break
}
}
done(s)
r.Respond(s)
// Node operations.
case *fuse.GetattrRequest:
s := &fuse.GetattrResponse{}
if n, ok := node.(NodeGetattrer); ok {
if err := n.Getattr(r, s, intr); err != nil {
done(err)
r.RespondError(err)
break
}
} else {
s.AttrValid = 1 * time.Minute
s.Attr = snode.attr()
}
done(s)
r.Respond(s)
case *fuse.SetattrRequest:
s := &fuse.SetattrResponse{}
// Special-case truncation, if no other bits are set
// and the open Handles all have a WriteAll method.
//
// TODO WriteAll mishandles all kinds of cases, e.g.
//.........这里部分代码省略.........
作者:seacoastbo
项目:fus
func (c *serveConn) serve(r fuse.Request) {
intr := make(Intr)
req := &serveRequest{Request: r, Intr: intr}
c.debug(request{
Op: opName(r),
Request: r.Hdr(),
In: r,
})
var node Node
var snode *serveNode
c.meta.Lock()
hdr := r.Hdr()
if id := hdr.Node; id != 0 {
if id < fuse.NodeID(len(c.node)) {
snode = c.node[uint(id)]
}
if snode == nil {
c.meta.Unlock()
c.debug(response{
Op: opName(r),
Request: logResponseHeader{ID: hdr.ID},
Error: fuse.ESTALE.ErrnoName(),
// this is the only place that sets both Error and
// Out; not sure if i want to do that; might get rid
// of len(c.node) things altogether
Out: logMissingNode{
MaxNode: fuse.NodeID(len(c.node)),
},
})
r.RespondError(fuse.ESTALE)
return
}
node = snode.node
}
if c.req[hdr.ID] != nil {
// This happens with OSXFUSE. Assume it's okay and
// that we'll never see an interrupt for this one.
// Otherwise everything wedges. TODO: Report to OSXFUSE?
//
// TODO this might have been because of missing done() calls
intr = nil
} else {
c.req[hdr.ID] = req
}
c.meta.Unlock()
// Call this before responding.
// After responding is too late: we might get another request
// with the same ID and be very confused.
done := func(resp interface{}) {
msg := response{
Op: opName(r),
Request: logResponseHeader{ID: hdr.ID},
}
if err, ok := resp.(error); ok {
msg.Error = err.Error()
if ferr, ok := err.(fuse.ErrorNumber); ok {
errno := ferr.Errno()
msg.Errno = errno.ErrnoName()
if errno == err {
// it's just a fuse.Errno with no extra detail;
// skip the textual message for log readability
msg.Error = ""
}
} else {
msg.Errno = fuse.DefaultErrno.ErrnoName()
}
} else {
msg.Out = resp
}
c.debug(msg)
c.meta.Lock()
delete(c.req, hdr.ID)
c.meta.Unlock()
}
switch r := r.(type) {
default:
// Note: To FUSE, ENOSYS means "this server never implements this 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)
// FS operations.
case *fuse.InitRequest:
s := &fuse.InitResponse{
MaxWrite: 128 * 1024,
Flags: fuse.InitBigWrites,
}
if fs, ok := c.fs.(FSIniter); ok {
if err := fs.Init(r, s, intr); err != nil {
done(err)
r.RespondError(err)
break
}
}
done(s)
//.........这里部分代码省略.........
作者:rjkroeg
项目:fus
// Record a fuse.Request, after zeroing header fields that are hard to
// reproduce.
//
// Make sure to record a copy, not the original request.
func (r *RequestRecorder) RecordRequest(req fuse.Request) {
hdr := req.Hdr()
*hdr = fuse.Header{}
r.rec.Record(req)
}
作者:keybas
项目:kbfs-bet
// handleRequest will either a) call done(s) and r.Respond(s) OR b) return an error.
func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, r fuse.Request, done func(resp interface{})) error {
switch r := r.(type) {
default:
// Note: To FUSE, ENOSYS means "this server never implements this request."
// It would be inappropriate to return ENOSYS for other operations in this
// switch that might only be unavailable in some contexts, not all.
return fuse.ENOSYS
case *fuse.StatfsRequest:
s := &fuse.StatfsResponse{}
if fs, ok := c.fs.(FSStatfser); ok {
if err := fs.Statfs(ctx, r, s); err != nil {
return err
}
}
done(s)
r.Respond(s)
return nil
// Node operations.
case *fuse.GetattrRequest:
s := &fuse.GetattrResponse{}
if n, ok := node.(NodeGetattrer); ok {
if err := n.Getattr(ctx, r, s); err != nil {
return err
}
} else {
if err := snode.attr(ctx, &s.Attr); err != nil {
return err
}
}
done(s)
r.Respond(s)
return nil
case *fuse.SetattrRequest:
s := &fuse.SetattrResponse{}
if n, ok := node.(NodeSetattrer); ok {
if err := n.Setattr(ctx, r, s); err != nil {
return err
}
}
if err := snode.attr(ctx, &s.Attr); err != nil {
return err
}
done(s)
r.Respond(s)
return nil
case *fuse.SymlinkRequest:
s := &fuse.SymlinkResponse{}
initLookupResponse(&s.LookupResponse)
n, ok := node.(NodeSymlinker)
if !ok {
return fuse.EIO // XXX or EPERM like Mkdir?
}
n2, err := n.Symlink(ctx, r)
if err != nil {
return err
}
if err := c.saveLookup(ctx, &s.LookupResponse, snode, r.NewName, n2); err != nil {
return err
}
done(s)
r.Respond(s)
return nil
case *fuse.ReadlinkRequest:
n, ok := node.(NodeReadlinker)
if !ok {
return fuse.EIO /// XXX or EPERM?
}
target, err := n.Readlink(ctx, r)
if err != nil {
return err
}
done(target)
r.Respond(target)
return nil
case *fuse.LinkRequest:
n, ok := node.(NodeLinker)
if !ok {
return fuse.EIO /// XXX or EPERM?
}
c.meta.Lock()
var oldNode *serveNode
if int(r.OldNode) < len(c.node) {
oldNode = c.node[r.OldNode]
}
c.meta.Unlock()
if oldNode == nil {
c.debug(logLinkRequestOldNodeNotFound{
Request: r.Hdr(),
In: r,
})
return fuse.EIO
}
//.........这里部分代码省略.........
作者:keybas
项目:kbfs-bet
func (c *Server) serve(r fuse.Request) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
parentCtx := ctx
if c.context != nil {
ctx = c.context(ctx, r)
}
req := &serveRequest{Request: r, cancel: cancel}
c.debug(request{
Op: opName(r),
Request: r.Hdr(),
In: r,
})
var node Node
var snode *serveNode
c.meta.Lock()
hdr := r.Hdr()
if id := hdr.Node; id != 0 {
if id < fuse.NodeID(len(c.node)) {
snode = c.node[uint(id)]
}
if snode == nil {
c.meta.Unlock()
c.debug(response{
Op: opName(r),
Request: logResponseHeader{ID: hdr.ID},
Error: fuse.ESTALE.ErrnoName(),
// this is the only place that sets both Error and
// Out; not sure if i want to do that; might get rid
// of len(c.node) things altogether
Out: logMissingNode{
MaxNode: fuse.NodeID(len(c.node)),
},
})
r.RespondError(fuse.ESTALE)
return
}
node = snode.node
}
if c.req[hdr.ID] != nil {
// This happens with OSXFUSE. Assume it's okay and
// that we'll never see an interrupt for this one.
// Otherwise everything wedges. TODO: Report to OSXFUSE?
//
// TODO this might have been because of missing done() calls
} else {
c.req[hdr.ID] = req
}
c.meta.Unlock()
// Call this before responding.
// After responding is too late: we might get another request
// with the same ID and be very confused.
done := func(resp interface{}) {
msg := response{
Op: opName(r),
Request: logResponseHeader{ID: hdr.ID},
}
if err, ok := resp.(error); ok {
msg.Error = err.Error()
if ferr, ok := err.(fuse.ErrorNumber); ok {
errno := ferr.Errno()
msg.Errno = errno.ErrnoName()
if errno == err {
// it's just a fuse.Errno with no extra detail;
// skip the textual message for log readability
msg.Error = ""
}
} else {
msg.Errno = fuse.DefaultErrno.ErrnoName()
}
} else {
msg.Out = resp
}
c.debug(msg)
c.meta.Lock()
delete(c.req, hdr.ID)
c.meta.Unlock()
}
var responded bool
defer func() {
if rec := recover(); rec != nil {
const size = 1 << 16
buf := make([]byte, size)
n := runtime.Stack(buf, false)
buf = buf[:n]
log.Printf("fuse: panic in handler for %v: %v\n%s", r, rec, buf)
err := handlerPanickedError{
Request: r,
Err: rec,
}
done(err)
r.RespondError(err)
return
}
//.........这里部分代码省略.........
作者:hatchlin
项目:fuse_gdriv
func (sc *serveConn) serve(req fuse.Request) {
switch req := req.(type) {
default:
// ENOSYS means "this server never implements this request."
//done(fuse.ENOSYS)
fuse.Debug(fmt.Sprintf("ENOSYS: %+v", req))
req.RespondError(fuse.ENOSYS)
case *fuse.InitRequest:
resp := fuse.InitResponse{MaxWrite: 128 * 1024,
Flags: fuse.InitBigWrites & fuse.InitAsyncRead,
}
req.Respond(&resp)
case *fuse.StatfsRequest:
var numfiles uint64
if f, err := sc.db.AllFileIds(); err != nil {
numfiles = uint64(len(f))
}
req.Respond(
&fuse.StatfsResponse{
Files: numfiles,
Bsize: blockSize,
},
)
case *fuse.GetattrRequest:
sc.getattr(req)
case *fuse.LookupRequest:
sc.lookup(req)
// Ack that the kernel has forgotten the metadata about an inode
case *fuse.ForgetRequest:
req.Respond()
// Hand back the inode as the HandleID
case *fuse.OpenRequest:
sc.open(req)
// Silently ignore attempts to change permissions
case *fuse.SetattrRequest:
inode := uint64(req.Header.Node)
f, err := sc.db.FileByInode(inode)
if err != nil {
fuse.Debug(fmt.Sprintf("FileByInode(%v): %v", inode, err))
req.RespondError(fuse.EIO)
return
}
req.Respond(&fuse.SetattrResponse{Attr: sc.attrFromFile(*f)})
case *fuse.CreateRequest:
// TODO: if allow_other, require uid == invoking uid to allow writes
sc.create(req)
// Return Dirents for directories, or requested portion of file
case *fuse.ReadRequest:
if req.Dir {
sc.readDir(req)
} else {
sc.read(req)
}
// Return MkdirResponse (it's LookupResponse, essentially) of new dir
case *fuse.MkdirRequest:
sc.mkdir(req)
// Removes the inode described by req.Header.Node
// Respond() for success, RespondError otherwise
case *fuse.RemoveRequest:
sc.remove(req)
// req.Header.Node describes the current parent directory
// req.NewDir describes the target directory (may be the same)
// req.OldName and req.NewName describe any (or no) change in name
case *fuse.RenameRequest:
sc.rename(req)
// Responds with the number of bytes written on success, RespondError otherwise
case *fuse.WriteRequest:
sc.write(req)
// Ack that the kernel has forgotten the metadata about an inode
case *fuse.FlushRequest:
req.Respond()
// Ack release of the kernel's mapping an inode->fileId
case *fuse.ReleaseRequest:
sc.release(req)
case *fuse.DestroyRequest:
req.Respond()
}
}
作者:wrees
项目:cfs-binary-releas
// Handle fuse request
func (f *fs) handle(r fuse.Request) {
switch r := r.(type) {
default:
log.Printf("Unhandled request: %v", r)
r.RespondError(fuse.ENOSYS)
case *fuse.GetattrRequest:
f.handleGetattr(r)
case *fuse.LookupRequest:
f.handleLookup(r)
case *fuse.MkdirRequest:
f.handleMkdir(r)
case *fuse.OpenRequest:
f.handleOpen(r)
case *fuse.ReadRequest:
f.handleRead(r)
case *fuse.WriteRequest:
f.handleWrite(r)
case *fuse.CreateRequest:
f.handleCreate(r)
case *fuse.SetattrRequest:
f.handleSetattr(r)
case *fuse.ReleaseRequest:
f.handleRelease(r)
case *fuse.FlushRequest:
f.handleFlush(r)
case *fuse.InterruptRequest:
f.handleInterrupt(r)
case *fuse.ForgetRequest:
f.handleForget(r)
case *fuse.RemoveRequest:
f.handleRemove(r)
case *fuse.AccessRequest:
f.handleAccess(r)
case *fuse.SymlinkRequest:
f.handleSymlink(r)
case *fuse.ReadlinkRequest:
f.handleReadlink(r)
case *fuse.GetxattrRequest:
f.handleGetxattr(r)
case *fuse.ListxattrRequest:
f.handleListxattr(r)
case *fuse.SetxattrRequest:
f.handleSetxattr(r)
case *fuse.RemovexattrRequest:
f.handleRemovexattr(r)
case *fuse.RenameRequest:
f.handleRename(r)
case *fuse.StatfsRequest:
f.handleStatfs(r)
/*
case *fuse.InitRequest:
f.handleInit(r)
case *fuse.MknodRequest:
f.handleMknod(r)
case *fuse.LinkRequest:
f.handleLink(r)
case *fuse.DestroyRequest:
f.handleDestroy(r)
case *fuse.FsyncRequest:
f.handleFsync(r)
*/
}
}