From f019faed748217ef4d3d2363ba0c59557422b0d3 Mon Sep 17 00:00:00 2001 From: Kislay Kishore Date: Fri, 27 Feb 2026 20:50:48 +0530 Subject: [PATCH] fix: dynamically calculate max_pages based on system page size Hardcoding FUSE `max_pages` to 256 assumes a 4KiB page size yielding a 1MiB max request. On ARM64 architectures (e.g., Grace CPU) with 64KiB pages, 256 pages allows the kernel to send read-ahead requests up to 16MiB. This overflows the daemon's fixed 1MiB buffer pool, resulting in 0-byte reads, premature EOFs, and fatal SIGBUS errors in mmap-heavy applications like TensorRT. This fix dynamically calculates the limit during the FUSE INIT phase: max_pages = (1 MiB buffer capacity) / os.Getpagesize() On 64KiB systems, this safely caps `max_pages` at 16. The kernel will now strictly split large read-ahead demands into 1MiB chunks, preventing buffer overflows and crashes. --- connection.go | 8 +++++++- internal/buffer/in_message.go | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/connection.go b/connection.go index ebb86b73..ba65e67b 100644 --- a/connection.go +++ b/connection.go @@ -185,7 +185,13 @@ func (c *Connection) Init() error { // kernel 4.20 increases the max from 32 -> 256 initOp.Flags |= fusekernel.InitMaxPages - initOp.MaxPages = 256 + + // MaxPages is the maximum size, in hardware pages, of the FUSE message + // 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. if !c.cfg.DisableWritebackCaching { diff --git a/internal/buffer/in_message.go b/internal/buffer/in_message.go index b583af50..a9728833 100644 --- a/internal/buffer/in_message.go +++ b/internal/buffer/in_message.go @@ -37,6 +37,12 @@ func init() { bufSize = pageSize + MaxWriteSize } +// Return the hardware page size. Note that this is not always 4KiB! Notably +// it's larger (e.g. 64KiB) on some ARM64 architectures. +func GetPageSize() int { + return pageSize +} + // An incoming message from the kernel, including leading fusekernel.InHeader // struct. Provides storage for messages and convenient access to their // contents.