Refactored allocation out OutMessage structs.

In preparation for allocating them up-front for ReadFile and ReadDir.
geesefs-0-30-9
Aaron Jacobs 2015-07-29 10:39:37 +10:00
parent 4fd46371a2
commit d903c709d3
2 changed files with 28 additions and 44 deletions

View File

@ -450,15 +450,17 @@ func (c *Connection) Reply(ctx context.Context, opErr error) {
} }
// Send the reply to the kernel, if one is required. // Send the reply to the kernel, if one is required.
outMsg := c.kernelResponse(m.Header().Unique, op, opErr) outMsg := c.getOutMessage()
if outMsg != nil { noResponse := c.kernelResponse(outMsg, m.Header().Unique, op, opErr)
err := c.writeMessage(outMsg.Bytes())
c.putOutMessage(outMsg)
if !noResponse {
err := c.writeMessage(outMsg.Bytes())
if err != nil && c.errorLogger != nil { if err != nil && c.errorLogger != nil {
c.errorLogger.Printf("writeMessage: %v", err) c.errorLogger.Printf("writeMessage: %v", err)
} }
} }
c.putOutMessage(outMsg)
} }
// Close the connection. Must not be called until operations that were read // Close the connection. Must not be called until operations that were read

View File

@ -387,51 +387,45 @@ func convertInMessage(
// Outgoing messages // Outgoing messages
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Return the response that should be sent to the kernel, or nil if the op // Fill in the response that should be sent to the kernel, or set noResponse if
// requires no response. // the op requires no response.
func (c *Connection) kernelResponse( func (c *Connection) kernelResponse(
m *buffer.OutMessage,
fuseID uint64, fuseID uint64,
op interface{}, op interface{},
opErr error) (m *buffer.OutMessage) { opErr error) (noResponse bool) {
// If the user replied with an error, create a response containing just the h := m.OutHeader()
// result header with the error filled in. Otherwise create an appropriate h.Unique = fuseID
// response.
// Did the user return an error? Otherwise, fill in the rest of the response.
if opErr != nil { if opErr != nil {
m = c.getOutMessage()
if errno, ok := opErr.(syscall.Errno); ok { if errno, ok := opErr.(syscall.Errno); ok {
m.OutHeader().Error = -int32(errno) m.OutHeader().Error = -int32(errno)
} else { } else {
m.OutHeader().Error = -int32(syscall.EIO) m.OutHeader().Error = -int32(syscall.EIO)
} }
} else { } else {
m = c.kernelResponseForOp(op) noResponse = c.kernelResponseForOp(m, op)
}
// Fill in the rest of the header, if a response is required.
if m != nil {
h := m.OutHeader()
h.Unique = fuseID
h.Len = uint32(m.Len())
} }
h.Len = uint32(m.Len())
return return
} }
// Like kernelResponse, but assumes the user replied with a nil error to the // Like kernelResponse, but assumes the user replied with a nil error to the
// op. Returns a nil response if no response is required. // op.
func (c *Connection) kernelResponseForOp( func (c *Connection) kernelResponseForOp(
op interface{}) (m *buffer.OutMessage) { m *buffer.OutMessage,
op interface{}) (noResponse bool) {
// Create the appropriate output message // Create the appropriate output message
switch o := op.(type) { switch o := op.(type) {
case *fuseops.LookUpInodeOp: case *fuseops.LookUpInodeOp:
size := fusekernel.EntryOutSize(c.protocol) size := fusekernel.EntryOutSize(c.protocol)
m = c.getOutMessage()
out := (*fusekernel.EntryOut)(m.Grow(size)) out := (*fusekernel.EntryOut)(m.Grow(size))
convertChildInodeEntry(&o.Entry, out) convertChildInodeEntry(&o.Entry, out)
case *fuseops.GetInodeAttributesOp: case *fuseops.GetInodeAttributesOp:
size := fusekernel.AttrOutSize(c.protocol) size := fusekernel.AttrOutSize(c.protocol)
m = c.getOutMessage()
out := (*fusekernel.AttrOut)(m.Grow(size)) out := (*fusekernel.AttrOut)(m.Grow(size))
out.AttrValid, out.AttrValidNsec = convertExpirationTime( out.AttrValid, out.AttrValidNsec = convertExpirationTime(
o.AttributesExpiration) o.AttributesExpiration)
@ -439,24 +433,21 @@ func (c *Connection) kernelResponseForOp(
case *fuseops.SetInodeAttributesOp: case *fuseops.SetInodeAttributesOp:
size := fusekernel.AttrOutSize(c.protocol) size := fusekernel.AttrOutSize(c.protocol)
m = c.getOutMessage()
out := (*fusekernel.AttrOut)(m.Grow(size)) out := (*fusekernel.AttrOut)(m.Grow(size))
out.AttrValid, out.AttrValidNsec = convertExpirationTime( out.AttrValid, out.AttrValidNsec = convertExpirationTime(
o.AttributesExpiration) o.AttributesExpiration)
convertAttributes(o.Inode, &o.Attributes, &out.Attr) convertAttributes(o.Inode, &o.Attributes, &out.Attr)
case *fuseops.ForgetInodeOp: case *fuseops.ForgetInodeOp:
// No response. noResponse = true
case *fuseops.MkDirOp: case *fuseops.MkDirOp:
size := fusekernel.EntryOutSize(c.protocol) size := fusekernel.EntryOutSize(c.protocol)
m = c.getOutMessage()
out := (*fusekernel.EntryOut)(m.Grow(size)) out := (*fusekernel.EntryOut)(m.Grow(size))
convertChildInodeEntry(&o.Entry, out) convertChildInodeEntry(&o.Entry, out)
case *fuseops.CreateFileOp: case *fuseops.CreateFileOp:
eSize := fusekernel.EntryOutSize(c.protocol) eSize := fusekernel.EntryOutSize(c.protocol)
m = c.getOutMessage()
e := (*fusekernel.EntryOut)(m.Grow(eSize)) e := (*fusekernel.EntryOut)(m.Grow(eSize))
convertChildInodeEntry(&o.Entry, e) convertChildInodeEntry(&o.Entry, e)
@ -466,67 +457,58 @@ func (c *Connection) kernelResponseForOp(
case *fuseops.CreateSymlinkOp: case *fuseops.CreateSymlinkOp:
size := fusekernel.EntryOutSize(c.protocol) size := fusekernel.EntryOutSize(c.protocol)
m = c.getOutMessage()
out := (*fusekernel.EntryOut)(m.Grow(size)) out := (*fusekernel.EntryOut)(m.Grow(size))
convertChildInodeEntry(&o.Entry, out) convertChildInodeEntry(&o.Entry, out)
case *fuseops.RenameOp: case *fuseops.RenameOp:
m = c.getOutMessage() // Empty response
case *fuseops.RmDirOp: case *fuseops.RmDirOp:
m = c.getOutMessage() // Empty response
case *fuseops.UnlinkOp: case *fuseops.UnlinkOp:
m = c.getOutMessage() // Empty response
case *fuseops.OpenDirOp: case *fuseops.OpenDirOp:
m = c.getOutMessage()
out := (*fusekernel.OpenOut)(m.Grow(unsafe.Sizeof(fusekernel.OpenOut{}))) out := (*fusekernel.OpenOut)(m.Grow(unsafe.Sizeof(fusekernel.OpenOut{})))
out.Fh = uint64(o.Handle) out.Fh = uint64(o.Handle)
case *fuseops.ReadDirOp: case *fuseops.ReadDirOp:
m = c.getOutMessage()
m.Append(o.Dst[:o.BytesRead]) m.Append(o.Dst[:o.BytesRead])
case *fuseops.ReleaseDirHandleOp: case *fuseops.ReleaseDirHandleOp:
m = c.getOutMessage() // Empty response
case *fuseops.OpenFileOp: case *fuseops.OpenFileOp:
m = c.getOutMessage()
out := (*fusekernel.OpenOut)(m.Grow(unsafe.Sizeof(fusekernel.OpenOut{}))) out := (*fusekernel.OpenOut)(m.Grow(unsafe.Sizeof(fusekernel.OpenOut{})))
out.Fh = uint64(o.Handle) out.Fh = uint64(o.Handle)
case *fuseops.ReadFileOp: case *fuseops.ReadFileOp:
m = c.getOutMessage()
m.Append(o.Dst[:o.BytesRead]) m.Append(o.Dst[:o.BytesRead])
case *fuseops.WriteFileOp: case *fuseops.WriteFileOp:
m = c.getOutMessage()
out := (*fusekernel.WriteOut)(m.Grow(unsafe.Sizeof(fusekernel.WriteOut{}))) out := (*fusekernel.WriteOut)(m.Grow(unsafe.Sizeof(fusekernel.WriteOut{})))
out.Size = uint32(len(o.Data)) out.Size = uint32(len(o.Data))
case *fuseops.SyncFileOp: case *fuseops.SyncFileOp:
m = c.getOutMessage() // Empty response
case *fuseops.FlushFileOp: case *fuseops.FlushFileOp:
m = c.getOutMessage() // Empty response
case *fuseops.ReleaseFileHandleOp: case *fuseops.ReleaseFileHandleOp:
m = c.getOutMessage() // Empty response
case *fuseops.ReadSymlinkOp: case *fuseops.ReadSymlinkOp:
m = c.getOutMessage()
m.AppendString(o.Target) m.AppendString(o.Target)
case *statFSOp: case *statFSOp:
m = c.getOutMessage()
m.Grow(unsafe.Sizeof(fusekernel.StatfsOut{})) m.Grow(unsafe.Sizeof(fusekernel.StatfsOut{}))
case *interruptOp: case *interruptOp:
// No response. noResponse = true
case *initOp: case *initOp:
m = c.getOutMessage()
out := (*fusekernel.InitOut)(m.Grow(unsafe.Sizeof(fusekernel.InitOut{}))) out := (*fusekernel.InitOut)(m.Grow(unsafe.Sizeof(fusekernel.InitOut{})))
out.Major = o.Library.Major out.Major = o.Library.Major