Skip to content

virtiofs: advertise multiple request queues for parallel I/O#3442

Open
benhillis wants to merge 2 commits intomicrosoft:mainfrom
benhillis:virtiofs-multi-queue
Open

virtiofs: advertise multiple request queues for parallel I/O#3442
benhillis wants to merge 2 commits intomicrosoft:mainfrom
benhillis:virtiofs-multi-queue

Conversation

@benhillis
Copy link
Copy Markdown
Member

Advertise num_request_queues based on available host CPUs (capped at 16)
instead of hardcoding 1. The Linux guest kernel (≥6.11) distributes
FUSE requests across queues on a per-CPU basis, eliminating single-queue
lock contention for parallel workloads.

Each queue is serviced by an independent worker task, so requests on
different queues are processed concurrently without contention. Older
kernels that lack multi-queue support (<6.11) will ignore the extra
queues and continue using queue 0 — no behavioral change for them.

The queue count is configurable via the new num_request_queues parameter
on VirtioFsDevice::new(). Passing None uses the host CPU count heuristic.

Changes

  • virtio.rs: Add MAX_REQUEST_QUEUES constant, compute queue count from available_parallelism(), update max_queues to num_request_queues + 1
  • resolver.rs: Pass None (use default heuristic)
  • integration_tests.rs: Pass Some(1) for deterministic test behavior

Advertise num_request_queues based on available host CPUs (capped at 16)
instead of hardcoding 1. The Linux guest kernel (>=6.11) distributes
FUSE requests across queues on a per-CPU basis, eliminating single-queue
lock contention for parallel workloads.

Each queue is serviced by an independent worker task, so requests on
different queues are processed concurrently without contention. Older
kernels that lack multi-queue support (< 6.11) will ignore the extra
queues and continue using queue 0 — no behavioral change for them.

The queue count is configurable via the new num_request_queues parameter
on VirtioFsDevice::new(). Passing None uses the host CPU count heuristic.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 8, 2026 16:56
@benhillis benhillis requested a review from a team as a code owner May 8, 2026 16:56
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the virtio-fs device to advertise multiple request queues (instead of always 1), using a host-CPU-based heuristic capped at 16. This enables parallel FUSE I/O in newer Linux guests that support virtio-fs multi-queue.

Changes:

  • Add MAX_REQUEST_QUEUES (16) and compute a default num_request_queues from std::thread::available_parallelism() when not explicitly provided.
  • Update virtio-fs device traits to advertise max_queues = num_request_queues + 1.
  • Thread the new num_request_queues: Option<u32> parameter through the resolver (default heuristic) and integration tests (force Some(1) for determinism).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
vm/devices/virtio/virtiofs/src/virtio.rs Adds configurable/default request-queue count and advertises the updated total queue count.
vm/devices/virtio/virtiofs/src/resolver.rs Uses the new API parameter, defaulting to the heuristic (None).
vm/devices/virtio/virtiofs/src/integration_tests.rs Pins queue count to Some(1) to keep tests deterministic.

Comment thread vm/devices/virtio/virtiofs/src/virtio.rs Outdated
Comment thread vm/devices/virtio/virtiofs/src/virtio.rs Outdated
@benhillis
Copy link
Copy Markdown
Member Author

I'm currently benchmarking this with the current WSL kernel and the upcoming 6.18 kernel. Will provide numbers once I have them.

Move .clamp(1, MAX_REQUEST_QUEUES) outside the unwrap_or_else closure
so that explicitly-provided values (e.g. Some(0) or Some(100)) are also
bounded. Previously only the heuristic path was clamped.

Add three tests verifying the clamping behavior for None, Some(0), and
Some(>MAX).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

Comment on lines +545 to +550
// num_request_queues should be at least 1 and at most MAX (16).
// max_queues = num_request_queues + 1 (hiprio queue).
assert!(traits.max_queues >= 2, "at least 1 request queue + hiprio");
assert!(
traits.max_queues <= 17,
"at most 16 request queues + hiprio"
Comment on lines +574 to +575
// Some(100) should be clamped to MAX_REQUEST_QUEUES (16) → max_queues = 17
assert_eq!(traits.max_queues, 17);
Comment on lines 44 to 48
)?,
0,
None,
None,
),
Comment on lines +67 to +68
/// queues on a per-CPU basis. If `None`, defaults to the number of
/// available CPUs (capped at 16).
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 9, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants