Skip to content

Commit c8a77a8

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 cc7579f commit c8a77a8

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
@@ -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,
@@ -411,22 +418,17 @@ impl Queue {
411418
// index into `AvailRing` is `self.next_avail % self.actual_size()`.
412419
let desc_index_offset = std::mem::size_of::<u16>()
413420
+ std::mem::size_of::<u16>()
414-
+ std::mem::size_of::<u16>() * usize::from(self.next_avail.0 % self.actual_size());
421+
+ std::mem::size_of::<u16>() * usize::from(avail_idx % self.actual_size());
415422
let desc_index_address = self
416423
.avail_ring
417424
.unchecked_add(usize_to_u64(desc_index_offset));
418425

419-
// `self.is_valid()` already performed all the bound checks on the descriptor table
420-
// and virtq rings, so it's safe to unwrap guest memory reads and to use unchecked
421-
// offsets.
426+
// SAFETY:
427+
// `desc_index_address` param is bounded by size of the queue as `avail_idx` is
428+
// modded by `actual_size()`.
422429
let desc_index: u16 = mem.read_obj(desc_index_address).unwrap();
423430

424-
DescriptorChain::checked_new(mem, self.desc_table, self.actual_size(), desc_index).map(
425-
|dc| {
426-
self.next_avail += Wrapping(1);
427-
dc
428-
},
429-
)
431+
DescriptorChain::checked_new(mem, self.desc_table, self.actual_size(), desc_index)
430432
}
431433

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

0 commit comments

Comments
 (0)