Commit 547051cf authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Collapse arrays into one array of operationHandler.

parent 87625729
...@@ -254,74 +254,68 @@ func (me *MountState) Loop(threaded bool) { ...@@ -254,74 +254,68 @@ func (me *MountState) Loop(threaded bool) {
} }
func (me *MountState) chopMessage(req *request) bool { func (me *MountState) chopMessage(req *request) *operationHandler {
inHSize := unsafe.Sizeof(InHeader{}) inHSize := unsafe.Sizeof(InHeader{})
if len(req.inputBuf) < inHSize { if len(req.inputBuf) < inHSize {
me.Error(os.NewError(fmt.Sprintf("Short read for input header: %v", req.inputBuf))) me.Error(os.NewError(fmt.Sprintf("Short read for input header: %v", req.inputBuf)))
return false return nil
} }
req.inHeader = (*InHeader)(unsafe.Pointer(&req.inputBuf[0])) req.inHeader = (*InHeader)(unsafe.Pointer(&req.inputBuf[0]))
req.arg = req.inputBuf[inHSize:] req.arg = req.inputBuf[inHSize:]
argSize, ok := inputSize(req.inHeader.Opcode) handler := getHandler(req.inHeader.Opcode)
if !ok { if handler == nil || handler.Func == nil {
log.Println("Unknown opcode %d (input)", req.inHeader.Opcode) log.Println("Unknown opcode %d (input)", req.inHeader.Opcode)
req.status = ENOSYS req.status = ENOSYS
return true return handler
} }
if len(req.arg) < argSize { if len(req.arg) < handler.InputSize {
log.Println("Short read for %v: %v", req.inHeader.Opcode, req.arg) log.Println("Short read for %v: %v", req.inHeader.Opcode, req.arg)
req.status = EIO req.status = EIO
return true return handler
} }
if argSize > 0 { if handler.InputSize > 0 {
req.inData = unsafe.Pointer(&req.arg[0]) req.inData = unsafe.Pointer(&req.arg[0])
req.arg = req.arg[argSize:] req.arg = req.arg[handler.InputSize:]
} }
return true return handler
} }
func (me *MountState) handle(req *request) { func (me *MountState) handle(req *request) {
defer me.discardRequest(req) defer me.discardRequest(req)
if !me.chopMessage(req) { handler := me.chopMessage(req)
if handler == nil {
return return
} }
if req.status == OK { if req.status == OK {
me.dispatch(req) me.dispatch(req, handler)
} }
// 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
if req.inHeader.Opcode != FUSE_FORGET { if req.inHeader.Opcode != FUSE_FORGET {
serialize(req, me.Debug) serialize(req, handler, me.Debug)
req.preWriteNs = time.Nanoseconds() req.preWriteNs = time.Nanoseconds()
me.Write(req) me.Write(req)
} }
} }
func (me *MountState) dispatch(req *request) { func (me *MountState) dispatch(req *request, handler *operationHandler) {
req.dispatchNs = time.Nanoseconds() req.dispatchNs = time.Nanoseconds()
f := lookupOperation(req.inHeader.Opcode)
if f == nil {
msg := fmt.Sprintf("Unsupported OpCode: %d=%v",
req.inHeader.Opcode, operationName(req.inHeader.Opcode))
me.Error(os.NewError(msg))
req.status = ENOSYS
return
}
if me.Debug { if me.Debug {
nm := "" nm := ""
// TODO - reinstate filename printing. // TODO - reinstate filename printing.
log.Printf("Dispatch: %v, NodeId: %v %s\n", log.Printf("Dispatch: %v, NodeId: %v %s\n",
operationName(req.inHeader.Opcode), req.inHeader.NodeId, nm) operationName(req.inHeader.Opcode), req.inHeader.NodeId, nm)
} }
f(me, req) handler.Func(me, req)
} }
// Thanks to Andrew Gerrand for this hack. // Thanks to Andrew Gerrand for this hack.
...@@ -330,13 +324,8 @@ func asSlice(ptr unsafe.Pointer, byteCount int) []byte { ...@@ -330,13 +324,8 @@ func asSlice(ptr unsafe.Pointer, byteCount int) []byte {
return *(*[]byte)(unsafe.Pointer(h)) return *(*[]byte)(unsafe.Pointer(h))
} }
func serialize(req *request, debug bool) { func serialize(req *request, handler *operationHandler, debug bool) {
dataLength, ok := outputSize(req.inHeader.Opcode) dataLength := handler.OutputSize
if !ok {
log.Println("Unknown opcode %d (output)", req.inHeader.Opcode)
req.status = ENOSYS
return
}
if req.outData == nil || req.status != OK { if req.outData == nil || req.status != OK {
dataLength = 0 dataLength = 0
} }
......
...@@ -231,138 +231,94 @@ func doRename(state *MountState, req *request) { ...@@ -231,138 +231,94 @@ func doRename(state *MountState, req *request) {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
var operationNames []string type operationFunc func(*MountState, *request)
var inputSizes []int
var outputSizes []int
type operation func(*MountState, *request) type operationHandler struct {
Name string
Func operationFunc
InputSize int
OutputSize int
}
var operationFuncs []operation var operationHandlers []*operationHandler
func operationName(opcode Opcode) string { func operationName(opcode Opcode) string {
if opcode > OPCODE_COUNT { h := getHandler(opcode)
if h == nil {
return "unknown" return "unknown"
} }
return operationNames[opcode] return h.Name
}
func inputSize(o Opcode) (int, bool) {
return lookupSize(o, inputSizes)
}
func outputSize(o Opcode) (int, bool) {
return lookupSize(o, outputSizes)
} }
func lookupSize(o Opcode, sMap []int) (int, bool) { func getHandler(o Opcode) *operationHandler {
if o >= OPCODE_COUNT { if o >= OPCODE_COUNT {
return -1, false return nil
} }
return sMap[int(o)], true return operationHandlers[o]
} }
func lookupOperation(o Opcode) operation { func init() {
return operationFuncs[o] operationHandlers = make([]*operationHandler, OPCODE_COUNT)
} for i, _ := range operationHandlers {
operationHandlers[i] = &operationHandler{Name: "UNKNOWN"}
func makeSizes(dict map[int]int) []int {
out := make([]int, OPCODE_COUNT)
for i, _ := range out {
out[i] = -1
}
for code, val := range dict {
out[code] = val
} }
return out
}
func init() { for op, sz := range map[int]int{
inputSizes = makeSizes(map[int]int{
FUSE_LOOKUP: 0,
FUSE_FORGET: unsafe.Sizeof(ForgetIn{}), FUSE_FORGET: unsafe.Sizeof(ForgetIn{}),
FUSE_GETATTR: unsafe.Sizeof(GetAttrIn{}), FUSE_GETATTR: unsafe.Sizeof(GetAttrIn{}),
FUSE_SETATTR: unsafe.Sizeof(SetAttrIn{}), FUSE_SETATTR: unsafe.Sizeof(SetAttrIn{}),
FUSE_READLINK: 0,
FUSE_SYMLINK: 0,
FUSE_MKNOD: unsafe.Sizeof(MknodIn{}), FUSE_MKNOD: unsafe.Sizeof(MknodIn{}),
FUSE_MKDIR: unsafe.Sizeof(MkdirIn{}), FUSE_MKDIR: unsafe.Sizeof(MkdirIn{}),
FUSE_UNLINK: 0,
FUSE_RMDIR: 0,
FUSE_RENAME: unsafe.Sizeof(RenameIn{}), FUSE_RENAME: unsafe.Sizeof(RenameIn{}),
FUSE_LINK: unsafe.Sizeof(LinkIn{}), FUSE_LINK: unsafe.Sizeof(LinkIn{}),
FUSE_OPEN: unsafe.Sizeof(OpenIn{}), FUSE_OPEN: unsafe.Sizeof(OpenIn{}),
FUSE_READ: unsafe.Sizeof(ReadIn{}), FUSE_READ: unsafe.Sizeof(ReadIn{}),
FUSE_WRITE: unsafe.Sizeof(WriteIn{}), FUSE_WRITE: unsafe.Sizeof(WriteIn{}),
FUSE_STATFS: 0,
FUSE_RELEASE: unsafe.Sizeof(ReleaseIn{}), FUSE_RELEASE: unsafe.Sizeof(ReleaseIn{}),
FUSE_FSYNC: unsafe.Sizeof(FsyncIn{}), FUSE_FSYNC: unsafe.Sizeof(FsyncIn{}),
FUSE_SETXATTR: unsafe.Sizeof(SetXAttrIn{}), FUSE_SETXATTR: unsafe.Sizeof(SetXAttrIn{}),
FUSE_GETXATTR: unsafe.Sizeof(GetXAttrIn{}), FUSE_GETXATTR: unsafe.Sizeof(GetXAttrIn{}),
FUSE_LISTXATTR: unsafe.Sizeof(GetXAttrIn{}), FUSE_LISTXATTR: unsafe.Sizeof(GetXAttrIn{}),
FUSE_REMOVEXATTR: 0,
FUSE_FLUSH: unsafe.Sizeof(FlushIn{}), FUSE_FLUSH: unsafe.Sizeof(FlushIn{}),
FUSE_INIT: unsafe.Sizeof(InitIn{}), FUSE_INIT: unsafe.Sizeof(InitIn{}),
FUSE_OPENDIR: unsafe.Sizeof(OpenIn{}), FUSE_OPENDIR: unsafe.Sizeof(OpenIn{}),
FUSE_READDIR: unsafe.Sizeof(ReadIn{}), FUSE_READDIR: unsafe.Sizeof(ReadIn{}),
FUSE_RELEASEDIR: unsafe.Sizeof(ReleaseIn{}), FUSE_RELEASEDIR: unsafe.Sizeof(ReleaseIn{}),
FUSE_FSYNCDIR: unsafe.Sizeof(FsyncIn{}), FUSE_FSYNCDIR: unsafe.Sizeof(FsyncIn{}),
FUSE_GETLK: 0,
FUSE_SETLK: 0,
FUSE_SETLKW: 0,
FUSE_ACCESS: unsafe.Sizeof(AccessIn{}), FUSE_ACCESS: unsafe.Sizeof(AccessIn{}),
FUSE_CREATE: unsafe.Sizeof(CreateIn{}), FUSE_CREATE: unsafe.Sizeof(CreateIn{}),
FUSE_INTERRUPT: unsafe.Sizeof(InterruptIn{}), FUSE_INTERRUPT: unsafe.Sizeof(InterruptIn{}),
FUSE_BMAP: unsafe.Sizeof(BmapIn{}), FUSE_BMAP: unsafe.Sizeof(BmapIn{}),
FUSE_DESTROY: 0,
FUSE_IOCTL: unsafe.Sizeof(IoctlIn{}), FUSE_IOCTL: unsafe.Sizeof(IoctlIn{}),
FUSE_POLL: unsafe.Sizeof(PollIn{}), FUSE_POLL: unsafe.Sizeof(PollIn{}),
}) } {
operationHandlers[op].InputSize = sz
}
outputSizes = makeSizes(map[int]int{ for op, sz := range map[int]int{
FUSE_LOOKUP: unsafe.Sizeof(EntryOut{}), FUSE_LOOKUP: unsafe.Sizeof(EntryOut{}),
FUSE_FORGET: 0,
FUSE_GETATTR: unsafe.Sizeof(AttrOut{}), FUSE_GETATTR: unsafe.Sizeof(AttrOut{}),
FUSE_SETATTR: unsafe.Sizeof(AttrOut{}), FUSE_SETATTR: unsafe.Sizeof(AttrOut{}),
FUSE_READLINK: 0,
FUSE_SYMLINK: unsafe.Sizeof(EntryOut{}), FUSE_SYMLINK: unsafe.Sizeof(EntryOut{}),
FUSE_MKNOD: unsafe.Sizeof(EntryOut{}), FUSE_MKNOD: unsafe.Sizeof(EntryOut{}),
FUSE_MKDIR: unsafe.Sizeof(EntryOut{}), FUSE_MKDIR: unsafe.Sizeof(EntryOut{}),
FUSE_UNLINK: 0,
FUSE_RMDIR: 0,
FUSE_RENAME: 0,
FUSE_LINK: unsafe.Sizeof(EntryOut{}), FUSE_LINK: unsafe.Sizeof(EntryOut{}),
FUSE_OPEN: unsafe.Sizeof(OpenOut{}), FUSE_OPEN: unsafe.Sizeof(OpenOut{}),
FUSE_READ: 0,
FUSE_WRITE: unsafe.Sizeof(WriteOut{}), FUSE_WRITE: unsafe.Sizeof(WriteOut{}),
FUSE_STATFS: unsafe.Sizeof(StatfsOut{}), FUSE_STATFS: unsafe.Sizeof(StatfsOut{}),
FUSE_RELEASE: 0,
FUSE_FSYNC: 0,
FUSE_SETXATTR: 0,
FUSE_GETXATTR: unsafe.Sizeof(GetXAttrOut{}), FUSE_GETXATTR: unsafe.Sizeof(GetXAttrOut{}),
FUSE_LISTXATTR: unsafe.Sizeof(GetXAttrOut{}), FUSE_LISTXATTR: unsafe.Sizeof(GetXAttrOut{}),
FUSE_REMOVEXATTR: 0,
FUSE_FLUSH: 0,
FUSE_INIT: unsafe.Sizeof(InitOut{}), FUSE_INIT: unsafe.Sizeof(InitOut{}),
FUSE_OPENDIR: unsafe.Sizeof(OpenOut{}), 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_CREATE: unsafe.Sizeof(CreateOut{}),
FUSE_INTERRUPT: 0,
FUSE_BMAP: unsafe.Sizeof(BmapOut{}), FUSE_BMAP: unsafe.Sizeof(BmapOut{}),
FUSE_DESTROY: 0,
FUSE_IOCTL: unsafe.Sizeof(IoctlOut{}), FUSE_IOCTL: unsafe.Sizeof(IoctlOut{}),
FUSE_POLL: unsafe.Sizeof(PollOut{}), FUSE_POLL: unsafe.Sizeof(PollOut{}),
}) } {
operationHandlers[op].OutputSize = sz
}
operationNames = make([]string, OPCODE_COUNT) for op, v := range map[int]string{
for k, v := range map[int]string{
FUSE_LOOKUP: "FUSE_LOOKUP", FUSE_LOOKUP: "FUSE_LOOKUP",
FUSE_FORGET: "FUSE_FORGET", FUSE_FORGET: "FUSE_FORGET",
FUSE_GETATTR: "FUSE_GETATTR", FUSE_GETATTR: "FUSE_GETATTR",
...@@ -401,11 +357,10 @@ func init() { ...@@ -401,11 +357,10 @@ func init() {
FUSE_DESTROY: "FUSE_DESTROY", FUSE_DESTROY: "FUSE_DESTROY",
FUSE_IOCTL: "FUSE_IOCTL", FUSE_IOCTL: "FUSE_IOCTL",
FUSE_POLL: "FUSE_POLL"} { FUSE_POLL: "FUSE_POLL"} {
operationNames[k] = v operationHandlers[op].Name = v
} }
operationFuncs = make([]operation, OPCODE_COUNT) for op, v := range map[Opcode]operationFunc{
for k, v := range map[Opcode]operation{
FUSE_OPEN: doOpen, FUSE_OPEN: doOpen,
FUSE_READDIR: doReadDir, FUSE_READDIR: doReadDir,
FUSE_WRITE: doWrite, FUSE_WRITE: doWrite,
...@@ -437,6 +392,6 @@ func init() { ...@@ -437,6 +392,6 @@ func init() {
FUSE_SYMLINK: doSymlink, FUSE_SYMLINK: doSymlink,
FUSE_RENAME: doRename, FUSE_RENAME: doRename,
} { } {
operationFuncs[k] = v operationHandlers[op].Func = v
} }
} }
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