@@ -197,6 +197,14 @@ impl<M: GuestAddressSpace, S: QueueStateT> Queue<M, S> {
197197 self . state . avail_idx ( self . mem . memory ( ) . deref ( ) , order)
198198 }
199199
200+ /// Reads the `idx` field from the used ring.
201+ ///
202+ /// # Arguments
203+ /// * `order` - the memory ordering used to access the `idx` field from memory.
204+ pub fn used_idx ( & self , order : Ordering ) -> Result < Wrapping < u16 > , Error > {
205+ self . state . used_idx ( self . mem . memory ( ) . deref ( ) , order)
206+ }
207+
200208 /// Put a used descriptor head into the used ring.
201209 ///
202210 /// # Arguments
@@ -236,13 +244,26 @@ impl<M: GuestAddressSpace, S: QueueStateT> Queue<M, S> {
236244 self . state . next_avail ( )
237245 }
238246
247+ /// Returns the index for the next descriptor in the used ring.
248+ pub fn next_used ( & self ) -> u16 {
249+ self . state . next_used ( )
250+ }
251+
239252 /// Set the index of the next entry in the available ring.
240253 ///
241254 /// # Arguments
242255 /// * `next_avail` - the index of the next available ring entry.
243256 pub fn set_next_avail ( & mut self , next_avail : u16 ) {
244257 self . state . set_next_avail ( next_avail) ;
245258 }
259+
260+ /// Sets the index for the next descriptor in the used ring.
261+ ///
262+ /// # Arguments
263+ /// * `next_used` - the index of the next used ring entry.
264+ pub fn set_next_used ( & mut self , next_used : u16 ) {
265+ self . state . set_next_used ( next_used) ;
266+ }
246267}
247268
248269impl < M : GuestAddressSpace > Queue < M , QueueState > {
@@ -348,6 +369,7 @@ mod tests {
348369 let vq = MockSplitQueue :: new ( m, 16 ) ;
349370 let mut q = vq. create_queue ( m) ;
350371
372+ assert_eq ! ( q. used_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 0 ) ) ;
351373 assert_eq ! ( u16 :: from_le( vq. used( ) . idx( ) . load( ) ) , 0 ) ;
352374
353375 // index too large
@@ -357,6 +379,7 @@ mod tests {
357379 // should be ok
358380 q. add_used ( 1 , 0x1000 ) . unwrap ( ) ;
359381 assert_eq ! ( q. state. next_used, Wrapping ( 1 ) ) ;
382+ assert_eq ! ( q. used_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 1 ) ) ;
360383 assert_eq ! ( u16 :: from_le( vq. used( ) . idx( ) . load( ) ) , 1 ) ;
361384
362385 let x = vq. used ( ) . ring ( ) . ref_at ( 0 ) . load ( ) ;
@@ -377,7 +400,7 @@ mod tests {
377400 // Same for `event_idx_enabled`, `next_avail` `next_used` and `signalled_used`.
378401 q. set_event_idx ( true ) ;
379402 q. set_next_avail ( 2 ) ;
380- q. add_used ( 1 , 200 ) . unwrap ( ) ;
403+ q. set_next_used ( 4 ) ;
381404 q. state . signalled_used = Some ( Wrapping ( 15 ) ) ;
382405 assert_eq ! ( q. state. size, 8 ) ;
383406 // `create_queue` also marks the queue as ready.
@@ -533,10 +556,14 @@ mod tests {
533556 i += 1 ;
534557 q. disable_notification ( ) . unwrap ( ) ;
535558
536- while let Some ( _chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
559+ while let Some ( chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
537560 // Here the device would consume entries from the available ring, add an entry in
538561 // the used ring and optionally notify the driver. For the purpose of this test, we
539562 // don't need to do anything with the chain, only consume it.
563+ let head_index = chain. head_index ( ) ;
564+ let mut desc_len = 0 ;
565+ chain. for_each ( |d| desc_len += d. len ( ) ) ;
566+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
540567 }
541568 if !q. enable_notification ( ) . unwrap ( ) {
542569 break ;
@@ -547,6 +574,7 @@ mod tests {
547574 assert_eq ! ( i, 1 ) ;
548575 // The next chain that can be consumed should have index 2.
549576 assert_eq ! ( q. next_avail( ) , 2 ) ;
577+ assert_eq ! ( q. next_used( ) , 2 ) ;
550578 // Let the device know it can consume one more chain.
551579 vq. avail ( ) . idx ( ) . store ( u16:: to_le ( 3 ) ) ;
552580 i = 0 ;
@@ -555,8 +583,12 @@ mod tests {
555583 i += 1 ;
556584 q. disable_notification ( ) . unwrap ( ) ;
557585
558- while let Some ( _chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
586+ while let Some ( chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
559587 // In a real use case, we would do something with the chain here.
588+ let head_index = chain. head_index ( ) ;
589+ let mut desc_len = 0 ;
590+ chain. for_each ( |d| desc_len += d. len ( ) ) ;
591+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
560592 }
561593
562594 // For the simplicity of the test we are updating here the `idx` value of the available
@@ -571,21 +603,27 @@ mod tests {
571603 assert_eq ! ( i, 2 ) ;
572604 // The next chain that can be consumed should have index 4.
573605 assert_eq ! ( q. next_avail( ) , 4 ) ;
606+ assert_eq ! ( q. next_used( ) , 4 ) ;
574607
575608 // Set an `idx` that is bigger than the number of entries added in the ring.
576609 // This is an allowed scenario, but the indexes of the chain will have unexpected values.
577610 vq. avail ( ) . idx ( ) . store ( u16:: to_le ( 7 ) ) ;
578611 loop {
579612 q. disable_notification ( ) . unwrap ( ) ;
580613
581- while let Some ( _chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
614+ while let Some ( chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
582615 // In a real use case, we would do something with the chain here.
616+ let head_index = chain. head_index ( ) ;
617+ let mut desc_len = 0 ;
618+ chain. for_each ( |d| desc_len += d. len ( ) ) ;
619+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
583620 }
584621 if !q. enable_notification ( ) . unwrap ( ) {
585622 break ;
586623 }
587624 }
588625 assert_eq ! ( q. next_avail( ) , 7 ) ;
626+ assert_eq ! ( q. next_used( ) , 7 ) ;
589627 }
590628
591629 #[ test]
@@ -619,14 +657,19 @@ mod tests {
619657 vq. avail ( ) . idx ( ) . store ( u16:: to_le ( 3 ) ) ;
620658 // No descriptor chains are consumed at this point.
621659 assert_eq ! ( q. next_avail( ) , 0 ) ;
660+ assert_eq ! ( q. next_used( ) , 0 ) ;
622661
623662 loop {
624663 q. disable_notification ( ) . unwrap ( ) ;
625664
626- while let Some ( _chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
665+ while let Some ( chain ) = q. iter ( ) . unwrap ( ) . next ( ) {
627666 // Here the device would consume entries from the available ring, add an entry in
628667 // the used ring and optionally notify the driver. For the purpose of this test, we
629668 // don't need to do anything with the chain, only consume it.
669+ let head_index = chain. head_index ( ) ;
670+ let mut desc_len = 0 ;
671+ chain. for_each ( |d| desc_len += d. len ( ) ) ;
672+ q. add_used ( head_index, desc_len) . unwrap ( ) ;
630673 }
631674 if !q. enable_notification ( ) . unwrap ( ) {
632675 break ;
@@ -635,6 +678,8 @@ mod tests {
635678 // The next chain that can be consumed should have index 3.
636679 assert_eq ! ( q. next_avail( ) , 3 ) ;
637680 assert_eq ! ( q. avail_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 3 ) ) ;
681+ assert_eq ! ( q. next_used( ) , 3 ) ;
682+ assert_eq ! ( q. used_idx( Ordering :: Acquire ) . unwrap( ) , Wrapping ( 3 ) ) ;
638683 assert ! ( q. lock( ) . ready( ) ) ;
639684
640685 // Decrement `idx` which should be forbidden. We don't enforce this thing, but we should
0 commit comments