Allow the kernel to send other requests while waiting for a read.
On Linux this significantly increases gcsfuse sequential read throughput.geesefs-0-30-9
commit
30cdb148b9
|
@ -158,7 +158,15 @@ func (c *Connection) Init() (err error) {
|
||||||
initOp.Library = c.protocol
|
initOp.Library = c.protocol
|
||||||
initOp.MaxReadahead = maxReadahead
|
initOp.MaxReadahead = maxReadahead
|
||||||
initOp.MaxWrite = buffer.MaxWriteSize
|
initOp.MaxWrite = buffer.MaxWriteSize
|
||||||
initOp.Flags = fusekernel.InitBigWrites
|
|
||||||
|
initOp.Flags = 0
|
||||||
|
|
||||||
|
// Tell the kernel not to use pitifully small 4 KiB writes.
|
||||||
|
initOp.Flags |= fusekernel.InitBigWrites
|
||||||
|
|
||||||
|
// Tell the kernel it is free to send further requests while a read request
|
||||||
|
// is in flight.
|
||||||
|
initOp.Flags |= fusekernel.InitAsyncRead
|
||||||
|
|
||||||
c.Reply(ctx, nil)
|
c.Reply(ctx, nil)
|
||||||
return
|
return
|
||||||
|
|
7
debug.go
7
debug.go
|
@ -20,6 +20,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func describeRequest(op interface{}) (s string) {
|
func describeRequest(op interface{}) (s string) {
|
||||||
|
// Handle special cases with custom formatting.
|
||||||
|
switch typed := op.(type) {
|
||||||
|
case *interruptOp:
|
||||||
|
s = fmt.Sprintf("interruptOp(fuseid=0x%08x)", typed.FuseID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
v := reflect.ValueOf(op).Elem()
|
v := reflect.ValueOf(op).Elem()
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
|
|
||||||
|
|
4
ops.go
4
ops.go
|
@ -40,9 +40,11 @@ type initOp struct {
|
||||||
// In
|
// In
|
||||||
Kernel fusekernel.Protocol
|
Kernel fusekernel.Protocol
|
||||||
|
|
||||||
|
// In/out
|
||||||
|
Flags fusekernel.InitFlags
|
||||||
|
|
||||||
// Out
|
// Out
|
||||||
Library fusekernel.Protocol
|
Library fusekernel.Protocol
|
||||||
MaxReadahead uint32
|
MaxReadahead uint32
|
||||||
Flags fusekernel.InitFlags
|
|
||||||
MaxWrite uint32
|
MaxWrite uint32
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -72,6 +73,18 @@ func (t *InterruptFSTest) StatFoo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *InterruptFSTest) InterruptedDuringRead() {
|
func (t *InterruptFSTest) InterruptedDuringRead() {
|
||||||
|
// On Linux, since we have async reads enabled, the kernel sends the read and
|
||||||
|
// the flush ops in parallel. When the process receives SIGINT, the interrupt
|
||||||
|
// is delivered only for the flush, probably because that's what the process
|
||||||
|
// appears to be blocking on. So this test doesn't work.
|
||||||
|
//
|
||||||
|
// Note that this means that cancellation is not delivered for reads on
|
||||||
|
// Linux. This is unfortunate, but probably worth it due to the significant
|
||||||
|
// increase in performance.
|
||||||
|
if runtime.GOOS == "linux" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
t.fs.EnableReadBlocking()
|
t.fs.EnableReadBlocking()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue