diff options
author | NeilBrown <neilb@suse.com> | 2017-03-10 01:00:47 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2017-03-11 17:31:37 -0500 |
commit | f5fe1b51905df7cfe4fdfd85c5fb7bc5b71a094f (patch) | |
tree | fbc336ee9d7ca18f8bfd81a8b54e99efd0555241 | |
parent | 84c37c168c0e49a412d7021cda3183a72adac0d0 (diff) |
blk: Ensure users for current->bio_list can see the full list.
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>
-rw-r--r-- | block/bio.c | 12 | ||||
-rw-r--r-- | block/blk-core.c | 30 | ||||
-rw-r--r-- | drivers/md/dm.c | 29 | ||||
-rw-r--r-- | drivers/md/raid10.c | 3 |
4 files changed, 45 insertions, 29 deletions
diff --git a/block/bio.c b/block/bio.c index 5eec5e08417f..e75878f8b14a 100644 --- a/block/bio.c +++ b/block/bio.c | |||
@@ -376,10 +376,14 @@ static void punt_bios_to_rescuer(struct bio_set *bs) | |||
376 | bio_list_init(&punt); | 376 | bio_list_init(&punt); |
377 | bio_list_init(&nopunt); | 377 | bio_list_init(&nopunt); |
378 | 378 | ||
379 | while ((bio = bio_list_pop(current->bio_list))) | 379 | while ((bio = bio_list_pop(¤t->bio_list[0]))) |
380 | bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio); | 380 | bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio); |
381 | current->bio_list[0] = nopunt; | ||
381 | 382 | ||
382 | *current->bio_list = nopunt; | 383 | bio_list_init(&nopunt); |
384 | while ((bio = bio_list_pop(¤t->bio_list[1]))) | ||
385 | bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio); | ||
386 | current->bio_list[1] = nopunt; | ||
383 | 387 | ||
384 | spin_lock(&bs->rescue_lock); | 388 | spin_lock(&bs->rescue_lock); |
385 | bio_list_merge(&bs->rescue_list, &punt); | 389 | bio_list_merge(&bs->rescue_list, &punt); |
@@ -466,7 +470,9 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) | |||
466 | * we retry with the original gfp_flags. | 470 | * we retry with the original gfp_flags. |
467 | */ | 471 | */ |
468 | 472 | ||
469 | if (current->bio_list && !bio_list_empty(current->bio_list)) | 473 | if (current->bio_list && |
474 | (!bio_list_empty(¤t->bio_list[0]) || | ||
475 | !bio_list_empty(¤t->bio_list[1]))) | ||
470 | gfp_mask &= ~__GFP_DIRECT_RECLAIM; | 476 | gfp_mask &= ~__GFP_DIRECT_RECLAIM; |
471 | 477 | ||
472 | p = mempool_alloc(bs->bio_pool, gfp_mask); | 478 | p = mempool_alloc(bs->bio_pool, gfp_mask); |
diff --git a/block/blk-core.c b/block/blk-core.c index 0eeb99ef654f..d772c221cc17 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -1973,7 +1973,14 @@ end_io: | |||
1973 | */ | 1973 | */ |
1974 | blk_qc_t generic_make_request(struct bio *bio) | 1974 | blk_qc_t generic_make_request(struct bio *bio) |
1975 | { | 1975 | { |
1976 | struct bio_list bio_list_on_stack; | 1976 | /* |
1977 | * bio_list_on_stack[0] contains bios submitted by the current | ||
1978 | * make_request_fn. | ||
1979 | * bio_list_on_stack[1] contains bios that were submitted before | ||
1980 | * the current make_request_fn, but that haven't been processed | ||
1981 | * yet. | ||
1982 | */ | ||
1983 | struct bio_list bio_list_on_stack[2]; | ||
1977 | blk_qc_t ret = BLK_QC_T_NONE; | 1984 | blk_qc_t ret = BLK_QC_T_NONE; |
1978 | 1985 | ||
1979 | if (!generic_make_request_checks(bio)) | 1986 | if (!generic_make_request_checks(bio)) |
@@ -1990,7 +1997,7 @@ blk_qc_t generic_make_request(struct bio *bio) | |||
1990 | * should be added at the tail | 1997 | * should be added at the tail |
1991 | */ | 1998 | */ |
1992 | if (current->bio_list) { | 1999 | if (current->bio_list) { |
1993 | bio_list_add(current->bio_list, bio); | 2000 | bio_list_add(¤t->bio_list[0], bio); |
1994 | goto out; | 2001 | goto out; |
1995 | } | 2002 | } |
1996 | 2003 | ||
@@ -2009,18 +2016,17 @@ blk_qc_t generic_make_request(struct bio *bio) | |||
2009 | * bio_list, and call into ->make_request() again. | 2016 | * bio_list, and call into ->make_request() again. |
2010 | */ | 2017 | */ |
2011 | BUG_ON(bio->bi_next); | 2018 | BUG_ON(bio->bi_next); |
2012 | bio_list_init(&bio_list_on_stack); | 2019 | bio_list_init(&bio_list_on_stack[0]); |
2013 | current->bio_list = &bio_list_on_stack; | 2020 | current->bio_list = bio_list_on_stack; |
2014 | do { | 2021 | do { |
2015 | struct request_queue *q = bdev_get_queue(bio->bi_bdev); | 2022 | struct request_queue *q = bdev_get_queue(bio->bi_bdev); |
2016 | 2023 | ||
2017 | if (likely(blk_queue_enter(q, false) == 0)) { | 2024 | if (likely(blk_queue_enter(q, false) == 0)) { |
2018 | struct bio_list hold; | ||
2019 | struct bio_list lower, same; | 2025 | struct bio_list lower, same; |
2020 | 2026 | ||
2021 | /* Create a fresh bio_list for all subordinate requests */ | 2027 | /* Create a fresh bio_list for all subordinate requests */ |
2022 | hold = bio_list_on_stack; | 2028 | bio_list_on_stack[1] = bio_list_on_stack[0]; |
2023 | bio_list_init(&bio_list_on_stack); | 2029 | bio_list_init(&bio_list_on_stack[0]); |
2024 | ret = q->make_request_fn(q, bio); | 2030 | ret = q->make_request_fn(q, bio); |
2025 | 2031 | ||
2026 | blk_queue_exit(q); | 2032 | blk_queue_exit(q); |
@@ -2030,19 +2036,19 @@ blk_qc_t generic_make_request(struct bio *bio) | |||
2030 | */ | 2036 | */ |
2031 | bio_list_init(&lower); | 2037 | bio_list_init(&lower); |
2032 | bio_list_init(&same); | 2038 | bio_list_init(&same); |
2033 | while ((bio = bio_list_pop(&bio_list_on_stack)) != NULL) | 2039 | while ((bio = bio_list_pop(&bio_list_on_stack[0])) != NULL) |
2034 | if (q == bdev_get_queue(bio->bi_bdev)) | 2040 | if (q == bdev_get_queue(bio->bi_bdev)) |
2035 | bio_list_add(&same, bio); | 2041 | bio_list_add(&same, bio); |
2036 | else | 2042 | else |
2037 | bio_list_add(&lower, bio); | 2043 | bio_list_add(&lower, bio); |
2038 | /* now assemble so we handle the lowest level first */ | 2044 | /* now assemble so we handle the lowest level first */ |
2039 | bio_list_merge(&bio_list_on_stack, &lower); | 2045 | bio_list_merge(&bio_list_on_stack[0], &lower); |
2040 | bio_list_merge(&bio_list_on_stack, &same); | 2046 | bio_list_merge(&bio_list_on_stack[0], &same); |
2041 | bio_list_merge(&bio_list_on_stack, &hold); | 2047 | bio_list_merge(&bio_list_on_stack[0], &bio_list_on_stack[1]); |
2042 | } else { | 2048 | } else { |
2043 | bio_io_error(bio); | 2049 | bio_io_error(bio); |
2044 | } | 2050 | } |
2045 | bio = bio_list_pop(current->bio_list); | 2051 | bio = bio_list_pop(&bio_list_on_stack[0]); |
2046 | } while (bio); | 2052 | } while (bio); |
2047 | current->bio_list = NULL; /* deactivate */ | 2053 | current->bio_list = NULL; /* deactivate */ |
2048 | 2054 | ||
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index f4ffd1eb8f44..dfb75979e455 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -989,26 +989,29 @@ static void flush_current_bio_list(struct blk_plug_cb *cb, bool from_schedule) | |||
989 | struct dm_offload *o = container_of(cb, struct dm_offload, cb); | 989 | struct dm_offload *o = container_of(cb, struct dm_offload, cb); |
990 | struct bio_list list; | 990 | struct bio_list list; |
991 | struct bio *bio; | 991 | struct bio *bio; |
992 | int i; | ||
992 | 993 | ||
993 | INIT_LIST_HEAD(&o->cb.list); | 994 | INIT_LIST_HEAD(&o->cb.list); |
994 | 995 | ||
995 | if (unlikely(!current->bio_list)) | 996 | if (unlikely(!current->bio_list)) |
996 | return; | 997 | return; |
997 | 998 | ||
998 | list = *current->bio_list; | 999 | for (i = 0; i < 2; i++) { |
999 | bio_list_init(current->bio_list); | 1000 | list = current->bio_list[i]; |
1000 | 1001 | bio_list_init(¤t->bio_list[i]); | |
1001 | while ((bio = bio_list_pop(&list))) { | 1002 | |
1002 | struct bio_set *bs = bio->bi_pool; | 1003 | while ((bio = bio_list_pop(&list))) { |
1003 | if (unlikely(!bs) || bs == fs_bio_set) { | 1004 | struct bio_set *bs = bio->bi_pool; |
1004 | bio_list_add(current->bio_list, bio); | 1005 | if (unlikely(!bs) || bs == fs_bio_set) { |
1005 | continue; | 1006 | bio_list_add(¤t->bio_list[i], bio); |
1007 | continue; | ||
1008 | } | ||
1009 | |||
1010 | spin_lock(&bs->rescue_lock); | ||
1011 | bio_list_add(&bs->rescue_list, bio); | ||
1012 | queue_work(bs->rescue_workqueue, &bs->rescue_work); | ||
1013 | spin_unlock(&bs->rescue_lock); | ||
1006 | } | 1014 | } |
1007 | |||
1008 | spin_lock(&bs->rescue_lock); | ||
1009 | bio_list_add(&bs->rescue_list, bio); | ||
1010 | queue_work(bs->rescue_workqueue, &bs->rescue_work); | ||
1011 | spin_unlock(&bs->rescue_lock); | ||
1012 | } | 1015 | } |
1013 | } | 1016 | } |
1014 | 1017 | ||
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 063c43d83b72..0536658c9d40 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -974,7 +974,8 @@ static void wait_barrier(struct r10conf *conf) | |||
974 | !conf->barrier || | 974 | !conf->barrier || |
975 | (atomic_read(&conf->nr_pending) && | 975 | (atomic_read(&conf->nr_pending) && |
976 | current->bio_list && | 976 | current->bio_list && |
977 | !bio_list_empty(current->bio_list)), | 977 | (!bio_list_empty(¤t->bio_list[0]) || |
978 | !bio_list_empty(¤t->bio_list[1]))), | ||
978 | conf->resync_lock); | 979 | conf->resync_lock); |
979 | conf->nr_waiting--; | 980 | conf->nr_waiting--; |
980 | if (!conf->nr_waiting) | 981 | if (!conf->nr_waiting) |