Skip to content

Commit 5cca175

Browse files
NeilBrowngregkh
authored andcommitted
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> [jwang: backport to 4.4] Signed-off-by: Jack Wang <jinpu.wang@profitbricks.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> [bwh: Restore changes in device-mapper from upstream version] Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
1 parent 2cbd78f commit 5cca175

5 files changed

Lines changed: 48 additions & 30 deletions

File tree

block/bio.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,14 @@ static void punt_bios_to_rescuer(struct bio_set *bs)
373373
bio_list_init(&punt);
374374
bio_list_init(&nopunt);
375375

376-
while ((bio = bio_list_pop(current->bio_list)))
376+
while ((bio = bio_list_pop(&current->bio_list[0])))
377377
bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio);
378+
current->bio_list[0] = nopunt;
378379

379-
*current->bio_list = nopunt;
380+
bio_list_init(&nopunt);
381+
while ((bio = bio_list_pop(&current->bio_list[1])))
382+
bio_list_add(bio->bi_pool == bs ? &punt : &nopunt, bio);
383+
current->bio_list[1] = nopunt;
380384

381385
spin_lock(&bs->rescue_lock);
382386
bio_list_merge(&bs->rescue_list, &punt);
@@ -464,7 +468,9 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
464468
* we retry with the original gfp_flags.
465469
*/
466470

467-
if (current->bio_list && !bio_list_empty(current->bio_list))
471+
if (current->bio_list &&
472+
(!bio_list_empty(&current->bio_list[0]) ||
473+
!bio_list_empty(&current->bio_list[1])))
468474
gfp_mask &= ~__GFP_DIRECT_RECLAIM;
469475

470476
p = mempool_alloc(bs->bio_pool, gfp_mask);

