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