@@ -125,7 +125,8 @@ pub struct VirtqProducer<M, N, P> {
125125 inner : RingProducer < M > ,
126126 notifier : N ,
127127 pool : P ,
128- inflight : Vec < Option < Inflight > > ,
128+ next_token : u32 ,
129+ inflight : Vec < Option < ( Token , Inflight ) > > ,
129130 pending : VecDeque < RecvCompletion > ,
130131}
131132
@@ -152,6 +153,7 @@ where
152153 pool,
153154 notifier,
154155 inflight,
156+ next_token : 0 ,
155157 pending : VecDeque :: new ( ) ,
156158 }
157159 }
@@ -218,13 +220,20 @@ where
218220 } ;
219221
220222 let id = used. id as usize ;
221- let inf = self
223+ let ( token , inf) = self
222224 . inflight
223225 . get_mut ( id)
224226 . ok_or ( VirtqError :: InvalidState ) ?
225227 . take ( )
226228 . ok_or ( VirtqError :: InvalidState ) ?;
227229
230+ // the token's descriptor ID must match the ring's
231+ debug_assert_eq ! (
232+ token. 1 , used. id,
233+ "ring returned desc_id={} but inflight slot {} has token with desc_id={}" ,
234+ used. id, id, token. 1 ,
235+ ) ;
236+
228237 let written = used. len as usize ;
229238
230239 // Free entry buffers (request data no longer needed)
@@ -250,10 +259,7 @@ where
250259 None => Bytes :: new ( ) ,
251260 } ;
252261
253- Ok ( Some ( RecvCompletion {
254- token : Token ( used. id ) ,
255- data,
256- } ) )
262+ Ok ( Some ( RecvCompletion { token, data } ) )
257263 }
258264
259265 /// Drain all available completions, calling the provided closure for each.
@@ -310,6 +316,9 @@ where
310316 let chain = inflight. try_into_chain ( written) ?;
311317 let id = self . inner . submit_available ( & chain) ?;
312318
319+ let token = Token ( self . next_token , id) ;
320+ self . next_token = self . next_token . wrapping_add ( 1 ) ;
321+
313322 let slot = self
314323 . inflight
315324 . get_mut ( id as usize )
@@ -319,7 +328,7 @@ where
319328 return Err ( VirtqError :: InvalidState ) ;
320329 }
321330
322- * slot = Some ( inflight) ;
331+ * slot = Some ( ( token , inflight) ) ;
323332
324333 let should_notify = self . inner . should_notify_since ( cursor_before) ?;
325334
@@ -336,7 +345,7 @@ where
336345 } ) ;
337346 }
338347
339- Ok ( Token ( id ) )
348+ Ok ( token )
340349 }
341350
342351 /// Signal backpressure to the consumer.
@@ -474,12 +483,18 @@ where
474483 . slot_addr ( pos as usize )
475484 . ok_or ( VirtqError :: InvalidState ) ?;
476485
477- self . inflight [ id as usize ] = Some ( Inflight :: WriteOnly {
478- completion : Allocation {
479- addr,
480- len : slot_size,
486+ let token = Token ( self . next_token , id) ;
487+ self . next_token = self . next_token . wrapping_add ( 1 ) ;
488+
489+ self . inflight [ id as usize ] = Some ( (
490+ token,
491+ Inflight :: WriteOnly {
492+ completion : Allocation {
493+ addr,
494+ len : slot_size,
495+ } ,
481496 } ,
482- } ) ;
497+ ) ) ;
483498
484499 ids. push ( id) ;
485500 }
@@ -869,7 +884,7 @@ mod tests {
869884 // Ring should still be fully usable
870885 let se = producer. chain ( ) . entry ( 64 ) . completion ( 128 ) . build ( ) . unwrap ( ) ;
871886 let tok = producer. submit ( se) . unwrap ( ) ;
872- assert ! ( tok. 0 < 16 ) ;
887+ assert ! ( tok. 1 < 16 ) ;
873888 }
874889
875890 #[ test]
@@ -885,7 +900,7 @@ mod tests {
885900 // Ring should still be fully usable
886901 let se = producer. chain ( ) . entry ( 64 ) . completion ( 128 ) . build ( ) . unwrap ( ) ;
887902 let tok = producer. submit ( se) . unwrap ( ) ;
888- assert ! ( tok. 0 < 16 ) ;
903+ assert ! ( tok. 1 < 16 ) ;
889904 }
890905
891906 #[ test]
0 commit comments