Skip to content

Commit 105f6ab

Browse files
committed
refactor(queue): move descriptor reading into separate method
Move descriptor reading into separate method. This will allow for descriptor preprocessing without actual poping of them. Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent 600164b commit 105f6ab

File tree

1 file changed

+19
-15
lines changed

1 file changed

+19
-15
lines changed

src/vmm/src/devices/virtio/queue.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -390,14 +390,21 @@ impl Queue {
390390
fn do_pop_unchecked<'b, M: GuestMemory>(
391391
&mut self,
392392
mem: &'b M,
393+
) -> Option<DescriptorChain<'b, M>> {
394+
self.get_desc_chain(self.next_avail.0, mem).inspect(|_| {
395+
self.next_avail += Wrapping(1);
396+
})
397+
}
398+
399+
/// Get descriptor chain from the avail ring at the specified index.
400+
pub fn get_desc_chain<'b, M: GuestMemory>(
401+
&self,
402+
avail_idx: u16,
403+
mem: &'b M,
393404
) -> Option<DescriptorChain<'b, M>> {
394405
// This fence ensures all subsequent reads see the updated driver writes.
395406
fence(Ordering::Acquire);
396407

397-
// We'll need to find the first available descriptor, that we haven't yet popped.
398-
// In a naive notation, that would be:
399-
// `descriptor_table[avail_ring[next_avail]]`.
400-
//
401408
// Avail ring has layout:
402409
// struct AvailRing {
403410
// flags: u16,
@@ -408,20 +415,17 @@ impl Queue {
408415
// We calculate offset into `ring` field.
409416
let desc_index_offset = std::mem::size_of::<u16>()
410417
+ std::mem::size_of::<u16>()
411-
+ std::mem::size_of::<u16>() * usize::from(self.next_avail.0 % self.actual_size());
412-
let desc_index_address = self.avail_ring.unchecked_add(usize_to_u64(desc_index_offset));
418+
+ std::mem::size_of::<u16>() * usize::from(avail_idx % self.actual_size());
419+
let desc_index_address = self
420+
.avail_ring
421+
.unchecked_add(usize_to_u64(desc_index_offset));
413422

414-
// `self.is_valid()` already performed all the bound checks on the descriptor table
415-
// and virtq rings, so it's safe to unwrap guest memory reads and to use unchecked
416-
// offsets.
423+
// SAFETY:
424+
// `desc_index_address` param is bounded by size of the queue as `avail_idx` is
425+
// modded by `actual_size()`.
417426
let desc_index: u16 = mem.read_obj(desc_index_address).unwrap();
418427

419-
DescriptorChain::checked_new(mem, self.desc_table, self.actual_size(), desc_index).map(
420-
|dc| {
421-
self.next_avail += Wrapping(1);
422-
dc
423-
},
424-
)
428+
DescriptorChain::checked_new(mem, self.desc_table, self.actual_size(), desc_index)
425429
}
426430

427431
/// Undo the effects of the last `self.pop()` call.

0 commit comments

Comments
 (0)