Skip to content

Commit 9efcc2c

Browse files
YuKuai-huaweiliu-song-6
authored andcommitted
md/raid1-10: don't handle pluged bio by daemon thread
current->bio_list will be set under submit_bio() context, in this case bitmap io will be added to the list and wait for current io submission to finish, while current io submission must wait for bitmap io to be done. commit 874807a ("md/raid1{,0}: fix deadlock in bitmap_unplug.") fix the deadlock by handling plugged bio by daemon thread. On the one hand, the deadlock won't exist after commit a214b94 ("blk-mq: only flush requests from the plug in blk_mq_submit_bio"). On the other hand, current solution makes it impossible to flush plugged bio in raid1/10_make_request(), because this will cause that all the writes will goto daemon thread. In order to limit the number of plugged bio, commit 874807a ("md/raid1{,0}: fix deadlock in bitmap_unplug.") is reverted, and the deadlock is fixed by handling bitmap io asynchronously. Signed-off-by: Yu Kuai <[email protected]> Signed-off-by: Song Liu <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent a022325 commit 9efcc2c

File tree

3 files changed

+19
-7
lines changed

3 files changed

+19
-7
lines changed

drivers/md/raid1-10.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,17 @@ static inline bool raid1_add_bio_to_plug(struct mddev *mddev, struct bio *bio,
152152

153153
return true;
154154
}
155+
156+
/*
157+
* current->bio_list will be set under submit_bio() context, in this case bitmap
158+
* io will be added to the list and wait for current io submission to finish,
159+
* while current io submission must wait for bitmap io to be done. In order to
160+
* avoid such deadlock, submit bitmap io asynchronously.
161+
*/
162+
static inline void raid1_prepare_flush_writes(struct bitmap *bitmap)
163+
{
164+
if (current->bio_list)
165+
md_bitmap_unplug_async(bitmap);
166+
else
167+
md_bitmap_unplug(bitmap);
168+
}

drivers/md/raid1.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
794794
static void flush_bio_list(struct r1conf *conf, struct bio *bio)
795795
{
796796
/* flush any pending bitmap writes to disk before proceeding w/ I/O */
797-
md_bitmap_unplug(conf->mddev->bitmap);
797+
raid1_prepare_flush_writes(conf->mddev->bitmap);
798798
wake_up(&conf->wait_barrier);
799799

800800
while (bio) { /* submit pending writes */
@@ -1169,7 +1169,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule)
11691169
struct r1conf *conf = mddev->private;
11701170
struct bio *bio;
11711171

1172-
if (from_schedule || current->bio_list) {
1172+
if (from_schedule) {
11731173
spin_lock_irq(&conf->device_lock);
11741174
bio_list_merge(&conf->pending_bio_list, &plug->pending);
11751175
spin_unlock_irq(&conf->device_lock);

drivers/md/raid10.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -910,9 +910,7 @@ static void flush_pending_writes(struct r10conf *conf)
910910
__set_current_state(TASK_RUNNING);
911911

912912
blk_start_plug(&plug);
913-
/* flush any pending bitmap writes to disk
914-
* before proceeding w/ I/O */
915-
md_bitmap_unplug(conf->mddev->bitmap);
913+
raid1_prepare_flush_writes(conf->mddev->bitmap);
916914
wake_up(&conf->wait_barrier);
917915

918916
while (bio) { /* submit pending writes */
@@ -1116,7 +1114,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
11161114
struct r10conf *conf = mddev->private;
11171115
struct bio *bio;
11181116

1119-
if (from_schedule || current->bio_list) {
1117+
if (from_schedule) {
11201118
spin_lock_irq(&conf->device_lock);
11211119
bio_list_merge(&conf->pending_bio_list, &plug->pending);
11221120
spin_unlock_irq(&conf->device_lock);
@@ -1128,7 +1126,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
11281126

11291127
/* we aren't scheduling, so we can do the write-out directly. */
11301128
bio = bio_list_get(&plug->pending);
1131-
md_bitmap_unplug(mddev->bitmap);
1129+
raid1_prepare_flush_writes(mddev->bitmap);
11321130
wake_up(&conf->wait_barrier);
11331131

11341132
while (bio) { /* submit pending writes */

0 commit comments

Comments
 (0)