diff options
author | NeilBrown <neilb@suse.com> | 2017-03-10 01:00:47 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-04-08 03:30:36 -0400 |
commit | 5959cded91e319524f4e09f747b03c477d9fbaef (patch) | |
tree | c36407ef9c7196f3b8dcd9acdf26cffdfd735cda /drivers/md | |
parent | d5986e0078f25ee9862f3f13157f1421f18d6c64 (diff) |
blk: Ensure users for current->bio_list can see the full list.
commit f5fe1b51905df7cfe4fdfd85c5fb7bc5b71a094f upstream.
Commit 79bd99596b73 ("blk: improve order of bio handling in generic_make_request()")
changed current->bio_list so that it did not contain *all* of the
queued bios, but only those submitted by the currently running
make_request_fn.
There are two places which walk the list and requeue selected bios,
and others that check if the list is empty. These are no longer
correct.
So redefine current->bio_list to point to an array of two lists, which
contain all queued bios, and adjust various code to test or walk both
lists.
Signed-off-by: NeilBrown <neilb@suse.com>
Fixes: 79bd99596b73 ("blk: improve order of bio handling in generic_make_request()")
Signed-off-by: Jens Axboe <axboe@fb.com>
Cc: Jack Wang <jinpu.wang@profitbricks.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm.c | 29 | ||||
-rw-r--r-- | drivers/md/raid10.c | 3 |
2 files changed, 18 insertions, 14 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 628ba001bb3c..e66f4040d84b 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -986,26 +986,29 @@ static void flush_current_bio_list(struct blk_plug_cb *cb, bool from_schedule) | |||
986 | struct dm_offload *o = container_of(cb, struct dm_offload, cb); | 986 | struct dm_offload *o = container_of(cb, struct dm_offload, cb); |
987 | struct bio_list list; | 987 | struct bio_list list; |
988 | struct bio *bio; | 988 | struct bio *bio; |
989 | int i; | ||
989 | 990 | ||
990 | INIT_LIST_HEAD(&o->cb.list); | 991 | INIT_LIST_HEAD(&o->cb.list); |
991 | 992 | ||
992 | if (unlikely(!current->bio_list)) | 993 | if (unlikely(!current->bio_list)) |
993 | return; | 994 | return; |
994 | 995 | ||
995 | list = *current->bio_list; | 996 | for (i = 0; i < 2; i++) { |
996 | bio_list_init(current->bio_list); | 997 | list = current->bio_list[i]; |
997 | 998 | bio_list_init(¤t->bio_list[i]); | |
998 | while ((bio = bio_list_pop(&list))) { | 999 | |
999 | struct bio_set *bs = bio->bi_pool; | 1000 | while ((bio = bio_list_pop(&list))) { |
1000 | if (unlikely(!bs) || bs == fs_bio_set) { | 1001 | struct bio_set *bs = bio->bi_pool; |
1001 | bio_list_add(current->bio_list, bio); | 1002 | if (unlikely(!bs) || bs == fs_bio_set) { |
1002 | continue; | 1003 | bio_list_add(¤t->bio_list[i], bio); |
1004 | continue; | ||
1005 | } | ||
1006 | |||
1007 | spin_lock(&bs->rescue_lock); | ||
1008 | bio_list_add(&bs->rescue_list, bio); | ||
1009 | queue_work(bs->rescue_workqueue, &bs->rescue_work); | ||
1010 | spin_unlock(&bs->rescue_lock); | ||
1003 | } | 1011 | } |
1004 | |||
1005 | spin_lock(&bs->rescue_lock); | ||
1006 | bio_list_add(&bs->rescue_list, bio); | ||
1007 | queue_work(bs->rescue_workqueue, &bs->rescue_work); | ||
1008 | spin_unlock(&bs->rescue_lock); | ||
1009 | } | 1012 | } |
1010 | } | 1013 | } |
1011 | 1014 | ||
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 55b5e0e77b17..4c4aab02e311 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -941,7 +941,8 @@ static void wait_barrier(struct r10conf *conf) | |||
941 | !conf->barrier || | 941 | !conf->barrier || |
942 | (atomic_read(&conf->nr_pending) && | 942 | (atomic_read(&conf->nr_pending) && |
943 | current->bio_list && | 943 | current->bio_list && |
944 | !bio_list_empty(current->bio_list)), | 944 | (!bio_list_empty(¤t->bio_list[0]) || |
945 | !bio_list_empty(¤t->bio_list[1]))), | ||
945 | conf->resync_lock); | 946 | conf->resync_lock); |
946 | conf->nr_waiting--; | 947 | conf->nr_waiting--; |
947 | if (!conf->nr_waiting) | 948 | if (!conf->nr_waiting) |