fuse: virtio_fs: clamp max_pages_limit by the transport DMA mapping size#261
Draft
benhillis wants to merge 1 commit into
Draft
fuse: virtio_fs: clamp max_pages_limit by the transport DMA mapping size#261benhillis wants to merge 1 commit into
benhillis wants to merge 1 commit into
Conversation
virtio-fs negotiates max_pages (and therefore max_write) without regard for the maximum size of a single DMA mapping the transport can perform. When the device sits behind a bouncing DMA layer -- e.g. swiotlb=force, which WSL enables whenever a virtio-fs device is present -- the effective per-mapping limit is IO_TLB_SEGSIZE * IO_TLB_SIZE = 256 KiB. Combined with the FUSE default of 256 pages (1 MiB max_write), the guest builds read/readdir/write requests whose buffers cannot be DMA-mapped, which fails with -EIO and wedges the request virtqueue. virtio-blk already avoids this class of bug by clamping its transfer size with virtio_max_dma_size(). Do the same here: lower the connection's max_pages_limit to the transport's per-mapping DMA limit, right next to the existing virtqueue-size clamp. process_init_reply() then caps the negotiated max_pages (and transitively max_write) to a value the guest can always map. When no DMA limit applies, virtio_max_dma_size() returns SIZE_MAX and the clamp is a no-op. Signed-off-by: Ben Hillis <benhill@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
asherkariv
approved these changes
Jun 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
virtio-fs negotiates
max_pages(and thereforemax_write) purely from the FUSE_INIT reply, without accounting for the largest single DMA mapping the transport can perform. When the device sits behind a bouncing DMA layer — e.g.swiotlb=force, which WSL enables whenever a virtio-fs device is present — the effective per-mapping limit isIO_TLB_SEGSIZE * IO_TLB_SIZE= 256 KiB. Combined with the FUSE default of 256 pages (1 MiBmax_write), the guest builds read/readdir/write requests whose buffers cannot be DMA-mapped, failing with-EIOand wedging the request virtqueue.virtio-blkalready avoids this whole class of bug by clamping its transfer size withvirtio_max_dma_size()(seedrivers/block/virtio_blk.c, which boundsmax_segment_sizethe same way). This change does the same for virtio-fs: it lowers the connection'smax_pages_limitto the transport's per-mapping DMA limit, right next to the existing virtqueue-size clamp invirtio_fs_get_tree().process_init_reply()then caps the negotiatedmax_pages(and transitivelymax_write) to a value the guest can always map. When no DMA limit applies,virtio_max_dma_size()returnsSIZE_MAXand the clamp is a no-op — zero change for non-bounce-buffered guests.The change
Under
swiotlb=forcethis dropsmax_pages_limitto 64 → negotiatedmax_writeof 256 KiB, which the guest can always bounce.Testing
Built
linux-msft-wsl-6.18.y+ this patch withMicrosoft/config-wsl(CONFIG_VIRTIO_FS=y); boots as6.18.33.1-microsoft-standard-WSL2+.Validated against a virtio-fs server offering the default 1 MiB
max_write, withswiotlb=forceactive. The only variable between runs is the guest kernel:DrvFsTests::WSL2VirtioFsGetDents-EIO, wedged request virtqueueWith the clamp, the negotiated
max_pagesdrops to 64 (256 KiBmax_write), so readdir/read/write buffers always fit the swiotlb per-mapping limit.