From dfadf1e8df7ec85167c21353b8bc670f612310e5 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 27 Jul 2015 15:40:36 +1000 Subject: [PATCH 1/7] Deleted Op. --- fuseops/ops.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/fuseops/ops.go b/fuseops/ops.go index 11d9271..b487ac8 100644 --- a/fuseops/ops.go +++ b/fuseops/ops.go @@ -22,17 +22,6 @@ import ( "github.com/jacobsa/fuse/internal/fusekernel" ) -// A common interface implemented by all ops in this package. Use a type switch -// to find particular concrete types, responding with fuse.ENOSYS if a type is -// not supported. -type Op interface { - // A short description of the op, to be used in logging. - ShortDesc() string - - // A long description of the op, to be used in debug logging. - DebugString() string -} - //////////////////////////////////////////////////////////////////////// // Inodes //////////////////////////////////////////////////////////////////////// From b1b941d4506b63c5abdd728158491a953ba845a4 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 27 Jul 2015 15:40:46 +1000 Subject: [PATCH 2/7] Deleted commonOp. --- fuseops/common_op.go | 174 ------------------------------------------- 1 file changed, 174 deletions(-) delete mode 100644 fuseops/common_op.go diff --git a/fuseops/common_op.go b/fuseops/common_op.go deleted file mode 100644 index fb3a224..0000000 --- a/fuseops/common_op.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package fuseops - -import ( - "fmt" - "log" - "reflect" - "strings" - "syscall" - - "github.com/jacobsa/fuse/internal/buffer" - "github.com/jacobsa/reqtrace" - "golang.org/x/net/context" -) - -// An interface that all ops inside which commonOp is embedded must -// implement. -type internalOp interface { - Op - - // Create a response message for the kernel, leaving the leading - // fusekernel.OutHeader untouched. - // - // Special case: a zero return value means that the kernel is not expecting a - // response. - kernelResponse() (b buffer.OutMessage) -} - -// A function that sends a reply message back to the kernel for the request -// with the given fuse unique ID. The error argument is for informational -// purposes only; the error to hand to the kernel is encoded in the message. -type replyFunc func(Op, uint64, []byte, error) error - -// A helper for embedding common behavior. -type commonOp struct { - // The context exposed to the user. - ctx context.Context - - // The op in which this struct is embedded. - op internalOp - - // The fuse unique ID of this request, as assigned by the kernel. - fuseID uint64 - - // A function that can be used to send a reply to the kernel. - sendReply replyFunc - - // A function that can be used to log debug information about the op. The - // first argument is a call depth. - // - // May be nil. - debugLog func(int, string, ...interface{}) - - // A logger to be used for logging exceptional errors. - // - // May be nil. - errorLogger *log.Logger -} - -func (o *commonOp) ShortDesc() (desc string) { - v := reflect.ValueOf(o.op) - opName := v.Type().String() - - // Attempt to better handle the usual case: a string that looks like - // "*fuseops.GetInodeAttributesOp". - const prefix = "*fuseops." - const suffix = "Op" - if strings.HasPrefix(opName, prefix) && strings.HasSuffix(opName, suffix) { - opName = opName[len(prefix) : len(opName)-len(suffix)] - } - - desc = opName - - // Include the inode number to which the op applies, if possible. - if f := v.Elem().FieldByName("Inode"); f.IsValid() { - desc = fmt.Sprintf("%s(inode=%v)", desc, f.Interface()) - } - - return -} - -func (o *commonOp) DebugString() string { - // By default, defer to ShortDesc. - return o.op.ShortDesc() -} - -func (o *commonOp) init( - ctx context.Context, - op internalOp, - fuseID uint64, - sendReply replyFunc, - debugLog func(int, string, ...interface{}), - errorLogger *log.Logger) { - // Initialize basic fields. - o.ctx = ctx - o.op = op - o.fuseID = fuseID - o.sendReply = sendReply - o.debugLog = debugLog - o.errorLogger = errorLogger - - // Set up a trace span for this op. - var reportForTrace reqtrace.ReportFunc - o.ctx, reportForTrace = reqtrace.StartSpan(o.ctx, o.op.ShortDesc()) - - // When the op is finished, report to both reqtrace and the connection. - prevSendReply := o.sendReply - o.sendReply = func(op Op, fuseID uint64, msg []byte, opErr error) (err error) { - reportForTrace(opErr) - err = prevSendReply(op, fuseID, msg, opErr) - return - } -} - -func (o *commonOp) Context() context.Context { - return o.ctx -} - -func (o *commonOp) Logf(format string, v ...interface{}) { - if o.debugLog == nil { - return - } - - const calldepth = 2 - o.debugLog(calldepth, format, v...) -} - -func (o *commonOp) Respond(err error) { - // If successful, we ask the op for an appopriate response to the kernel, and - // it is responsible for leaving room for the fusekernel.OutHeader struct. - // Otherwise, create our own. - var b buffer.OutMessage - if err == nil { - b = o.op.kernelResponse() - } else { - b = buffer.NewOutMessage(0) - } - - // Fill in the header if a reply is needed. - msg := b.Bytes() - if msg != nil { - h := b.OutHeader() - h.Unique = o.fuseID - h.Len = uint32(len(msg)) - if err != nil { - // If the user gave us a syscall.Errno, use that value in the reply. - // Otherwise use the generic EIO. - if errno, ok := err.(syscall.Errno); ok { - h.Error = -int32(errno) - } else { - h.Error = -int32(syscall.EIO) - } - } - } - - // Reply. - replyErr := o.sendReply(o.op, o.fuseID, msg, err) - if replyErr != nil && o.errorLogger != nil { - o.errorLogger.Printf("Error from sendReply: %v", replyErr) - } -} From 56b1f10c47ed9d1f1342b9f5d7536dad47d7c052 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 27 Jul 2015 15:41:46 +1000 Subject: [PATCH 3/7] Killed unexported fields. --- fuseops/ops.go | 61 -------------------------------------------------- 1 file changed, 61 deletions(-) diff --git a/fuseops/ops.go b/fuseops/ops.go index b487ac8..5115a34 100644 --- a/fuseops/ops.go +++ b/fuseops/ops.go @@ -18,8 +18,6 @@ import ( "fmt" "os" "time" - - "github.com/jacobsa/fuse/internal/fusekernel" ) //////////////////////////////////////////////////////////////////////// @@ -29,9 +27,6 @@ import ( // Look up a child by name within a parent directory. The kernel sends this // when resolving user paths to dentry structs, which are then cached. type LookUpInodeOp struct { - commonOp - protocol fusekernel.Protocol - // The ID of the directory inode to which the child belongs. Parent InodeID @@ -63,9 +58,6 @@ func (o *LookUpInodeOp) ShortDesc() (desc string) { // inode attributes is stale. This is controlled by the AttributesExpiration // field of ChildInodeEntry, etc. type GetInodeAttributesOp struct { - commonOp - protocol fusekernel.Protocol - // The inode of interest. Inode InodeID @@ -89,9 +81,6 @@ func (o *GetInodeAttributesOp) DebugString() string { // The kernel sends this for obvious cases like chmod(2), and for less obvious // cases like ftrunctate(2). type SetInodeAttributesOp struct { - commonOp - protocol fusekernel.Protocol - // The inode of interest. Inode InodeID @@ -148,8 +137,6 @@ type SetInodeAttributesOp struct { // Rather they should take fuse.Connection.ReadOp returning io.EOF as // implicitly decrementing all lookup counts to zero. type ForgetInodeOp struct { - commonOp - // The inode whose reference count should be decremented. Inode InodeID @@ -173,9 +160,6 @@ type ForgetInodeOp struct { // // Therefore the file system should return EEXIST if the name already exists. type MkDirOp struct { - commonOp - protocol fusekernel.Protocol - // The ID of parent directory inode within which to create the child. Parent InodeID @@ -206,9 +190,6 @@ func (o *MkDirOp) ShortDesc() (desc string) { // // Therefore the file system should return EEXIST if the name already exists. type CreateFileOp struct { - commonOp - protocol fusekernel.Protocol - // The ID of parent directory inode within which to create the child file. Parent InodeID @@ -241,9 +222,6 @@ func (o *CreateFileOp) ShortDesc() (desc string) { // Create a symlink inode. If the name already exists, the file system should // return EEXIST (cf. the notes on CreateFileOp and MkDirOp). type CreateSymlinkOp struct { - commonOp - protocol fusekernel.Protocol - // The ID of parent directory inode within which to create the child symlink. Parent InodeID @@ -310,8 +288,6 @@ func (o *CreateSymlinkOp) ShortDesc() (desc string) { // about this. // type RenameOp struct { - commonOp - // The old parent directory, and the name of the entry within it to be // relocated. OldParent InodeID @@ -331,8 +307,6 @@ type RenameOp struct { // // Sample implementation in ext2: ext2_rmdir (http://goo.gl/B9QmFf) type RmDirOp struct { - commonOp - // The ID of parent directory inode, and the name of the directory being // removed within it. Parent InodeID @@ -346,8 +320,6 @@ type RmDirOp struct { // // Sample implementation in ext2: ext2_unlink (http://goo.gl/hY6r6C) type UnlinkOp struct { - commonOp - // The ID of parent directory inode, and the name of the entry being removed // within it. Parent InodeID @@ -365,8 +337,6 @@ type UnlinkOp struct { // user-space process. On OS X it may not be sent for every open(2) (cf. // https://github.com/osxfuse/osxfuse/issues/199). type OpenDirOp struct { - commonOp - // The ID of the inode to be opened. Inode InodeID @@ -383,8 +353,6 @@ type OpenDirOp struct { // Read entries from a directory previously opened with OpenDir. type ReadDirOp struct { - commonOp - // The directory inode that we are reading, and the handle previously // returned by OpenDir when opening that inode. Inode InodeID @@ -480,8 +448,6 @@ type ReadDirOp struct { // // Errors from this op are ignored by the kernel (cf. http://goo.gl/RL38Do). type ReleaseDirHandleOp struct { - commonOp - // The handle ID to be released. The kernel guarantees that this ID will not // be used in further calls to the file system (unless it is reissued by the // file system). @@ -499,8 +465,6 @@ type ReleaseDirHandleOp struct { // process. On OS X it may not be sent for every open(2) // (cf.https://github.com/osxfuse/osxfuse/issues/199). type OpenFileOp struct { - commonOp - // The ID of the inode to be opened. Inode InodeID @@ -520,8 +484,6 @@ type OpenFileOp struct { // some reads may be served by the page cache. See notes on WriteFileOp for // more. type ReadFileOp struct { - commonOp - // The file inode that we are reading, and the handle previously returned by // CreateFile or OpenFile when opening that inode. Inode InodeID @@ -575,8 +537,6 @@ type ReadFileOp struct { // (See also http://goo.gl/ocdTdM, fuse-devel thread "Fuse guarantees on // concurrent requests".) type WriteFileOp struct { - commonOp - // The file inode that we are modifying, and the handle previously returned // by CreateFile or OpenFile when opening that inode. Inode InodeID @@ -630,8 +590,6 @@ type WriteFileOp struct { // See also: FlushFileOp, which may perform a similar function when closing a // file (but which is not used in "real" file systems). type SyncFileOp struct { - commonOp - // The file and handle being sync'd. Inode InodeID Handle HandleID @@ -685,8 +643,6 @@ type SyncFileOp struct { // to at least schedule a real flush, and maybe do it immediately in order to // return any errors that occur. type FlushFileOp struct { - commonOp - // The file and handle being flushed. Inode InodeID Handle HandleID @@ -701,35 +657,18 @@ type FlushFileOp struct { // // Errors from this op are ignored by the kernel (cf. http://goo.gl/RL38Do). type ReleaseFileHandleOp struct { - commonOp - // The handle ID to be released. The kernel guarantees that this ID will not // be used in further calls to the file system (unless it is reissued by the // file system). Handle HandleID } -// A sentinel used for unknown ops. The user is expected to respond with a -// non-nil error. -type unknownOp struct { - commonOp - opCode uint32 - inode InodeID -} - -func (o *unknownOp) ShortDesc() (desc string) { - desc = fmt.Sprintf("(inode=%v)", o.opCode, o.inode) - return -} - //////////////////////////////////////////////////////////////////////// // Reading symlinks //////////////////////////////////////////////////////////////////////// // Read the target of a symlink inode. type ReadSymlinkOp struct { - commonOp - // The symlink inode that we are reading. Inode InodeID From e59dbd14f4a8b2edcbaf43d04dd9d69f908bbcc5 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 27 Jul 2015 15:42:02 +1000 Subject: [PATCH 4/7] Killed methods. --- fuseops/ops.go | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/fuseops/ops.go b/fuseops/ops.go index 5115a34..d73c42c 100644 --- a/fuseops/ops.go +++ b/fuseops/ops.go @@ -15,7 +15,6 @@ package fuseops import ( - "fmt" "os" "time" ) @@ -48,11 +47,6 @@ type LookUpInodeOp struct { Entry ChildInodeEntry } -func (o *LookUpInodeOp) ShortDesc() (desc string) { - desc = fmt.Sprintf("LookUpInode(parent=%v, name=%q)", o.Parent, o.Name) - return -} - // Refresh the attributes for an inode whose ID was previously returned in a // LookUpInodeOp. The kernel sends this when the FUSE VFS layer's cache of // inode attributes is stale. This is controlled by the AttributesExpiration @@ -68,14 +62,6 @@ type GetInodeAttributesOp struct { AttributesExpiration time.Time } -func (o *GetInodeAttributesOp) DebugString() string { - return fmt.Sprintf( - "Inode: %d, Exp: %v, Attr: %s", - o.Inode, - o.AttributesExpiration, - o.Attributes.DebugString()) -} - // Change attributes for an inode. // // The kernel sends this for obvious cases like chmod(2), and for less obvious @@ -174,11 +160,6 @@ type MkDirOp struct { Entry ChildInodeEntry } -func (o *MkDirOp) ShortDesc() (desc string) { - desc = fmt.Sprintf("MkDir(parent=%v, name=%q)", o.Parent, o.Name) - return -} - // Create a file inode and open it. // // The kernel sends this when the user asks to open a file with the O_CREAT @@ -214,11 +195,6 @@ type CreateFileOp struct { Handle HandleID } -func (o *CreateFileOp) ShortDesc() (desc string) { - desc = fmt.Sprintf("CreateFile(parent=%v, name=%q)", o.Parent, o.Name) - return -} - // Create a symlink inode. If the name already exists, the file system should // return EEXIST (cf. the notes on CreateFileOp and MkDirOp). type CreateSymlinkOp struct { @@ -239,16 +215,6 @@ type CreateSymlinkOp struct { Entry ChildInodeEntry } -func (o *CreateSymlinkOp) ShortDesc() (desc string) { - desc = fmt.Sprintf( - "CreateSymlink(parent=%v, name=%q, target=%q)", - o.Parent, - o.Name, - o.Target) - - return -} - //////////////////////////////////////////////////////////////////////// // Unlinking //////////////////////////////////////////////////////////////////////// From 3755e3c1a1f54589f88f093c66a2b452244c1801 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 27 Jul 2015 15:43:41 +1000 Subject: [PATCH 5/7] Fixed package fuse. --- connection.go | 5 ++--- conversions.go | 6 +++--- ops.go | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/connection.go b/connection.go index 24647f0..2fe72ed 100644 --- a/connection.go +++ b/connection.go @@ -26,7 +26,6 @@ import ( "golang.org/x/net/context" - "github.com/jacobsa/fuse/fuseops" "github.com/jacobsa/fuse/internal/buffer" "github.com/jacobsa/fuse/internal/fusekernel" ) @@ -90,7 +89,7 @@ type Connection struct { // context that the user uses to reply to the op. type opState struct { inMsg *buffer.InMessage - op fuseops.Op + op interface{} opID uint32 // For logging } @@ -396,7 +395,7 @@ func (c *Connection) writeMessage(msg []byte) (err error) { // /dev/fuse. It must not be called multiple times concurrently. // // LOCKS_EXCLUDED(c.mu) -func (c *Connection) ReadOp() (ctx context.Context, op fuseops.Op, err error) { +func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) { // Keep going until we find a request we know how to convert. for { // Read the next message from the kernel. diff --git a/conversions.go b/conversions.go index a011c91..e454466 100644 --- a/conversions.go +++ b/conversions.go @@ -27,13 +27,13 @@ import ( "github.com/jacobsa/fuse/internal/fusekernel" ) -// Convert a kernel message to an appropriate implementation of fuseops.Op. If -// the op is unknown, a special unexported type will be used. +// Convert a kernel message to an appropriate op. If the op is unknown, a +// special unexported type will be used. // // The caller is responsible for arranging for the message to be destroyed. func convertInMessage( m *buffer.InMessage, - protocol fusekernel.Protocol) (o fuseops.Op, err error) { + protocol fusekernel.Protocol) (o interface{}, err error) { switch m.Header().Opcode { case fusekernel.OpLookup: buf := m.ConsumeBytes(m.Len()) diff --git a/ops.go b/ops.go index 9bf884a..158337b 100644 --- a/ops.go +++ b/ops.go @@ -28,7 +28,7 @@ import ( // response, return a nil response. func kernelResponse( fuseID uint64, - op fuseops.Op, + op interface{}, opErr error, protocol fusekernel.Protocol) (msg []byte) { // If the user replied with an error, create room enough just for the result @@ -59,7 +59,7 @@ func kernelResponse( // Like kernelResponse, but assumes the user replied with a nil error to the // op. func kernelResponseForOp( - op fuseops.Op, + op interface{}, protocol fusekernel.Protocol) (b buffer.OutMessage) { // Create the appropriate output message switch o := op.(type) { From 522995296e7a9397065562b8231574ba6c4f3eed Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 27 Jul 2015 15:44:17 +1000 Subject: [PATCH 6/7] Fixed package fuse. --- fuseutil/file_system.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fuseutil/file_system.go b/fuseutil/file_system.go index f02ac31..3ebcdf8 100644 --- a/fuseutil/file_system.go +++ b/fuseutil/file_system.go @@ -29,8 +29,8 @@ import ( // loop" that switches on op types, instead receiving typed method calls // directly. // -// The FileSystem implementation should not call Op.Respond, instead returning -// the error with which the caller should respond. +// The FileSystem implementation should not call Connection.Reply, instead +// returning the error with which the caller should respond. // // See NotImplementedFileSystem for a convenient way to embed default // implementations for methods you don't care about. @@ -110,7 +110,7 @@ func (s *fileSystemServer) ServeOps(c *fuse.Connection) { func (s *fileSystemServer) handleOp( c *fuse.Connection, ctx context.Context, - op fuseops.Op) { + op interface{}) { defer s.opsInFlight.Done() // Dispatch to the appropriate method. From a99d69abcecd356d2903066ea65246f835adcfd9 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 27 Jul 2015 15:44:54 +1000 Subject: [PATCH 7/7] Fixed a couple of out of date references. --- errors.go | 2 +- fuseops/doc.go | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/errors.go b/errors.go index bc9f902..455c79b 100644 --- a/errors.go +++ b/errors.go @@ -18,7 +18,7 @@ import "syscall" const ( // Errors corresponding to kernel error numbers. These may be treated - // specially by fuseops.Op.Respond methods. + // specially by Connection.Reply. EEXIST = syscall.EEXIST EINVAL = syscall.EINVAL EIO = syscall.EIO diff --git a/fuseops/doc.go b/fuseops/doc.go index 5e4a880..8eccde0 100644 --- a/fuseops/doc.go +++ b/fuseops/doc.go @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package fuseops contains implementations of the fuse.Op interface that may -// be returned by fuse.Connection.ReadOp. See documentation in that package for -// more. +// Package fuseops contains ops that may be returned by fuse.Connection.ReadOp. +// See documentation in that package for more. package fuseops