Skip to content

Commit a4fc692

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 de2cb6a commit a4fc692

File tree

1 file changed

+16
-14
lines changed

1 file changed

+16
-14
lines changed

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

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -394,14 +394,21 @@ impl Queue {
394394
fn do_pop_unchecked<'b, M: GuestMemory>(
395395
&mut self,
396396
mem: &'b M,
397+
) -> Option<DescriptorChain<'b, M>> {
398+
self.get_desc_chain(self.next_avail.0, mem).inspect(|_| {
399+
self.next_avail += Wrapping(1);
400+
})
401+
}
402+
403+
/// Get descriptor chain from the avail ring at the specified index.
404+
pub fn get_desc_chain<'b, M: GuestMemory>(
405+
&self,
406+
avail_idx: u16,
407+
mem: &'b M,
397408
) -> Option<DescriptorChain<'b, M>> {
398409
// This fence ensures all subsequent reads see the updated driver writes.
399410
fence(Ordering::Acquire);
400411

401-
// We'll need to find the first available descriptor, that we haven't yet popped.
402-
// In a naive notation, that would be:
403-
// `descriptor_table[avail_ring[next_avail]]`.
404-
//
405412
// Avail ring has layout:
406413
// struct AvailRing {
407414
// flags: u16,
@@ -415,22 +422,17 @@ impl Queue {
415422
// index into `AvailRing` is `self.next_avail % self.actual_size()`.
416423
let desc_index_offset = std::mem::size_of::<u16>()
417424
+ std::mem::size_of::<u16>()
418-
+ std::mem::size_of::<u16>() * usize::from(self.next_avail.0 % self.actual_size());
425+
+ std::mem::size_of::<u16>() * usize::from(avail_idx % self.actual_size());
419426
let desc_index_address = self
420427
.avail_ring
421428
.unchecked_add(usize_to_u64(desc_index_offset));
422429

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

428-
DescriptorChain::checked_new(mem, self.desc_table, self.actual_size(), desc_index).map(
429-
|dc| {
430-
self.next_avail += Wrapping(1);
431-
dc
432-
},
433-
)
435+
DescriptorChain::checked_new(mem, self.desc_table, self.actual_size(), desc_index)
434436
}
435437

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

0 commit comments

Comments
 (0)