@@ -384,24 +384,6 @@ impl VirtioBlock {
384384 }
385385 }
386386
387- fn add_used_descriptor (
388- queue : & mut Queue ,
389- index : u16 ,
390- len : u32 ,
391- irq_trigger : & IrqTrigger ,
392- block_metrics : & BlockDeviceMetrics ,
393- ) {
394- queue. add_used ( index, len) . unwrap_or_else ( |err| {
395- error ! ( "Failed to add available descriptor head {}: {}" , index, err)
396- } ) ;
397-
398- if queue. prepare_kick ( ) {
399- irq_trigger. trigger_irq ( IrqType :: Vring ) . unwrap_or_else ( |_| {
400- block_metrics. event_fails . inc ( ) ;
401- } ) ;
402- }
403- }
404-
405387 /// Device specific function for peaking inside a queue and processing descriptors.
406388 pub fn process_queue ( & mut self , queue_index : usize ) -> Result < ( ) , InvalidAvailIdx > {
407389 // This is safe since we checked in the event handler that the device is activated.
@@ -443,17 +425,26 @@ impl VirtioBlock {
443425 break ;
444426 }
445427 ProcessingResult :: Executed ( finished) => {
446- Self :: add_used_descriptor (
447- queue,
448- head. index ,
449- finished. num_bytes_to_mem ,
450- & self . irq_trigger ,
451- & self . metrics ,
452- ) ;
428+ queue
429+ . add_used ( head. index , finished. num_bytes_to_mem )
430+ . unwrap_or_else ( |err| {
431+ error ! (
432+ "Failed to add available descriptor head {}: {}" ,
433+ head. index, err
434+ )
435+ } ) ;
453436 }
454437 }
455438 }
456439
440+ if queue. prepare_kick ( ) {
441+ self . irq_trigger
442+ . trigger_irq ( IrqType :: Vring )
443+ . unwrap_or_else ( |_| {
444+ self . metrics . event_fails . inc ( ) ;
445+ } ) ;
446+ }
447+
457448 if let FileEngine :: Async ( ref mut engine) = self . disk . file_engine {
458449 if let Err ( err) = engine. kick_submission_queue ( ) {
459450 error ! ( "BlockError submitting pending block requests: {:?}" , err) ;
@@ -495,17 +486,25 @@ impl VirtioBlock {
495486 ) ,
496487 } ;
497488 let finished = pending. finish ( mem, res, & self . metrics ) ;
498-
499- Self :: add_used_descriptor (
500- queue ,
501- finished . desc_idx ,
502- finished . num_bytes_to_mem ,
503- & self . irq_trigger ,
504- & self . metrics ,
505- ) ;
489+ queue
490+ . add_used ( finished . desc_idx , finished . num_bytes_to_mem )
491+ . unwrap_or_else ( |err| {
492+ error ! (
493+ "Failed to add available descriptor head {}: {}" ,
494+ finished . desc_idx , err
495+ )
496+ } ) ;
506497 }
507498 }
508499 }
500+
501+ if queue. prepare_kick ( ) {
502+ self . irq_trigger
503+ . trigger_irq ( IrqType :: Vring )
504+ . unwrap_or_else ( |_| {
505+ self . metrics . event_fails . inc ( ) ;
506+ } ) ;
507+ }
509508 }
510509
511510 pub fn process_async_completion_event ( & mut self ) {
@@ -1573,14 +1572,14 @@ mod tests {
15731572
15741573 // Run scenario that doesn't trigger FullSq BlockError: Add sq_size flush requests.
15751574 add_flush_requests_batch ( & mut block, & vq, IO_URING_NUM_ENTRIES ) ;
1576- simulate_queue_event ( & mut block, Some ( false ) ) ;
1575+ simulate_queue_event ( & mut block, Some ( true ) ) ;
15771576 assert ! ( !block. is_io_engine_throttled) ;
15781577 simulate_async_completion_event ( & mut block, true ) ;
15791578 check_flush_requests_batch ( IO_URING_NUM_ENTRIES , & vq) ;
15801579
15811580 // Run scenario that triggers FullSqError : Add sq_size + 10 flush requests.
15821581 add_flush_requests_batch ( & mut block, & vq, IO_URING_NUM_ENTRIES + 10 ) ;
1583- simulate_queue_event ( & mut block, Some ( false ) ) ;
1582+ simulate_queue_event ( & mut block, Some ( true ) ) ;
15841583 assert ! ( block. is_io_engine_throttled) ;
15851584 // When the async_completion_event is triggered:
15861585 // 1. sq_size requests should be processed processed.
@@ -1607,16 +1606,16 @@ mod tests {
16071606 // Run scenario that triggers FullCqError. Push 2 * IO_URING_NUM_ENTRIES and wait for
16081607 // completion. Then try to push another entry.
16091608 add_flush_requests_batch ( & mut block, & vq, IO_URING_NUM_ENTRIES ) ;
1610- simulate_queue_event ( & mut block, Some ( false ) ) ;
1609+ simulate_queue_event ( & mut block, Some ( true ) ) ;
16111610 assert ! ( !block. is_io_engine_throttled) ;
16121611 thread:: sleep ( Duration :: from_millis ( 150 ) ) ;
16131612 add_flush_requests_batch ( & mut block, & vq, IO_URING_NUM_ENTRIES ) ;
1614- simulate_queue_event ( & mut block, Some ( false ) ) ;
1613+ simulate_queue_event ( & mut block, Some ( true ) ) ;
16151614 assert ! ( !block. is_io_engine_throttled) ;
16161615 thread:: sleep ( Duration :: from_millis ( 150 ) ) ;
16171616
16181617 add_flush_requests_batch ( & mut block, & vq, 1 ) ;
1619- simulate_queue_event ( & mut block, Some ( false ) ) ;
1618+ simulate_queue_event ( & mut block, Some ( true ) ) ;
16201619 assert ! ( block. is_io_engine_throttled) ;
16211620 simulate_async_completion_event ( & mut block, true ) ;
16221621 assert ! ( !block. is_io_engine_throttled) ;
@@ -1672,13 +1671,15 @@ mod tests {
16721671 vq. dtable [ 1 ] . len . set ( 512 ) ;
16731672 mem. write_obj :: < u64 > ( 123_456_789 , data_addr) . unwrap ( ) ;
16741673
1675- // Following write procedure should fail because of bandwidth rate limiting.
1674+ // This will fail because of bandwidth rate limiting.
1675+ // The irq is still triggered because notification suppression
1676+ // is not enabled.
16761677 {
16771678 // Trigger the attempt to write.
16781679 check_metric_after_block ! (
16791680 & block. metrics. rate_limiter_throttled_events,
16801681 1 ,
1681- simulate_queue_event( & mut block, Some ( false ) )
1682+ simulate_queue_event( & mut block, Some ( true ) )
16821683 ) ;
16831684
16841685 // Assert that limiter is blocked.
@@ -1740,13 +1741,15 @@ mod tests {
17401741 vq. dtable [ 1 ] . len . set ( 512 ) ;
17411742 mem. write_obj :: < u64 > ( 123_456_789 , data_addr) . unwrap ( ) ;
17421743
1743- // Following write procedure should fail because of ops rate limiting.
1744+ // This will fail because of ops rate limiting.
1745+ // The irq is still triggered because notification suppression
1746+ // is not enabled.
17441747 {
17451748 // Trigger the attempt to write.
17461749 check_metric_after_block ! (
17471750 & block. metrics. rate_limiter_throttled_events,
17481751 1 ,
1749- simulate_queue_event( & mut block, Some ( false ) )
1752+ simulate_queue_event( & mut block, Some ( true ) )
17501753 ) ;
17511754
17521755 // Assert that limiter is blocked.
@@ -1755,7 +1758,8 @@ mod tests {
17551758 assert_eq ! ( vq. used. idx. get( ) , 0 ) ;
17561759 }
17571760
1758- // Do a second write that still fails but this time on the fast path.
1761+ // Do a second write that still fails but this time on the fast path
1762+ // which does not call `process_queue`, so no irq notifications.
17591763 {
17601764 // Trigger the attempt to write.
17611765 check_metric_after_block ! (
0 commit comments