Commit 736b11e3 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Pass raw []byte data directly to writev using a separate Iovec entry.

parent 4f8976bb
...@@ -252,16 +252,18 @@ func (self *MountState) handle(in_data []byte) { ...@@ -252,16 +252,18 @@ func (self *MountState) handle(in_data []byte) {
func dispatch(state *MountState, h *InHeader, arg *bytes.Buffer) (outBytes [][]byte) { func dispatch(state *MountState, h *InHeader, arg *bytes.Buffer) (outBytes [][]byte) {
input := newInput(h.Opcode) input := newInput(h.Opcode)
if input != nil && !parseLittleEndian(arg, input) { if input != nil && !parseLittleEndian(arg, input) {
return serialize(h, EIO, nil, false) return serialize(h, EIO, nil, nil, false)
} }
var out Empty var out Empty
var status Status var status Status
var flatData []byte
out = nil out = nil
status = OK status = OK
fs := state.fileSystem fs := state.fileSystem
filename := "" filename := ""
// Perhaps a map is faster? // Perhaps a map is faster?
if h.Opcode == FUSE_UNLINK || h.Opcode == FUSE_RMDIR || if h.Opcode == FUSE_UNLINK || h.Opcode == FUSE_RMDIR ||
...@@ -327,7 +329,7 @@ func dispatch(state *MountState, h *InHeader, arg *bytes.Buffer) (outBytes [][]b ...@@ -327,7 +329,7 @@ func dispatch(state *MountState, h *InHeader, arg *bytes.Buffer) (outBytes [][]b
case FUSE_OPEN: case FUSE_OPEN:
out, status = doOpen(state, h, input.(*OpenIn)) out, status = doOpen(state, h, input.(*OpenIn))
case FUSE_READ: case FUSE_READ:
out, status = doRead(state, h, input.(*ReadIn)) flatData, status = doRead(state, h, input.(*ReadIn))
case FUSE_WRITE: case FUSE_WRITE:
out, status = doWrite(state, h, input.(*WriteIn), arg.Bytes()) out, status = doWrite(state, h, input.(*WriteIn), arg.Bytes())
case FUSE_FLUSH: case FUSE_FLUSH:
...@@ -336,7 +338,6 @@ func dispatch(state *MountState, h *InHeader, arg *bytes.Buffer) (outBytes [][]b ...@@ -336,7 +338,6 @@ func dispatch(state *MountState, h *InHeader, arg *bytes.Buffer) (outBytes [][]b
out, status = doRelease(state, h, input.(*ReleaseIn)) out, status = doRelease(state, h, input.(*ReleaseIn))
case FUSE_FSYNC: case FUSE_FSYNC:
status = doFsync(state, h, input.(*FsyncIn)) status = doFsync(state, h, input.(*FsyncIn))
case FUSE_OPENDIR: case FUSE_OPENDIR:
out, status = doOpenDir(state, h, input.(*OpenIn)) out, status = doOpenDir(state, h, input.(*OpenIn))
case FUSE_READDIR: case FUSE_READDIR:
...@@ -373,13 +374,13 @@ func dispatch(state *MountState, h *InHeader, arg *bytes.Buffer) (outBytes [][]b ...@@ -373,13 +374,13 @@ func dispatch(state *MountState, h *InHeader, arg *bytes.Buffer) (outBytes [][]b
// case FUSE_INTERRUPT // case FUSE_INTERRUPT
default: default:
state.Error(os.NewError(fmt.Sprintf("Unsupported OpCode: %d=%v", h.Opcode, operationName(h.Opcode)))) state.Error(os.NewError(fmt.Sprintf("Unsupported OpCode: %d=%v", h.Opcode, operationName(h.Opcode))))
return serialize(h, ENOSYS, nil, false) return serialize(h, ENOSYS, nil, nil, false)
} }
return serialize(h, status, out, state.Debug) return serialize(h, status, out, flatData, state.Debug)
} }
func serialize(h *InHeader, res Status, out interface{}, debug bool) (data [][]byte) { func serialize(h *InHeader, res Status, out interface{}, flatData []byte, debug bool) ([][]byte) {
out_data := make([]byte, 0) out_data := make([]byte, 0)
b := new(bytes.Buffer) b := new(bytes.Buffer)
if out != nil && res == OK { if out != nil && res == OK {
...@@ -394,24 +395,24 @@ func serialize(h *InHeader, res Status, out interface{}, debug bool) (data [][]b ...@@ -394,24 +395,24 @@ func serialize(h *InHeader, res Status, out interface{}, debug bool) (data [][]b
var hout OutHeader var hout OutHeader
hout.Unique = h.Unique hout.Unique = h.Unique
hout.Status = -res hout.Status = -res
hout.Length = uint32(len(out_data) + SizeOfOutHeader) hout.Length = uint32(len(out_data) + SizeOfOutHeader + len(flatData))
b = new(bytes.Buffer) b = new(bytes.Buffer)
err := binary.Write(b, binary.LittleEndian, &hout) err := binary.Write(b, binary.LittleEndian, &hout)
if err != nil { if err != nil {
panic("Can't serialize OutHeader") panic("Can't serialize OutHeader")
} }
_, _ = b.Write(out_data)
data = [][]byte{b.Bytes()} data := [][]byte{b.Bytes(), out_data, flatData}
if debug { if debug {
val := fmt.Sprintf("%v", out) val := fmt.Sprintf("%v", out)
max := 1024 max := 1024
if len(val) > max { if len(val) > max {
val = val[:max] + fmt.Sprintf(" ...trimmed (response size %d)", len(b.Bytes())) val = val[:max] + fmt.Sprintf(" ...trimmed (response size %d)", hout.Length)
} }
log.Printf("Serialize: %v code: %v value: %v\n", log.Printf("Serialize: %v code: %v value: %v flat: %d\n",
operationName(h.Opcode), errorString(res), val) operationName(h.Opcode), errorString(res), val, len(flatData))
} }
return data return data
...@@ -479,7 +480,7 @@ func doRelease(state *MountState, header *InHeader, input *ReleaseIn) (out Empty ...@@ -479,7 +480,7 @@ func doRelease(state *MountState, header *InHeader, input *ReleaseIn) (out Empty
return nil, OK return nil, OK
} }
func doRead(state *MountState, header *InHeader, input *ReadIn) (out Empty, code Status) { func doRead(state *MountState, header *InHeader, input *ReadIn) (out []byte, code Status) {
output, code := state.FindFile(input.Fh).Read(input) output, code := state.FindFile(input.Fh).Read(input)
return output, code return output, code
} }
......
...@@ -11,6 +11,8 @@ import ( ...@@ -11,6 +11,8 @@ import (
"fmt" "fmt"
"path" "path"
"math" "math"
"syscall"
"unsafe"
) )
// Make a temporary directory securely. // Make a temporary directory securely.
...@@ -234,3 +236,35 @@ func CopyFileInfo(fi *os.FileInfo, attr *Attr) { ...@@ -234,3 +236,35 @@ func CopyFileInfo(fi *os.FileInfo, attr *Attr) {
attr.Rdev = uint32(fi.Rdev) attr.Rdev = uint32(fi.Rdev)
attr.Blksize = uint32(fi.Blksize) attr.Blksize = uint32(fi.Blksize)
} }
func writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, errno int) {
n1, _, e1 := syscall.Syscall(syscall.SYS_WRITEV, uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt))
n = int(n1)
errno = int(e1)
return
}
func Writev(fd int, packet [][]byte) (n int, err os.Error) {
if len(packet) == 0 {
return
}
iovecs := make([]syscall.Iovec, len(packet))
j := 0
for i, v := range packet {
if v == nil || len(v) == 0 {
continue
}
iovecs[j].Base = (*byte)(unsafe.Pointer(&packet[i][0]))
iovecs[j].SetLen(len(packet[i]))
j++
}
n, errno := writev(fd, (*syscall.Iovec)(unsafe.Pointer(&iovecs[0])), j)
if errno != 0 {
err = os.NewSyscallError("writev", errno)
return
}
return
}
...@@ -92,34 +92,6 @@ func unmount(mountPoint string) (err os.Error) { ...@@ -92,34 +92,6 @@ func unmount(mountPoint string) (err os.Error) {
return return
} }
func writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, errno int) {
n1, _, e1 := syscall.Syscall(syscall.SYS_WRITEV, uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt))
n = int(n1)
errno = int(e1)
return
}
func Writev(fd int, packet [][]byte) (n int, err os.Error) {
if len(packet) == 0 {
return
}
iovecs := make([]syscall.Iovec, len(packet))
for i, v := range packet {
if v == nil {
continue
}
iovecs[i].Base = (*byte)(unsafe.Pointer(&packet[i][0]))
iovecs[i].SetLen(len(packet[i]))
}
n, errno := writev(fd, (*syscall.Iovec)(unsafe.Pointer(&iovecs[0])), len(iovecs))
if errno != 0 {
err = os.NewSyscallError("writev", errno)
return
}
return
}
func getFuseConn(local *os.File) (f *os.File, err os.Error) { func getFuseConn(local *os.File) (f *os.File, err os.Error) {
var data [4]byte var data [4]byte
control := make([]byte, 4*256) control := make([]byte, 4*256)
......
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