@@ -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 ) {
@@ -1572,14 +1571,14 @@ mod tests {
15721571
15731572 // Run scenario that doesn't trigger FullSq BlockError: Add sq_size flush requests.
15741573 add_flush_requests_batch ( & mut block, & vq, IO_URING_NUM_ENTRIES ) ;
1575- simulate_queue_event ( & mut block, Some ( false ) ) ;
1574+ simulate_queue_event ( & mut block, Some ( true ) ) ;
15761575 assert ! ( !block. is_io_engine_throttled) ;
15771576 simulate_async_completion_event ( & mut block, true ) ;
15781577 check_flush_requests_batch ( IO_URING_NUM_ENTRIES , & vq) ;
15791578
15801579 // Run scenario that triggers FullSqError : Add sq_size + 10 flush requests.
15811580 add_flush_requests_batch ( & mut block, & vq, IO_URING_NUM_ENTRIES + 10 ) ;
1582- simulate_queue_event ( & mut block, Some ( false ) ) ;
1581+ simulate_queue_event ( & mut block, Some ( true ) ) ;
15831582 assert ! ( block. is_io_engine_throttled) ;
15841583 // When the async_completion_event is triggered:
15851584 // 1. sq_size requests should be processed processed.
@@ -1606,16 +1605,16 @@ mod tests {
16061605 // Run scenario that triggers FullCqError. Push 2 * IO_URING_NUM_ENTRIES and wait for
16071606 // completion. Then try to push another entry.
16081607 add_flush_requests_batch ( & mut block, & vq, IO_URING_NUM_ENTRIES ) ;
1609- simulate_queue_event ( & mut block, Some ( false ) ) ;
1608+ simulate_queue_event ( & mut block, Some ( true ) ) ;
16101609 assert ! ( !block. is_io_engine_throttled) ;
16111610 thread:: sleep ( Duration :: from_millis ( 150 ) ) ;
16121611 add_flush_requests_batch ( & mut block, & vq, IO_URING_NUM_ENTRIES ) ;
1613- simulate_queue_event ( & mut block, Some ( false ) ) ;
1612+ simulate_queue_event ( & mut block, Some ( true ) ) ;
16141613 assert ! ( !block. is_io_engine_throttled) ;
16151614 thread:: sleep ( Duration :: from_millis ( 150 ) ) ;
16161615
16171616 add_flush_requests_batch ( & mut block, & vq, 1 ) ;
1618- simulate_queue_event ( & mut block, Some ( false ) ) ;
1617+ simulate_queue_event ( & mut block, Some ( true ) ) ;
16191618 assert ! ( block. is_io_engine_throttled) ;
16201619 simulate_async_completion_event ( & mut block, true ) ;
16211620 assert ! ( !block. is_io_engine_throttled) ;
@@ -1671,13 +1670,15 @@ mod tests {
16711670 vq. dtable [ 1 ] . len . set ( 512 ) ;
16721671 mem. write_obj :: < u64 > ( 123_456_789 , data_addr) . unwrap ( ) ;
16731672
1674- // Following write procedure should fail because of bandwidth rate limiting.
1673+ // This will fail because of bandwidth rate limiting.
1674+ // The irq is still triggered because notification suppression
1675+ // is not enabled.
16751676 {
16761677 // Trigger the attempt to write.
16771678 check_metric_after_block ! (
16781679 & block. metrics. rate_limiter_throttled_events,
16791680 1 ,
1680- simulate_queue_event( & mut block, Some ( false ) )
1681+ simulate_queue_event( & mut block, Some ( true ) )
16811682 ) ;
16821683
16831684 // Assert that limiter is blocked.
@@ -1739,13 +1740,15 @@ mod tests {
17391740 vq. dtable [ 1 ] . len . set ( 512 ) ;
17401741 mem. write_obj :: < u64 > ( 123_456_789 , data_addr) . unwrap ( ) ;
17411742
1742- // Following write procedure should fail because of ops rate limiting.
1743+ // This will fail because of ops rate limiting.
1744+ // The irq is still triggered because notification suppression
1745+ // is not enabled.
17431746 {
17441747 // Trigger the attempt to write.
17451748 check_metric_after_block ! (
17461749 & block. metrics. rate_limiter_throttled_events,
17471750 1 ,
1748- simulate_queue_event( & mut block, Some ( false ) )
1751+ simulate_queue_event( & mut block, Some ( true ) )
17491752 ) ;
17501753
17511754 // Assert that limiter is blocked.
@@ -1754,7 +1757,8 @@ mod tests {
17541757 assert_eq ! ( vq. used. idx. get( ) , 0 ) ;
17551758 }
17561759
1757- // Do a second write that still fails but this time on the fast path.
1760+ // Do a second write that still fails but this time on the fast path
1761+ // which does not call `process_queue`, so no irq notifications.
17581762 {
17591763 // Trigger the attempt to write.
17601764 check_metric_after_block ! (
0 commit comments