block/blk-core.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,7 +2021,14 @@ generic_make_request_checks(struct bio *bio)
20212021
*/
20222022
blk_qc_t generic_make_request(struct bio *bio)
20232023
{
2024-
struct bio_list bio_list_on_stack;
2024+
/*
2025+
* bio_list_on_stack[0] contains bios submitted by the current
2026+
* make_request_fn.
2027+
* bio_list_on_stack[1] contains bios that were submitted before
2028+
* the current make_request_fn, but that haven't been processed
2029+
* yet.
2030+
*/
2031+
struct bio_list bio_list_on_stack[2];
20252032
blk_qc_t ret = BLK_QC_T_NONE;
20262033

20272034
if (!generic_make_request_checks(bio))
@@ -2038,7 +2045,7 @@ blk_qc_t generic_make_request(struct bio *bio)
20382045
* should be added at the tail
20392046
*/
20402047
if (current->bio_list) {
2041-
bio_list_add(current->bio_list, bio);
2048+
bio_list_add(&current->bio_list[0], bio);
20422049
goto out;
20432050
}
20442051

@@ -2057,17 +2064,17 @@ blk_qc_t generic_make_request(struct bio *bio)
20572064
* bio_list, and call into ->make_request() again.
20582065
*/
20592066
BUG_ON(bio->bi_next);
2060-
bio_list_init(&bio_list_on_stack);
2061-
current->bio_list = &bio_list_on_stack;
2067+
bio_list_init(&bio_list_on_stack[0]);
2068+
current->bio_list = bio_list_on_stack;
20622069
do {
20632070
struct request_queue *q = bdev_get_queue(bio->bi_bdev);
20642071

20652072
if (likely(blk_queue_enter(q, __GFP_DIRECT_RECLAIM) == 0)) {
2066-
struct bio_list lower, same, hold;
2073+
struct bio_list lower, same;
20672074

20682075
/* Create a fresh bio_list for all subordinate requests */
2069-
hold = bio_list_on_stack;
2070-
bio_list_init(&bio_list_on_stack);
2076+
bio_list_on_stack[1] = bio_list_on_stack[0];
2077+
bio_list_init(&bio_list_on_stack[0]);
20712078

20722079
ret = q->make_request_fn(q, bio);
20732080

@@ -2077,19 +2084,19 @@ blk_qc_t generic_make_request(struct bio *bio)
20772084
*/
20782085
bio_list_init(&lower);
20792086
bio_list_init(&same);
2080-
while ((bio = bio_list_pop(&bio_list_on_stack)) != NULL)
2087+
while ((bio = bio_list_pop(&bio_list_on_stack[0])) != NULL)
20812088
if (q == bdev_get_queue(bio->bi_bdev))
20822089
bio_list_add(&same, bio);
20832090
else
20842091
bio_list_add(&lower, bio);
20852092
/* now assemble so we handle the lowest level first */
2086-
bio_list_merge(&bio_list_on_stack, &lower);
2087-
bio_list_merge(&bio_list_on_stack, &same);
2088-
bio_list_merge(&bio_list_on_stack, &hold);
2093+
bio_list_merge(&bio_list_on_stack[0], &lower);
2094+
bio_list_merge(&bio_list_on_stack[0], &same);
2095+
bio_list_merge(&bio_list_on_stack[0], &bio_list_on_stack[1]);
20892096
} else {
20902097
bio_io_error(bio);
20912098
}
2092-
bio = bio_list_pop(current->bio_list);
2099+
bio = bio_list_pop(&bio_list_on_stack[0]);
20932100
} while (bio);
20942101
current->bio_list = NULL; /* deactivate */
20952102

drivers/md/dm.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,26 +1481,29 @@ static void flush_current_bio_list(struct blk_plug_cb *cb, bool from_schedule)
14811481
struct dm_offload *o = container_of(cb, struct dm_offload, cb);
14821482
struct bio_list list;
14831483
struct bio *bio;
1484+
int i;
14841485

14851486
INIT_LIST_HEAD(&o->cb.list);
14861487

14871488
if (unlikely(!current->bio_list))
14881489
return;
14891490

1490-
list = *current->bio_list;
1491-
bio_list_init(current->bio_list);
1492-
1493-
while ((bio = bio_list_pop(&list))) {
1494-
struct bio_set *bs = bio->bi_pool;
1495-
if (unlikely(!bs) || bs == fs_bio_set) {
1496-
bio_list_add(current->bio_list, bio);
1497-
continue;
1491+
for (i = 0; i < 2; i++) {
1492+
list = current->bio_list[i];
1493+
bio_list_init(&current->bio_list[i]);
1494+
1495+
while ((bio = bio_list_pop(&list))) {
1496+
struct bio_set *bs = bio->bi_pool;
1497+
if (unlikely(!bs) || bs == fs_bio_set) {
1498+
bio_list_add(&current->bio_list[i], bio);
1499+
continue;
1500+
}
1501+
1502+
spin_lock(&bs->rescue_lock);
1503+
bio_list_add(&bs->rescue_list, bio);
1504+
queue_work(bs->rescue_workqueue, &bs->rescue_work);
1505+
spin_unlock(&bs->rescue_lock);
14981506
}
1499-
1500-
spin_lock(&bs->rescue_lock);
1501-
bio_list_add(&bs->rescue_list, bio);
1502-
queue_work(bs->rescue_workqueue, &bs->rescue_work);
1503-
spin_unlock(&bs->rescue_lock);
15041507
}
15051508
}
15061509

drivers/md/raid1.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,8 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio)
877877
((conf->start_next_window <
878878
conf->next_resync + RESYNC_SECTORS) &&
879879
current->bio_list &&
880-
!bio_list_empty(current->bio_list))),
880+
(!bio_list_empty(&current->bio_list[0]) ||
881+
!bio_list_empty(&current->bio_list[1])))),
881882
conf->resync_lock);
882883
conf->nr_waiting--;
883884
}

drivers/md/raid10.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,8 @@ static void wait_barrier(struct r10conf *conf)
946946
!conf->barrier ||
947947
(conf->nr_pending &&
948948
current->bio_list &&
949-
!bio_list_empty(current->bio_list)),
949+
(!bio_list_empty(&current->bio_list[0]) ||
950+
!bio_list_empty(&current->bio_list[1]))),
950951
conf->resync_lock);
951952
conf->nr_waiting--;
952953
}

0 commit comments

Comments
 (0)