virtio-queue: add DescriptorChainReader and Writer - #399
Conversation
|
Comes from the discussion at rust-vmm/vhost-device#944 (comment) |
|
Tests were generated by an agent as specified in the PR/commit body, but I have also tested locally with vhost-device-media (replacing the types in descriptor_chain.rs by the one added here) and confirmed it to work. |
|
I haven't used this new API in detail, but wouldn't it be possible to store owned descriptor chains somewhere and create the already existing borrowed reader/writers on demand whenever we need to use them? |
|
Or, the API could take a lifetime, like |
But
|
|
Thanks for the answers. Just a note:
A use std::ops::Deref;
use std::borrow::Cow;
fn take_static(s: &'static str) {
println!("s = {s}");
}
fn main() {
let a: Cow<'static, str> = Cow::Borrowed("a");
let b: Cow<'static, str> = Cow::Owned("b".to_string());
take_static(a.deref());
take_static(b.deref());
}So the analogous reader enum would be sth like: pub enum Reader<'a, B> {
Borrowed(Reader<'a, B>),
Owned(DescriptorChainReader<M>),
}But this is unrelated to this PR, so nevermind :) |
|
Oh. That's right. Thanks for the clarification and examples. Following your example we could do something like: pub enum Reader<'a, B = (), M = ()> {
Borrowed(BorrowedReader<'a, B>), // current Reader, renamed
Owned(DescriptorChainReader<M>),
}
pub type OwnedReader<M> = Reader<'static, (), M>;
// And analogous
pub type OwnedWriter<M> = Writer<'static, (), M>;Changing I can try to explore it further if you think it'll make for a better design in the long term. |
No need, I was just thinking out loud. Will review your PR separately. |
The existing Reader<'a, B> and Writer<'a, B> borrow guest memory with an external lifetime parameter, which prevents them from being used as concrete type parameters in structs that need to be stored across requests. Currently, vhost-device-media workarounds it by duplicating the I/O logic locally. Add DescriptorChainReader<M> and DescriptorChainWriter<M>, which own the guest memory accessor through the DescriptorChain<M> they consume rather than borrowing it from an external reference. Both implement std::io::Read and std::io::Write respectively, and expose bytes_read() and bytes_written() counters. Because they carry no lifetime parameter, they can be stored directly as fields or type parameters in device handler structs. Unlike the existing types, these are lazy: descriptors are traversed one at a time per read/write call rather than pre-fetched at construction. To enable this without requiring M: Clone on the reader/writer constructors (as happens with vhost-device-media implementation), add a memory() accessor to DescriptorChainRwIter, which gives access to the guest memory held inside the iterator's DescriptorChain without the caller needing to retain a separate handle. Used an agent for generating tests, docs, and reviews. Assisted-by: Claude <noreply@anthropic.com> Signed-off-by: Albert Esteve <aesteve@redhat.com>
We are still at |
|
If we can afford this breaking change maybe we could rename But I'm not sure we should put effort into the single |
Summary of the PR
The existing Reader<'a, B> and Writer<'a, B> borrow guest memory with an external lifetime parameter, which prevents them from being used as concrete type parameters in structs that need to be stored across requests. Currently, vhost-device-media workarounds it by duplicating the I/O logic locally.
Add DescriptorChainReader and DescriptorChainWriter, which own the guest memory accessor through the DescriptorChain they consume rather than borrowing it from an external reference. Both implement std::io::Read and std::io::Write respectively, and expose bytes_read() and bytes_written() counters. Because they carry no lifetime parameter, they can be stored directly as fields or type parameters in device handler structs.
Unlike the existing types, these are lazy: descriptors are traversed one at a time per read/write call rather than pre-fetched at construction.
To enable this without requiring M: Clone on the reader/writer constructors (as happens with vhost-device-media implementation), add a memory() accessor to DescriptorChainRwIter, which gives access to the guest memory held inside the iterator's DescriptorChain without the caller needing to retain a separate handle.
Used an agent for generating tests, docs, and reviews.
Requirements
Before submitting your PR, please make sure you addressed the following
requirements:
git commit -s), and the commit message has max 60 characters for thesummary and max 75 characters for each description line.
test.
Release" section of CHANGELOG.md (if no such section exists, please create one).
unsafecode is properly documented.