md: retry bailed bio
Subsystems (3)
cover md: retry bailed bio
From: Shaohua Li <[email protected]>
With cc27b0c78c79(md: fix deadlock between mddev_suspend() and md_write_start()), pers->make_request could bail out without handling the bio. If that happens, we should retry. There are two call sites we don't do the retry and cause problems. This set fixes the issues.
Thanks,
Shaohua
Shaohua Li (3):
md: separate request handling
md: fix a race condition for flush request handling
dm-raid: fix a race condition in request handling
drivers/md/dm-raid.c | 2 +- drivers/md/md.c | 72 +++++++++++++++++++++++++++++++--------------------- drivers/md/md.h | 1 + 3 files changed, 45 insertions(+), 30 deletions(-)
Signature · 1 line
2.11.0
PATCH 1/3 md: separate request handling
From: Shaohua Li <[email protected]>
With commit cc27b0c78c79, pers->make_request could bail out without handling the bio. If that happens, we should retry. The commit fixes md_make_request but not other call sites. Separate the request handling part, so other call sites can use it.
Fix: cc27b0c78c79(md: fix deadlock between mddev_suspend() and md_write_start())
--- drivers/md/md.c | 58 ++++++++++++++++++++++++++++++++------------------------- drivers/md/md.h | 1 + 2 files changed, 34 insertions(+), 25 deletions(-)
drivers/md/md.c +33 -25
@@ -266,6 +266,37 @@ static DEFINE_SPINLOCK(all_mddevs_lock);* call has finished, the bio has been linked into some internal structure * and so is visible to ->quiesce(), so we don't need the refcount any more. */ +void md_handle_request (struct mddev *mddev,struct bio *bio) +{ +check_suspended: +rcu_read_lock (); +if (mddev->suspended) { +DEFINE_WAIT (__wait); +for (;;) { +prepare_to_wait (&mddev->sb_wait, &__wait, +TASK_UNINTERRUPTIBLE ); +if (!mddev->suspended) +break ; +rcu_read_unlock (); +schedule (); +rcu_read_lock (); + } +finish_wait (&mddev->sb_wait, &__wait); + } +atomic_inc (&mddev->active_io); +rcu_read_unlock (); + +if (!mddev->pers->make_request (mddev, bio)) { +atomic_dec (&mddev->active_io); +wake_up (&mddev->sb_wait); + goto check_suspended; + } + +if (atomic_dec_and_test (&mddev->active_io) && mddev->suspended) +wake_up (&mddev->sb_wait); +} +EXPORT_SYMBOL (md_handle_request); +static blk_qc_t md_make_request (struct request_queue *q,struct bio *bio) {const int rw =bio_data_dir (bio);
@@ -285,23 +316,6 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)bio_endio (bio);return BLK_QC_T_NONE ; } -check_suspended: -rcu_read_lock (); -if (mddev->suspended) { -DEFINE_WAIT (__wait); -for (;;) { -prepare_to_wait (&mddev->sb_wait, &__wait, -TASK_UNINTERRUPTIBLE ); -if (!mddev->suspended) -break ; -rcu_read_unlock (); -schedule (); -rcu_read_lock (); - } -finish_wait (&mddev->sb_wait, &__wait); - } -atomic_inc (&mddev->active_io); -rcu_read_unlock ();/* * save the sectors now since our bio can
@@ -310,20 +324,14 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio) sectors =bio_sectors (bio);/* bio could be mergeable after passing to underlayer */ bio->bi_opf &= ~REQ_NOMERGE ; -if (!mddev->pers->make_request (mddev, bio)) { -atomic_dec (&mddev->active_io); -wake_up (&mddev->sb_wait); - goto check_suspended; - } + +md_handle_request (mddev, bio); cpu =part_stat_lock ();part_stat_inc (cpu, &mddev->gendisk->part0, ios[rw]);part_stat_add (cpu, &mddev->gendisk->part0, sectors[rw], sectors);part_stat_unlock (); -if (atomic_dec_and_test (&mddev->active_io) && mddev->suspended) -wake_up (&mddev->sb_wait); -return BLK_QC_T_NONE ; }
drivers/md/md.h +1 -0
@@ -692,6 +692,7 @@ extern void md_stop_writes(struct mddev *mddev);extern int md_rdev_init (struct md_rdev *rdev);extern void md_rdev_clear (struct md_rdev *rdev); +extern void md_handle_request (struct mddev *mddev,struct bio *bio);extern void mddev_suspend (struct mddev *mddev);extern void mddev_resume (struct mddev *mddev); extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
Signature · 1 line
2.11.0
PATCH 2/3 md: fix a race condition for flush request handling
In reply to Shaohua LiFrom: Shaohua Li <[email protected]>
md_submit_flush_data calls pers->make_request, which missed the suspend check. Fix it with the new md_handle_request API.
Fix: cc27b0c78c79(md: fix deadlock between mddev_suspend() and md_write_start())
--- drivers/md/md.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/md/md.c +10 -4
@@ -447,16 +447,22 @@ static void md_submit_flush_data(struct work_struct *ws) struct mddev *mddev = container_of(ws, struct mddev, flush_work);struct bio *bio = mddev->flush_bio; +/* +* must reset flush_bio before calling into md_handle_request to avoid a +* deadlock, because other bios passed md_handle_request suspend check +* could wait for this and below md_handle_request could wait for those +* bios because of suspend check +*/ + mddev->flush_bio =NULL ; +wake_up (&mddev->sb_wait); +if (bio->bi_iter.bi_size ==0 )/* an empty barrier - all done */ bio_endio (bio);else { bio->bi_opf &= ~REQ_PREFLUSH ; - mddev->pers->make_request (mddev, bio); +md_handle_request (mddev, bio); } - - mddev->flush_bio =NULL ; -wake_up (&mddev->sb_wait); }void md_flush_request (struct mddev *mddev,struct bio *bio)
Signature · 1 line
2.11.0
PATCH 3/3 dm-raid: fix a race condition in request handling
In reply to Shaohua LiFrom: Shaohua Li <[email protected]>
raid_map calls pers->make_request, which missed the suspend check. Fix it with the new md_handle_request API.
Fix: cc27b0c78c79(md: fix deadlock between mddev_suspend() and md_write_start())
--- drivers/md/dm-raid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/dm-raid.c +1 -1
@@ -3238,7 +3238,7 @@ static int raid_map(struct dm_target *ti, struct bio *bio)if (unlikely (bio_end_sector (bio) > mddev->array_sectors))return DM_MAPIO_REQUEUE ; - mddev->pers->make_request (mddev, bio); +md_handle_request (mddev, bio);return DM_MAPIO_SUBMITTED ; }
Signature · 1 line
2.11.0
Quoted 6 lines · Shaohua Li
From: Shaohua Li <[email protected]>
With
cc27b0c78c79(md: fix deadlock between mddev_suspend() and md_write_start()),pers->make_requestcould bail out without handling the bio. If that happens, we should retry. There are two call sites we don't do the retry and cause problems. This set fixes the issues.
All look good to me, thanks.
NeilBrown
Quoted 21 lines
Thanks,
ShaohuaShaohua Li (3):
md: separate request handling
md: fix a race condition for flush request handling
dm-raid: fix a race condition in request handlingdrivers/md/dm-raid.c | 2 +- drivers/md/md.c | 72 +++++++++++++++++++++++++++++++--------------------- drivers/md/md.h | 1 + 3 files changed, 45 insertions(+), 30 deletions(-)Signature · 6 lines
2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-raid" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html