From: Yu Kuai <yukuai3@xxxxxxxxxx> There are no functional changes, prepare to fix a problem that 'sb_wait' is not woke up while 'active_io' is decreased to 0. Signed-off-by: Yu Kuai <yukuai3@xxxxxxxxxx> --- drivers/md/md.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 0fe7ab6e8ab9..0d69b1a2e2d5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -368,16 +368,18 @@ static bool is_suspended(struct mddev *mddev, struct bio *bio) return true; } -void md_handle_request(struct mddev *mddev, struct bio *bio) +static bool md_array_enter(struct mddev *mddev, struct bio *bio) { check_suspended: if (is_suspended(mddev, bio)) { DEFINE_WAIT(__wait); + /* Bail out if REQ_NOWAIT is set for the bio */ if (bio->bi_opf & REQ_NOWAIT) { bio_wouldblock_error(bio); - return; + return false; } + for (;;) { prepare_to_wait(&mddev->sb_wait, &__wait, TASK_UNINTERRUPTIBLE); @@ -387,15 +389,34 @@ void md_handle_request(struct mddev *mddev, struct bio *bio) } finish_wait(&mddev->sb_wait, &__wait); } + if (!percpu_ref_tryget_live(&mddev->active_io)) goto check_suspended; + return true; +} + +static void md_array_exit(struct mddev *mddev) +{ + percpu_ref_put(&mddev->active_io); +} + +void md_handle_request(struct mddev *mddev, struct bio *bio) +{ +retry: + if (!md_array_enter(mddev, bio)) + return; + if (!mddev->pers->make_request(mddev, bio)) { - percpu_ref_put(&mddev->active_io); - goto check_suspended; + md_array_exit(mddev); + goto retry; } - percpu_ref_put(&mddev->active_io); + /* + * pers->make_request() will grab additional reference until bio is + * done. + */ + md_array_exit(mddev); } EXPORT_SYMBOL(md_handle_request); @@ -8667,7 +8688,7 @@ static void md_end_clone_io(struct bio *bio) bio_put(bio); bio_endio(orig_bio); - percpu_ref_put(&mddev->active_io); + md_array_exit(mddev); } static void md_clone_bio(struct mddev *mddev, struct bio **bio) -- 2.39.2