diff --git a/connection.go b/connection.go index a970316..88b186e 100644 --- a/connection.go +++ b/connection.go @@ -485,8 +485,15 @@ func (c *Connection) Reply(ctx context.Context, opErr error) { outMsg := state.outMsg fuseID := inMsg.Header().Unique + suppressReuse := false + if wr, ok := op.(*fuseops.WriteFileOp); ok { + suppressReuse = wr.SuppressReuse + } + // Make sure we destroy the messages when we're done. - defer c.putInMessage(inMsg) + if !suppressReuse { + defer c.putInMessage(inMsg) + } defer c.putOutMessage(outMsg) // Clean up state for this op. diff --git a/fuseops/ops.go b/fuseops/ops.go index a150af5..470f256 100644 --- a/fuseops/ops.go +++ b/fuseops/ops.go @@ -749,7 +749,18 @@ type WriteFileOp struct { // be written, except on error (http://goo.gl/KUpwwn). This appears to be // because it uses file mmapping machinery (http://goo.gl/SGxnaN) to write a // page at a time. - Data []byte + Data []byte + + // Set by the file system: "no reuse" flag. + // + // By default, the Data buffer is reused by the library, so the file system + // must copy the data if it wants to use it later. + // + // However, if the file system sets this flag to true, the library doesn't + // reuse this buffer, so the file system can safely store and use Data slice + // without copying memory. + SuppressReuse bool + OpContext OpContext } diff --git a/internal/buffer/in_message_linux.go b/internal/buffer/in_message_linux.go index 31c5e96..6273733 100644 --- a/internal/buffer/in_message_linux.go +++ b/internal/buffer/in_message_linux.go @@ -17,4 +17,4 @@ package buffer // The maximum fuse write request size that InMessage can acommodate. // // As of kernel 4.20 Linux accepts writes up to 256 pages or 1MiB -const MaxWriteSize = 1 << 20 +const MaxWriteSize = 1 << 17