@@ -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