@@ -382,10 +382,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
382382
383383static bool is_md_suspended (struct mddev * mddev )
384384{
385- if (mddev -> suspended )
386- return true;
387- else
388- return false;
385+ return percpu_ref_is_dying (& mddev -> active_io );
389386}
390387/* Rather than calling directly into the personality make_request function,
391388 * IO requests come here first so that we can check if the device is
@@ -412,12 +409,10 @@ static bool is_suspended(struct mddev *mddev, struct bio *bio)
412409void md_handle_request (struct mddev * mddev , struct bio * bio )
413410{
414411check_suspended :
415- rcu_read_lock ();
416412 if (is_suspended (mddev , bio )) {
417413 DEFINE_WAIT (__wait );
418414 /* Bail out if REQ_NOWAIT is set for the bio */
419415 if (bio -> bi_opf & REQ_NOWAIT ) {
420- rcu_read_unlock ();
421416 bio_wouldblock_error (bio );
422417 return ;
423418 }
@@ -426,23 +421,19 @@ void md_handle_request(struct mddev *mddev, struct bio *bio)
426421 TASK_UNINTERRUPTIBLE );
427422 if (!is_suspended (mddev , bio ))
428423 break ;
429- rcu_read_unlock ();
430424 schedule ();
431- rcu_read_lock ();
432425 }
433426 finish_wait (& mddev -> sb_wait , & __wait );
434427 }
435- atomic_inc ( & mddev -> active_io );
436- rcu_read_unlock () ;
428+ if (! percpu_ref_tryget_live ( & mddev -> active_io ))
429+ goto check_suspended ;
437430
438431 if (!mddev -> pers -> make_request (mddev , bio )) {
439- atomic_dec (& mddev -> active_io );
440- wake_up (& mddev -> sb_wait );
432+ percpu_ref_put (& mddev -> active_io );
441433 goto check_suspended ;
442434 }
443435
444- if (atomic_dec_and_test (& mddev -> active_io ) && is_md_suspended (mddev ))
445- wake_up (& mddev -> sb_wait );
436+ percpu_ref_put (& mddev -> active_io );
446437}
447438EXPORT_SYMBOL (md_handle_request );
448439
@@ -490,11 +481,10 @@ void mddev_suspend(struct mddev *mddev)
490481 lockdep_assert_held (& mddev -> reconfig_mutex );
491482 if (mddev -> suspended ++ )
492483 return ;
493- synchronize_rcu ();
494484 wake_up (& mddev -> sb_wait );
495485 set_bit (MD_ALLOW_SB_UPDATE , & mddev -> flags );
496- smp_mb__after_atomic ( );
497- wait_event (mddev -> sb_wait , atomic_read (& mddev -> active_io ) == 0 );
486+ percpu_ref_kill ( & mddev -> active_io );
487+ wait_event (mddev -> sb_wait , percpu_ref_is_zero (& mddev -> active_io ));
498488 mddev -> pers -> quiesce (mddev , 1 );
499489 clear_bit_unlock (MD_ALLOW_SB_UPDATE , & mddev -> flags );
500490 wait_event (mddev -> sb_wait , !test_bit (MD_UPDATING_SB , & mddev -> flags ));
@@ -512,6 +502,7 @@ void mddev_resume(struct mddev *mddev)
512502 lockdep_assert_held (& mddev -> reconfig_mutex );
513503 if (-- mddev -> suspended )
514504 return ;
505+ percpu_ref_resurrect (& mddev -> active_io );
515506 wake_up (& mddev -> sb_wait );
516507 mddev -> pers -> quiesce (mddev , 0 );
517508
@@ -690,7 +681,6 @@ void mddev_init(struct mddev *mddev)
690681 timer_setup (& mddev -> safemode_timer , md_safemode_timeout , 0 );
691682 atomic_set (& mddev -> active , 1 );
692683 atomic_set (& mddev -> openers , 0 );
693- atomic_set (& mddev -> active_io , 0 );
694684 spin_lock_init (& mddev -> lock );
695685 atomic_set (& mddev -> flush_pending , 0 );
696686 init_waitqueue_head (& mddev -> sb_wait );
@@ -5767,6 +5757,12 @@ static void md_safemode_timeout(struct timer_list *t)
57675757}
57685758
57695759static int start_dirty_degraded ;
5760+ static void active_io_release (struct percpu_ref * ref )
5761+ {
5762+ struct mddev * mddev = container_of (ref , struct mddev , active_io );
5763+
5764+ wake_up (& mddev -> sb_wait );
5765+ }
57705766
57715767int md_run (struct mddev * mddev )
57725768{
@@ -5847,10 +5843,15 @@ int md_run(struct mddev *mddev)
58475843 nowait = nowait && bdev_nowait (rdev -> bdev );
58485844 }
58495845
5846+ err = percpu_ref_init (& mddev -> active_io , active_io_release ,
5847+ PERCPU_REF_ALLOW_REINIT , GFP_KERNEL );
5848+ if (err )
5849+ return err ;
5850+
58505851 if (!bioset_initialized (& mddev -> bio_set )) {
58515852 err = bioset_init (& mddev -> bio_set , BIO_POOL_SIZE , 0 , BIOSET_NEED_BVECS );
58525853 if (err )
5853- return err ;
5854+ goto exit_active_io ;
58545855 }
58555856 if (!bioset_initialized (& mddev -> sync_set )) {
58565857 err = bioset_init (& mddev -> sync_set , BIO_POOL_SIZE , 0 , BIOSET_NEED_BVECS );
@@ -6038,6 +6039,8 @@ int md_run(struct mddev *mddev)
60386039 bioset_exit (& mddev -> sync_set );
60396040exit_bio_set :
60406041 bioset_exit (& mddev -> bio_set );
6042+ exit_active_io :
6043+ percpu_ref_exit (& mddev -> active_io );
60416044 return err ;
60426045}
60436046EXPORT_SYMBOL_GPL (md_run );
@@ -6262,6 +6265,7 @@ void md_stop(struct mddev *mddev)
62626265 */
62636266 __md_stop_writes (mddev );
62646267 __md_stop (mddev );
6268+ percpu_ref_exit (& mddev -> active_io );
62656269 bioset_exit (& mddev -> bio_set );
62666270 bioset_exit (& mddev -> sync_set );
62676271}
@@ -7835,6 +7839,7 @@ static void md_free_disk(struct gendisk *disk)
78357839 struct mddev * mddev = disk -> private_data ;
78367840
78377841 percpu_ref_exit (& mddev -> writes_pending );
7842+ percpu_ref_exit (& mddev -> active_io );
78387843 bioset_exit (& mddev -> bio_set );
78397844 bioset_exit (& mddev -> sync_set );
78407845
0 commit comments