Skip to content

virtio-9p: migrate from VirtioQueueWorkerContext to direct VirtioQueue#2946

Open
jstarks wants to merge 2 commits intomicrosoft:mainfrom
jstarks:virtio-9p
Open

virtio-9p: migrate from VirtioQueueWorkerContext to direct VirtioQueue#2946
jstarks wants to merge 2 commits intomicrosoft:mainfrom
jstarks:virtio-9p

Conversation

@jstarks
Copy link
Member

@jstarks jstarks commented Mar 11, 2026

Same pattern as virtio-pmem, #2945.

Same pattern as virtio-pmem: Plan9Worker (T) holds device logic and is
created at Device::new(). Plan9Queue (S) holds the VirtioQueue, inserted
at enable() and removed at poll_disable(). No Option<TaskControl> needed.

- Remove Arc<Plan9FileSystem> -- Plan9Worker is sole owner
- Remove Arc<fs::File> field from device (dead after move to worker)
- Remove exit_event (StopTask handles cancellation)
- Remove async-trait and event-listener deps
- Add pal_async (PolledWait) and futures (StreamExt) deps
- Extract process_9p_request() as a free function
@jstarks jstarks requested review from a team as code owners March 11, 2026 18:05
Copilot AI review requested due to automatic review settings March 11, 2026 18:05
Copy link
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

Migrates the virtio-9p device’s queue handling from the VirtioQueueWorkerContext indirection to direct VirtioQueue ownership with a custom AsyncRun loop, matching the newer pattern used by other virtio devices.

Changes:

  • Replace VirtioQueueWorker/VirtioQueueWorkerContext usage with TaskControl<Plan9Worker, Plan9Queue> and an AsyncRun implementation.
  • Create and drive VirtioQueue directly via PolledWait + StreamExt::next().
  • Update crate dependencies to remove async-trait/event-listener and add futures/pal_async.

Reviewed changes

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

File Description
vm/devices/virtio/virtio_p9/src/lib.rs Refactors queue lifecycle to direct VirtioQueue + AsyncRun; moves request processing into a helper function.
vm/devices/virtio/virtio_p9/Cargo.toml Adjusts dependencies for the new queue/event and stream-based implementation.
Cargo.lock Updates locked dependency versions (including virtio_p9 deps list).

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +116 to +124
let queue_event = PolledWait::new(&self.driver, queue_resources.event).unwrap();
let queue = VirtioQueue::new(
resources.features,
queue_resources.params,
self.worker.task().mem.clone(),
queue_resources.notify,
queue_event,
)
.expect("failed to create virtio queue");
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

enable() currently uses both .next().expect("expected single queue") and panicking error handling (PolledWait::new(...).unwrap(), VirtioQueue::new(...).expect(...)). Even if these are “should never happen” invariants, other virtio devices (e.g. virtio-blk) tend to log and return instead of crashing the VMM. Consider handling missing/invalid queue resources and queue/event creation failures by logging the error and returning early.

Copilot uses AI. Check for mistakes.
Comment on lines +182 to +185
// Make a copy of the incoming message.
let mut message = vec![0; work.get_payload_length(false) as usize];
if let Err(e) = work.read(&worker.mem, &mut message) {
tracing::error!(
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

This allocates a Vec sized directly from work.get_payload_length(false) (guest-controlled descriptor lengths). A malicious/buggy guest can request very large buffers and trigger excessive memory allocation/OOM. Consider enforcing a reasonable maximum request size (or reworking to stream/parse in-place, similar to virtiofs’s payload reader) and completing the descriptor with an error response when the limit is exceeded.

Copilot uses AI. Check for mistakes.
Comment on lines +192 to +194
// Allocate a temporary buffer for the response.
let mut response = vec![9; work.get_payload_length(true) as usize];
if let Ok(size) = worker.fs.process_message(&message, &mut response) {
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

This allocates a response buffer sized from work.get_payload_length(true) (guest-controlled writable descriptor lengths), which can also be huge and lead to OOM/abort. Please cap the maximum response size you’re willing to allocate (and/or write the reply in smaller chunks) before allocating.

Copilot uses AI. Check for mistakes.
@jstarks
Copy link
Member Author

jstarks commented Mar 12, 2026

Blocked on #2947

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