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