diff --git a/connection.go b/connection.go index ba65e67..960e52f 100644 --- a/connection.go +++ b/connection.go @@ -80,6 +80,8 @@ type Connection struct { // Freelists, serviced by freelists.go. inMessages freelist.Freelist // GUARDED_BY(mu) outMessages freelist.Freelist // GUARDED_BY(mu) + + inMessageSize int } // State that is maintained for each in-flight op. This is stuffed into the @@ -121,6 +123,12 @@ func newConnection( cancelFuncs: make(map[uint64]func()), } + maxPayload := max(buffer.MaxReadSize, buffer.MaxWriteSize) + if cfg.MaxMessageSize > 0 { + maxPayload = max(maxPayload, int(cfg.MaxMessageSize)) + } + c.inMessageSize = maxPayload + buffer.GetPageSize() + // Initialize. if err := c.Init(); err != nil { c.close() @@ -172,7 +180,9 @@ func (c *Connection) Init() error { // Respond to the init op. initOp.Library = c.protocol initOp.MaxReadahead = maxReadahead - initOp.MaxWrite = buffer.MaxWriteSize + + maxPayload := c.inMessageSize - buffer.GetPageSize() + initOp.MaxWrite = uint32(maxPayload) initOp.Flags = 0 @@ -190,7 +200,6 @@ func (c *Connection) Init() error { // payload. It applies to both requests and replies, and does not include // the extra 1 page for the FUSE header and the "args" struct. We set it to // the max of our message in/out payload sizes. - maxPayload := max(buffer.MaxReadSize, buffer.MaxWriteSize) initOp.MaxPages = uint16(maxPayload / buffer.GetPageSize()) // Enable writeback caching if the user hasn't asked us not to. diff --git a/freelists.go b/freelists.go index 8489e1f..9961a55 100644 --- a/freelists.go +++ b/freelists.go @@ -31,7 +31,7 @@ func (c *Connection) getInMessage() *buffer.InMessage { c.mu.Unlock() if x == nil { - x = buffer.NewInMessage() + x = buffer.NewInMessage(c.inMessageSize) } return x diff --git a/internal/buffer/in_message.go b/internal/buffer/in_message.go index a972883..5874004 100644 --- a/internal/buffer/in_message.go +++ b/internal/buffer/in_message.go @@ -28,13 +28,8 @@ import ( // this. var pageSize int -// We size the buffer to have enough room for a fuse request plus data -// associated with a write request. -var bufSize int - func init() { pageSize = syscall.Getpagesize() - bufSize = pageSize + MaxWriteSize } // Return the hardware page size. Note that this is not always 4KiB! Notably @@ -53,9 +48,9 @@ type InMessage struct { } // NewInMessage creates a new InMessage with its storage initialized. -func NewInMessage() *InMessage { +func NewInMessage(size int) *InMessage { return &InMessage{ - storage: make([]byte, bufSize), + storage: make([]byte, size), } } diff --git a/mount_config.go b/mount_config.go index f95895a..3336b0c 100644 --- a/mount_config.go +++ b/mount_config.go @@ -241,6 +241,10 @@ type MountConfig struct { // to always provide ReadFileOp.Dst. If the file system populates ReadFileOp.Data, // that data will be used for a vectored read, irrespective of this flag's value. UseVectoredRead bool + + // The maximum size of a FUSE message (in bytes) that the daemon is + // prepared to read or write. If not set, defaults to 1 MiB. + MaxMessageSize uint32 } type FUSEImpl uint8