Skip to content

Commit

Permalink
md/raid1-10: don't handle pluged bio by daemon thread
Browse files Browse the repository at this point in the history
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 <yukuai3@huawei.com>
Signed-off-by: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20230529131106.2123367-7-yukuai1@huaweicloud.com
  • Loading branch information
Yu Kuai authored and Song Liu committed Jun 13, 2023
1 parent a022325 commit 9efcc2c
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 7 deletions.
14 changes: 14 additions & 0 deletions drivers/md/raid1-10.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,17 @@ static inline bool raid1_add_bio_to_plug(struct mddev *mddev, struct bio *bio,

return true;
}

/*
* 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. In order to
* avoid such deadlock, submit bitmap io asynchronously.
*/
static inline void raid1_prepare_flush_writes(struct bitmap *bitmap)
{
if (current->bio_list)
md_bitmap_unplug_async(bitmap);
else
md_bitmap_unplug(bitmap);
}
4 changes: 2 additions & 2 deletions drivers/md/raid1.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
static void flush_bio_list(struct r1conf *conf, struct bio *bio)
{
/* flush any pending bitmap writes to disk before proceeding w/ I/O */
md_bitmap_unplug(conf->mddev->bitmap);
raid1_prepare_flush_writes(conf->mddev->bitmap);
wake_up(&conf->wait_barrier);

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

if (from_schedule || current->bio_list) {
if (from_schedule) {
spin_lock_irq(&conf->device_lock);
bio_list_merge(&conf->pending_bio_list, &plug->pending);
spin_unlock_irq(&conf->device_lock);
Expand Down
8 changes: 3 additions & 5 deletions drivers/md/raid10.c
Original file line number Diff line number Diff line change
Expand Up @@ -910,9 +910,7 @@ static void flush_pending_writes(struct r10conf *conf)
__set_current_state(TASK_RUNNING);

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

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

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

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

while (bio) { /* submit pending writes */
Expand Down

0 comments on commit 9efcc2c

Please sign in to comment.