Commit 27311775 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Use raw pointer manipulations rather than encoding/binary for (de)serizalizing data.

parent 2c2cba15
...@@ -3,9 +3,9 @@ package fuse ...@@ -3,9 +3,9 @@ package fuse
// all of the code for DirEntryList. // all of the code for DirEntryList.
import ( import (
"encoding/binary"
"fmt"
"bytes" "bytes"
"fmt"
"unsafe"
) )
var _ = fmt.Print var _ = fmt.Print
...@@ -33,13 +33,14 @@ func (me *DirEntryList) Add(name []byte, inode uint64, mode uint32) bool { ...@@ -33,13 +33,14 @@ func (me *DirEntryList) Add(name []byte, inode uint64, mode uint32) bool {
lastLen := me.buf.Len() lastLen := me.buf.Len()
me.offset++ me.offset++
dirent := new(Dirent) dirent := Dirent{
dirent.Off = me.offset Off: me.offset,
dirent.Ino = inode Ino: inode,
dirent.NameLen = uint32(len(name)) NameLen: uint32(len(name)),
dirent.Typ = ModeToType(mode) Typ: ModeToType(mode),
}
err := binary.Write(&me.buf, binary.LittleEndian, dirent) _, err := me.buf.Write(asSlice(unsafe.Pointer(&dirent), unsafe.Sizeof(Dirent{})))
if err != nil { if err != nil {
panic("Serialization of Dirent failed") panic("Serialization of Dirent failed")
} }
......
package fuse package fuse
import ( import (
"bytes"
"encoding/binary"
"fmt" "fmt"
"log" "log"
"os" "os"
"reflect"
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
"time" "time"
"unsafe"
) )
// TODO make generic option setting. // TODO make generic option setting.
...@@ -29,17 +29,17 @@ type fuseRequest struct { ...@@ -29,17 +29,17 @@ type fuseRequest struct {
inputBuf []byte inputBuf []byte
// These split up inputBuf. // These split up inputBuf.
inHeader InHeader inHeader *InHeader
arg *bytes.Buffer arg []byte
// Data for the output. // Unstructured data, a pointer to the relevant XxxxOut struct.
data interface{}
status Status status Status
data unsafe.Pointer
flatData []byte flatData []byte
// Header+data for what we send back to the kernel. // Header + structured data for what we send back to the kernel.
// May be followed by flatData. // May be followed by flatData.
output []byte outHeaderBytes []byte
// Start timestamp for timing info. // Start timestamp for timing info.
startNs int64 startNs int64
...@@ -193,21 +193,21 @@ func (me *MountState) Error(err os.Error) { ...@@ -193,21 +193,21 @@ func (me *MountState) Error(err os.Error) {
} }
func (me *MountState) Write(req *fuseRequest) { func (me *MountState) Write(req *fuseRequest) {
if req.output == nil { if req.outHeaderBytes == nil {
return return
} }
var err os.Error var err os.Error
if req.flatData == nil { if req.flatData == nil {
_, err = me.mountFile.Write(req.output) _, err = me.mountFile.Write(req.outHeaderBytes)
} else { } else {
_, err = Writev(me.mountFile.Fd(), _, err = Writev(me.mountFile.Fd(),
[][]byte{req.output, req.flatData}) [][]byte{req.outHeaderBytes, req.flatData})
} }
if err != nil { if err != nil {
me.Error(os.NewError(fmt.Sprintf("writer: Writev %v failed, err: %v. Opcode: %v", me.Error(os.NewError(fmt.Sprintf("writer: Writev %v failed, err: %v. Opcode: %v",
req.output, err, operationName(req.inHeader.Opcode)))) req.outHeaderBytes, err, operationName(req.inHeader.Opcode))))
} }
} }
...@@ -334,35 +334,45 @@ func (me *MountState) loop() { ...@@ -334,35 +334,45 @@ func (me *MountState) loop() {
} }
func (me *MountState) handle(req *fuseRequest) { func (me *MountState) handle(req *fuseRequest) {
defer me.discardFuseRequest(req)
req.dispatchNs = time.Nanoseconds() req.dispatchNs = time.Nanoseconds()
req.arg = bytes.NewBuffer(req.inputBuf)
err := binary.Read(req.arg, binary.LittleEndian, &req.inHeader) inHSize := unsafe.Sizeof(InHeader{})
if err == os.EOF { if len(req.inputBuf) < inHSize {
err = os.NewError(fmt.Sprintf("MountPoint, handle: can't read a header, in_data: %v", req.inputBuf)) me.Error(os.NewError(fmt.Sprintf("Short read for input header: %v", req.inputBuf)))
}
if err != nil {
me.Error(err)
return return
} }
req.inHeader = (*InHeader)(unsafe.Pointer(&req.inputBuf[0]))
req.arg = req.inputBuf[inHSize:]
me.dispatch(req) me.dispatch(req)
if req.inHeader.Opcode != FUSE_FORGET { if req.inHeader.Opcode != FUSE_FORGET {
serialize(req, me.Debug) serialize(req, me.Debug)
req.preWriteNs = time.Nanoseconds() req.preWriteNs = time.Nanoseconds()
me.Write(req) me.Write(req)
} }
me.discardFuseRequest(req)
} }
func (me *MountState) dispatch(req *fuseRequest) { func (me *MountState) dispatch(req *fuseRequest) {
h := &req.inHeader h := req.inHeader
argumentSize, ok := inputSizeMap[int(h.Opcode)]
input := newInput(h.Opcode) if !ok {
if input != nil && !parseLittleEndian(req.arg, input) { log.Println("Unknown opcode %d (input)", h.Opcode)
req.status = ENOSYS
return
}
if len(req.arg) < argumentSize {
log.Println("Short read for %v: %v", h.Opcode, req.arg)
req.status = EIO req.status = EIO
return return
} }
var out Empty var inData unsafe.Pointer
if argumentSize > 0 {
inData = unsafe.Pointer(&req.arg[0])
}
data := req.arg[argumentSize:]
var status Status = OK var status Status = OK
fs := me.fileSystem fs := me.fileSystem
...@@ -372,7 +382,7 @@ func (me *MountState) dispatch(req *fuseRequest) { ...@@ -372,7 +382,7 @@ func (me *MountState) dispatch(req *fuseRequest) {
h.Opcode == FUSE_LOOKUP || h.Opcode == FUSE_MKDIR || h.Opcode == FUSE_LOOKUP || h.Opcode == FUSE_MKDIR ||
h.Opcode == FUSE_MKNOD || h.Opcode == FUSE_CREATE || h.Opcode == FUSE_MKNOD || h.Opcode == FUSE_CREATE ||
h.Opcode == FUSE_LINK || h.Opcode == FUSE_GETXATTR { h.Opcode == FUSE_LINK || h.Opcode == FUSE_GETXATTR {
filename = strings.TrimRight(string(req.arg.Bytes()), "\x00") filename = strings.TrimRight(string(data), "\x00")
} }
if me.Debug { if me.Debug {
nm := "" nm := ""
...@@ -385,93 +395,112 @@ func (me *MountState) dispatch(req *fuseRequest) { ...@@ -385,93 +395,112 @@ func (me *MountState) dispatch(req *fuseRequest) {
// Follow ordering of fuse_lowlevel.h. // Follow ordering of fuse_lowlevel.h.
switch h.Opcode { switch h.Opcode {
case FUSE_INIT: case FUSE_INIT:
out, status = initFuse(me, h, input.(*InitIn)) req.data, status = initFuse(me, h, (*InitIn)(inData))
case FUSE_DESTROY: case FUSE_DESTROY:
fs.Destroy(h, input.(*InitIn)) fs.Destroy(h, (*InitIn)(inData))
case FUSE_LOOKUP: case FUSE_LOOKUP:
out, status = fs.Lookup(h, filename) lookupOut, s := fs.Lookup(h, filename)
status = s
req.data = unsafe.Pointer(lookupOut)
case FUSE_FORGET: case FUSE_FORGET:
fs.Forget(h, input.(*ForgetIn)) fs.Forget(h, (*ForgetIn)(inData))
// If we try to write OK, nil, we will get // If we try to write OK, nil, we will get
// error: writer: Writev [[16 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0]] // error: writer: Writev [[16 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0]]
// failed, err: writev: no such file or directory // failed, err: writev: no such file or directory
return return
case FUSE_GETATTR: case FUSE_GETATTR:
// TODO - if input.Fh is set, do file.GetAttr // TODO - if inData.Fh is set, do file.GetAttr
out, status = fs.GetAttr(h, input.(*GetAttrIn)) attrOut, s := fs.GetAttr(h, (*GetAttrIn)(inData))
status = s
req.data = unsafe.Pointer(attrOut)
case FUSE_SETATTR: case FUSE_SETATTR:
out, status = doSetattr(me, h, input.(*SetAttrIn)) req.data, status = doSetattr(me, h, (*SetAttrIn)(inData))
case FUSE_READLINK: case FUSE_READLINK:
out, status = fs.Readlink(h) req.flatData, status = fs.Readlink(h)
case FUSE_MKNOD: case FUSE_MKNOD:
out, status = fs.Mknod(h, input.(*MknodIn), filename) entryOut, s := fs.Mknod(h, (*MknodIn)(inData), filename)
status = s
req.data = unsafe.Pointer(entryOut)
case FUSE_MKDIR: case FUSE_MKDIR:
out, status = fs.Mkdir(h, input.(*MkdirIn), filename) entryOut, s := fs.Mkdir(h, (*MkdirIn)(inData), filename)
status = s
req.data = unsafe.Pointer(entryOut)
case FUSE_UNLINK: case FUSE_UNLINK:
status = fs.Unlink(h, filename) status = fs.Unlink(h, filename)
case FUSE_RMDIR: case FUSE_RMDIR:
status = fs.Rmdir(h, filename) status = fs.Rmdir(h, filename)
case FUSE_SYMLINK: case FUSE_SYMLINK:
filenames := strings.Split(string(req.arg.Bytes()), "\x00", 3) filenames := strings.Split(string(data), "\x00", 3)
if len(filenames) >= 2 { if len(filenames) >= 2 {
out, status = fs.Symlink(h, filenames[1], filenames[0]) entryOut, s := fs.Symlink(h, filenames[1], filenames[0])
status = s
req.data = unsafe.Pointer(entryOut)
} else { } else {
status = EIO status = EIO
} }
case FUSE_RENAME: case FUSE_RENAME:
filenames := strings.Split(string(req.arg.Bytes()), "\x00", 3) filenames := strings.Split(string(data), "\x00", 3)
if len(filenames) >= 2 { if len(filenames) >= 2 {
status = fs.Rename(h, input.(*RenameIn), filenames[0], filenames[1]) status = fs.Rename(h, (*RenameIn)(inData), filenames[0], filenames[1])
} else { } else {
status = EIO status = EIO
} }
case FUSE_LINK: case FUSE_LINK:
out, status = fs.Link(h, input.(*LinkIn), filename) entryOut, s := fs.Link(h, (*LinkIn)(inData), filename)
status = s
req.data = unsafe.Pointer(entryOut)
case FUSE_OPEN: case FUSE_OPEN:
out, status = doOpen(me, h, input.(*OpenIn)) req.data, status = doOpen(me, h, (*OpenIn)(inData))
case FUSE_READ: case FUSE_READ:
req.flatData, status = doRead(me, h, input.(*ReadIn), me.buffers) req.flatData, status = doRead(me, h, (*ReadIn)(inData), me.buffers)
case FUSE_WRITE: case FUSE_WRITE:
out, status = doWrite(me, h, input.(*WriteIn), req.arg.Bytes()) req.data, status = doWrite(me, h, (*WriteIn)(inData), data)
case FUSE_FLUSH: case FUSE_FLUSH:
out, status = doFlush(me, h, input.(*FlushIn)) status = doFlush(me, h, (*FlushIn)(inData))
case FUSE_RELEASE: case FUSE_RELEASE:
out, status = doRelease(me, h, input.(*ReleaseIn)) status = doRelease(me, h, (*ReleaseIn)(inData))
case FUSE_FSYNC: case FUSE_FSYNC:
status = doFsync(me, h, input.(*FsyncIn)) status = doFsync(me, h, (*FsyncIn)(inData))
case FUSE_OPENDIR: case FUSE_OPENDIR:
out, status = doOpenDir(me, h, input.(*OpenIn)) req.data, status = doOpenDir(me, h, (*OpenIn)(inData))
case FUSE_READDIR: case FUSE_READDIR:
out, status = doReadDir(me, h, input.(*ReadIn)) req.flatData, status = doReadDir(me, h, (*ReadIn)(inData))
case FUSE_RELEASEDIR: case FUSE_RELEASEDIR:
out, status = doReleaseDir(me, h, input.(*ReleaseIn)) status = doReleaseDir(me, h, (*ReleaseIn)(inData))
case FUSE_FSYNCDIR: case FUSE_FSYNCDIR:
// todo- check input type. // todo- check inData type.
status = doFsyncDir(me, h, input.(*FsyncIn)) status = doFsyncDir(me, h, (*FsyncIn)(inData))
// TODO - implement XAttr routines. // TODO - implement XAttr routines.
// case FUSE_SETXATTR: // case FUSE_SETXATTR:
// status = fs.SetXAttr(h, input.(*SetXAttrIn)) // status = fs.SetXAttr(h, (*SetXAttrIn)(inData))
case FUSE_GETXATTR: case FUSE_GETXATTR:
out, req.flatData, status = doGetXAttr(me, h, input.(*GetXAttrIn), filename) req.data, req.flatData, status = doGetXAttr(me, h, (*GetXAttrIn)(inData), filename)
// case FUSE_LISTXATTR: // case FUSE_LISTXATTR:
// case FUSE_REMOVEXATTR // case FUSE_REMOVEXATTR
case FUSE_ACCESS: case FUSE_ACCESS:
status = fs.Access(h, input.(*AccessIn)) status = fs.Access(h, (*AccessIn)(inData))
case FUSE_CREATE: case FUSE_CREATE:
out, status = doCreate(me, h, input.(*CreateIn), filename) req.data, status = doCreate(me, h, (*CreateIn)(inData), filename)
// TODO - implement file locking. // TODO - implement file locking.
// case FUSE_SETLK // case FUSE_SETLK
// case FUSE_SETLKW // case FUSE_SETLKW
case FUSE_BMAP: case FUSE_BMAP:
out, status = fs.Bmap(h, input.(*BmapIn)) bmapOut, s := fs.Bmap(h, (*BmapIn)(inData))
status = s
req.data = unsafe.Pointer(bmapOut)
case FUSE_IOCTL: case FUSE_IOCTL:
out, status = fs.Ioctl(h, input.(*IoctlIn)) ioctlOut, s := fs.Ioctl(h, (*IoctlIn)(inData))
status = s
req.data = unsafe.Pointer(ioctlOut)
case FUSE_POLL: case FUSE_POLL:
out, status = fs.Poll(h, input.(*PollIn)) pollOut, s := fs.Poll(h, (*PollIn)(inData))
status = s
req.data = unsafe.Pointer(pollOut)
// TODO - figure out how to support this // TODO - figure out how to support this
// case FUSE_INTERRUPT // case FUSE_INTERRUPT
default: default:
...@@ -481,38 +510,39 @@ func (me *MountState) dispatch(req *fuseRequest) { ...@@ -481,38 +510,39 @@ func (me *MountState) dispatch(req *fuseRequest) {
} }
req.status = status req.status = status
req.data = out }
// Thanks to Andrew Gerrand for this hack.
func asSlice(ptr unsafe.Pointer, byteCount int) []byte {
h := &reflect.SliceHeader{uintptr(ptr), byteCount, byteCount}
return *(*[]byte)(unsafe.Pointer(h))
} }
func serialize(req *fuseRequest, debug bool) { func serialize(req *fuseRequest, debug bool) {
headerBytes := make([]byte, SizeOfOutHeader) dataLength, ok := outputSizeMap[int(req.inHeader.Opcode)]
buf := bytes.NewBuffer(headerBytes) if !ok {
if req.data != nil && req.status == OK { log.Println("Unknown opcode %d (output)", req.inHeader.Opcode)
err := binary.Write(buf, binary.LittleEndian, req.data) req.status = ENOSYS
if err != nil { return
panic(fmt.Sprintf("Can't serialize out: %v, err: %v", req.data, err)) }
} if req.data == nil || req.status != OK {
dataLength = 0
} }
var hOut OutHeader sizeOfOutHeader := unsafe.Sizeof(OutHeader{})
hOut.Unique = req.inHeader.Unique
hOut.Status = -req.status
hOut.Length = uint32(buf.Len() + len(req.flatData))
data := buf.Bytes() req.outHeaderBytes = make([]byte, sizeOfOutHeader + dataLength)
outHeader := (*OutHeader)(unsafe.Pointer(&req.outHeaderBytes[0]))
outHeader.Unique = req.inHeader.Unique
outHeader.Status = -req.status
outHeader.Length = uint32(sizeOfOutHeader + dataLength + len(req.flatData))
buf = bytes.NewBuffer(data[:0]) copy(req.outHeaderBytes[sizeOfOutHeader:], asSlice(req.data, dataLength))
err := binary.Write(buf, binary.LittleEndian, &hOut)
if err != nil {
panic("Can't serialize OutHeader")
}
req.output = data
if debug { if debug {
val := fmt.Sprintf("%v", req.data) val := fmt.Sprintf("%v", req.outHeaderBytes)
max := 1024 max := 1024
if len(val) > max { if len(val) > max {
val = val[:max] + fmt.Sprintf(" ...trimmed (response size %d)", hOut.Length) val = val[:max] + fmt.Sprintf(" ...trimmed (response size %d)", outHeader.Length)
} }
log.Printf("Serialize: %v code: %v value: %v flat: %d\n", log.Printf("Serialize: %v code: %v value: %v flat: %d\n",
...@@ -520,7 +550,7 @@ func serialize(req *fuseRequest, debug bool) { ...@@ -520,7 +550,7 @@ func serialize(req *fuseRequest, debug bool) {
} }
} }
func initFuse(state *MountState, h *InHeader, input *InitIn) (Empty, Status) { func initFuse(state *MountState, h *InHeader, input *InitIn) (unsafe.Pointer, Status) {
out, initStatus := state.fileSystem.Init(h, input) out, initStatus := state.fileSystem.Init(h, input)
if initStatus != OK { if initStatus != OK {
return nil, initStatus return nil, initStatus
...@@ -542,13 +572,13 @@ func initFuse(state *MountState, h *InHeader, input *InitIn) (Empty, Status) { ...@@ -542,13 +572,13 @@ func initFuse(state *MountState, h *InHeader, input *InitIn) (Empty, Status) {
out.MaxWrite = maxRead out.MaxWrite = maxRead
return out, OK return unsafe.Pointer(out), OK
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Handling files. // Handling files.
func doOpen(state *MountState, header *InHeader, input *OpenIn) (genericOut Empty, code Status) { func doOpen(state *MountState, header *InHeader, input *OpenIn) (unsafe.Pointer, Status) {
flags, fuseFile, status := state.fileSystem.Open(header, input) flags, fuseFile, status := state.fileSystem.Open(header, input)
if status != OK { if status != OK {
return nil, status return nil, status
...@@ -559,10 +589,10 @@ func doOpen(state *MountState, header *InHeader, input *OpenIn) (genericOut Empt ...@@ -559,10 +589,10 @@ func doOpen(state *MountState, header *InHeader, input *OpenIn) (genericOut Empt
out := new(OpenOut) out := new(OpenOut)
out.Fh = state.RegisterFile(fuseFile) out.Fh = state.RegisterFile(fuseFile)
out.OpenFlags = flags out.OpenFlags = flags
return out, status return unsafe.Pointer(out), status
} }
func doCreate(state *MountState, header *InHeader, input *CreateIn, name string) (genericOut Empty, code Status) { func doCreate(state *MountState, header *InHeader, input *CreateIn, name string) (unsafe.Pointer, Status) {
flags, fuseFile, entry, status := state.fileSystem.Create(header, input, name) flags, fuseFile, entry, status := state.fileSystem.Create(header, input, name)
if status != OK { if status != OK {
return nil, status return nil, status
...@@ -574,15 +604,16 @@ func doCreate(state *MountState, header *InHeader, input *CreateIn, name string) ...@@ -574,15 +604,16 @@ func doCreate(state *MountState, header *InHeader, input *CreateIn, name string)
out.Entry = *entry out.Entry = *entry
out.Open.Fh = state.RegisterFile(fuseFile) out.Open.Fh = state.RegisterFile(fuseFile)
out.Open.OpenFlags = flags out.Open.OpenFlags = flags
return out, status
return unsafe.Pointer(out), status
} }
func doRelease(state *MountState, header *InHeader, input *ReleaseIn) (out Empty, code Status) { func doRelease(state *MountState, header *InHeader, input *ReleaseIn) (code Status) {
f := state.FindFile(input.Fh) f := state.FindFile(input.Fh)
state.fileSystem.Release(header, f) state.fileSystem.Release(header, f)
f.Release() f.Release()
state.UnregisterFile(input.Fh) state.UnregisterFile(input.Fh)
return nil, OK return OK
} }
func doRead(state *MountState, header *InHeader, input *ReadIn, buffers *BufferPool) (out []byte, code Status) { func doRead(state *MountState, header *InHeader, input *ReadIn, buffers *BufferPool) (out []byte, code Status) {
...@@ -590,26 +621,28 @@ func doRead(state *MountState, header *InHeader, input *ReadIn, buffers *BufferP ...@@ -590,26 +621,28 @@ func doRead(state *MountState, header *InHeader, input *ReadIn, buffers *BufferP
return output, code return output, code
} }
func doWrite(state *MountState, header *InHeader, input *WriteIn, data []byte) (out WriteOut, code Status) { func doWrite(state *MountState, header *InHeader, input *WriteIn, data []byte) (out unsafe.Pointer, code Status) {
n, status := state.FindFile(input.Fh).Write(input, data) n, status := state.FindFile(input.Fh).Write(input, data)
out.Size = n o := new(WriteOut)
return out, status o.Size = n
return unsafe.Pointer(o), status
} }
func doFsync(state *MountState, header *InHeader, input *FsyncIn) (code Status) { func doFsync(state *MountState, header *InHeader, input *FsyncIn) (code Status) {
return state.FindFile(input.Fh).Fsync(input) return state.FindFile(input.Fh).Fsync(input)
} }
func doFlush(state *MountState, header *InHeader, input *FlushIn) (out Empty, code Status) { func doFlush(state *MountState, header *InHeader, input *FlushIn) (code Status) {
return nil, state.FindFile(input.Fh).Flush() return state.FindFile(input.Fh).Flush()
} }
func doSetattr(state *MountState, header *InHeader, input *SetAttrIn) (out *AttrOut, code Status) { func doSetattr(state *MountState, header *InHeader, input *SetAttrIn) (out unsafe.Pointer, code Status) {
// TODO - if Fh != 0, we should do a FSetAttr instead. // TODO - if Fh != 0, we should do a FSetAttr instead.
return state.fileSystem.SetAttr(header, input) o, s := state.fileSystem.SetAttr(header, input)
return unsafe.Pointer(o), s
} }
func doGetXAttr(state *MountState, header *InHeader, input *GetXAttrIn, attr string) (out Empty, data []byte, code Status) { func doGetXAttr(state *MountState, header *InHeader, input *GetXAttrIn, attr string) (out unsafe.Pointer, data []byte, code Status) {
data, code = state.fileSystem.GetXAttr(header, attr) data, code = state.fileSystem.GetXAttr(header, attr)
if code != OK { if code != OK {
return nil, nil, code return nil, nil, code
...@@ -619,7 +652,7 @@ func doGetXAttr(state *MountState, header *InHeader, input *GetXAttrIn, attr str ...@@ -619,7 +652,7 @@ func doGetXAttr(state *MountState, header *InHeader, input *GetXAttrIn, attr str
if input.Size == 0 { if input.Size == 0 {
out := new(GetXAttrOut) out := new(GetXAttrOut)
out.Size = size out.Size = size
return out, nil, OK return unsafe.Pointer(out), nil, OK
} }
if size > input.Size { if size > input.Size {
...@@ -632,15 +665,15 @@ func doGetXAttr(state *MountState, header *InHeader, input *GetXAttrIn, attr str ...@@ -632,15 +665,15 @@ func doGetXAttr(state *MountState, header *InHeader, input *GetXAttrIn, attr str
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Handling directories // Handling directories
func doReleaseDir(state *MountState, header *InHeader, input *ReleaseIn) (out Empty, code Status) { func doReleaseDir(state *MountState, header *InHeader, input *ReleaseIn) (code Status) {
d := state.FindDir(input.Fh) d := state.FindDir(input.Fh)
state.fileSystem.ReleaseDir(header, d) state.fileSystem.ReleaseDir(header, d)
d.ReleaseDir() d.ReleaseDir()
state.UnregisterDir(input.Fh) state.UnregisterDir(input.Fh)
return nil, OK return OK
} }
func doOpenDir(state *MountState, header *InHeader, input *OpenIn) (genericOut Empty, code Status) { func doOpenDir(state *MountState, header *InHeader, input *OpenIn) (unsafe.Pointer, Status) {
flags, fuseDir, status := state.fileSystem.OpenDir(header, input) flags, fuseDir, status := state.fileSystem.OpenDir(header, input)
if status != OK { if status != OK {
return nil, status return nil, status
...@@ -649,15 +682,14 @@ func doOpenDir(state *MountState, header *InHeader, input *OpenIn) (genericOut E ...@@ -649,15 +682,14 @@ func doOpenDir(state *MountState, header *InHeader, input *OpenIn) (genericOut E
out := new(OpenOut) out := new(OpenOut)
out.Fh = state.RegisterDir(fuseDir) out.Fh = state.RegisterDir(fuseDir)
out.OpenFlags = flags out.OpenFlags = flags
return out, status return unsafe.Pointer(out), status
} }
func doReadDir(state *MountState, header *InHeader, input *ReadIn) (out Empty, code Status) { func doReadDir(state *MountState, header *InHeader, input *ReadIn) (out []byte, code Status) {
dir := state.FindDir(input.Fh) dir := state.FindDir(input.Fh)
entries, code := dir.ReadDir(input) entries, code := dir.ReadDir(input)
if entries == nil { if entries == nil {
var emptyBytes []byte return nil, code
return emptyBytes, code
} }
return entries.Bytes(), code return entries.Bytes(), code
} }
......
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
package fuse package fuse
import ( import (
"bytes"
"encoding/binary"
"os" "os"
"fmt" "fmt"
"log" "log"
...@@ -144,77 +142,6 @@ func (code Status) String() string { ...@@ -144,77 +142,6 @@ func (code Status) String() string {
return fmt.Sprintf("%d=%v", int(code), os.Errno(code)) return fmt.Sprintf("%d=%v", int(code), os.Errno(code))
} }
func newInput(opcode uint32) Empty {
switch opcode {
case FUSE_FORGET:
return new(ForgetIn)
case FUSE_GETATTR:
return new(GetAttrIn)
case FUSE_MKNOD:
return new(MknodIn)
case FUSE_MKDIR:
return new(MkdirIn)
case FUSE_RENAME:
return new(RenameIn)
case FUSE_LINK:
return new(LinkIn)
case FUSE_SETATTR:
return new(SetAttrIn)
case FUSE_OPEN:
return new(OpenIn)
case FUSE_CREATE:
return new(CreateIn)
case FUSE_FLUSH:
return new(FlushIn)
case FUSE_RELEASE:
return new(ReleaseIn)
case FUSE_READ:
return new(ReadIn)
case FUSE_WRITE:
return new(WriteIn)
case FUSE_FSYNC:
return new(FsyncIn)
// case FUSE_GET/SETLK(W)
case FUSE_ACCESS:
return new(AccessIn)
case FUSE_INIT:
return new(InitIn)
case FUSE_BMAP:
return new(BmapIn)
case FUSE_INTERRUPT:
return new(InterruptIn)
case FUSE_IOCTL:
return new(IoctlIn)
case FUSE_POLL:
return new(PollIn)
case FUSE_SETXATTR:
return new(SetXAttrIn)
case FUSE_GETXATTR:
return new(GetXAttrIn)
case FUSE_OPENDIR:
return new(OpenIn)
case FUSE_FSYNCDIR:
return new(FsyncIn)
case FUSE_READDIR:
return new(ReadIn)
case FUSE_RELEASEDIR:
return new(ReleaseIn)
}
return nil
}
func parseLittleEndian(b *bytes.Buffer, data interface{}) bool {
err := binary.Read(b, binary.LittleEndian, data)
if err == nil {
return true
}
if err == os.EOF {
return false
}
panic(fmt.Sprintf("Cannot parse %v", data))
}
func SplitNs(time float64, secs *uint64, nsecs *uint32) { func SplitNs(time float64, secs *uint64, nsecs *uint32) {
*nsecs = uint32(1e9 * (time - math.Trunc(time))) *nsecs = uint32(1e9 * (time - math.Trunc(time)))
*secs = uint64(math.Trunc(time)) *secs = uint64(math.Trunc(time))
...@@ -327,3 +254,91 @@ func MyPID() string { ...@@ -327,3 +254,91 @@ func MyPID() string {
v, _ := os.Readlink("/proc/self") v, _ := os.Readlink("/proc/self")
return v return v
} }
var inputSizeMap map[int]int
var outputSizeMap map[int]int
func init() {
inputSizeMap = map[int]int{
FUSE_LOOKUP: 0,
FUSE_FORGET: unsafe.Sizeof(ForgetIn{}),
FUSE_GETATTR: unsafe.Sizeof(GetAttrIn{}),
FUSE_SETATTR: unsafe.Sizeof(SetAttrIn{}),
FUSE_READLINK: 0,
FUSE_SYMLINK: 0,
FUSE_MKNOD: unsafe.Sizeof(MknodIn{}),
FUSE_MKDIR: unsafe.Sizeof(MkdirIn{}),
FUSE_UNLINK: 0,
FUSE_RMDIR: 0,
FUSE_RENAME: unsafe.Sizeof(RenameIn{}),
FUSE_LINK: unsafe.Sizeof(LinkIn{}),
FUSE_OPEN: unsafe.Sizeof(OpenIn{}),
FUSE_READ: unsafe.Sizeof(ReadIn{}),
FUSE_WRITE: unsafe.Sizeof(WriteIn{}),
FUSE_STATFS: 0,
FUSE_RELEASE: unsafe.Sizeof(ReleaseIn{}),
FUSE_FSYNC: unsafe.Sizeof(FsyncIn{}),
FUSE_SETXATTR: unsafe.Sizeof(SetXAttrIn{}),
FUSE_GETXATTR: unsafe.Sizeof(GetXAttrIn{}),
FUSE_LISTXATTR: 0,
FUSE_REMOVEXATTR: 0,
FUSE_FLUSH: unsafe.Sizeof(FlushIn{}),
FUSE_INIT: unsafe.Sizeof(InitIn{}),
FUSE_OPENDIR: unsafe.Sizeof(OpenIn{}),
FUSE_READDIR: unsafe.Sizeof(ReadIn{}),
FUSE_RELEASEDIR: unsafe.Sizeof(ReleaseIn{}),
FUSE_FSYNCDIR: unsafe.Sizeof(FsyncIn{}),
FUSE_GETLK: 0,
FUSE_SETLK: 0,
FUSE_SETLKW: 0,
FUSE_ACCESS: unsafe.Sizeof(AccessIn{}),
FUSE_CREATE: unsafe.Sizeof(CreateIn{}),
FUSE_INTERRUPT: unsafe.Sizeof(InterruptIn{}),
FUSE_BMAP: unsafe.Sizeof(BmapIn{}),
FUSE_DESTROY: 0,
FUSE_IOCTL: unsafe.Sizeof(IoctlIn{}),
FUSE_POLL: unsafe.Sizeof(PollIn{}),
}
outputSizeMap = map[int]int {
FUSE_LOOKUP: unsafe.Sizeof(EntryOut{}),
FUSE_FORGET: 0,
FUSE_GETATTR: unsafe.Sizeof(AttrOut{}),
FUSE_SETATTR: unsafe.Sizeof(AttrOut{}),
FUSE_READLINK: 0,
FUSE_SYMLINK: unsafe.Sizeof(EntryOut{}),
FUSE_MKNOD: unsafe.Sizeof(EntryOut{}),
FUSE_MKDIR: unsafe.Sizeof(EntryOut{}),
FUSE_UNLINK: 0,
FUSE_RMDIR: 0,
FUSE_RENAME: 0,
FUSE_LINK: unsafe.Sizeof(EntryOut{}),
FUSE_OPEN: unsafe.Sizeof(OpenOut{}),
FUSE_READ: 0,
FUSE_WRITE: unsafe.Sizeof(WriteOut{}),
FUSE_STATFS: unsafe.Sizeof(StatfsOut{}),
FUSE_RELEASE: 0,
FUSE_FSYNC: 0,
FUSE_SETXATTR: 0,
FUSE_GETXATTR: unsafe.Sizeof(GetXAttrOut{}),
FUSE_LISTXATTR: 0,
FUSE_REMOVEXATTR: 0,
FUSE_FLUSH: 0,
FUSE_INIT: unsafe.Sizeof(InitOut{}),
FUSE_OPENDIR: unsafe.Sizeof(OpenOut{}),
FUSE_READDIR: 0,
FUSE_RELEASEDIR: 0,
FUSE_FSYNCDIR: 0,
// TODO
FUSE_GETLK: 0,
FUSE_SETLK: 0,
FUSE_SETLKW: 0,
FUSE_ACCESS: 0,
FUSE_CREATE: unsafe.Sizeof(CreateOut{}),
FUSE_INTERRUPT: 0,
FUSE_BMAP: unsafe.Sizeof(BmapOut{}),
FUSE_DESTROY: 0,
FUSE_IOCTL: unsafe.Sizeof(IoctlOut{}),
FUSE_POLL: unsafe.Sizeof(PollOut{}),
}
}
...@@ -327,7 +327,6 @@ type WriteOut struct { ...@@ -327,7 +327,6 @@ type WriteOut struct {
Padding uint32 Padding uint32
} }
type StatfsOut struct { type StatfsOut struct {
St Kstatfs St Kstatfs
} }
...@@ -461,8 +460,6 @@ type InHeader struct { ...@@ -461,8 +460,6 @@ type InHeader struct {
Padding uint32 Padding uint32
} }
const SizeOfOutHeader = 16
type OutHeader struct { type OutHeader struct {
Length uint32 Length uint32
Status Status Status Status
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment