J Jinpu Wang #
Message details and related content
On Mon, Dec 19, 2016 at 12:16 PM, Jinpu Wang [off-list ref] wrote:
Hi Neil, After apply the patch below, it paniced during boot in generic_make_request-> bio_list_pop. Looks related to you do bio_list_init(&bio_list_on_stack); again.quoted
diff --git a/block/blk-core.c b/block/blk-core.c index 14d7c0740dc0..3436b6fc3ef8 100644 --- a/block/blk-core.c +++ b/block/blk-core.c@@ -2036,10 +2036,31 @@ blk_qc_t generic_make_request(struct bio *bio) struct request_queue *q = bdev_get_queue(bio->bi_bdev); if (likely(blk_queue_enter(q, false) == 0)) { + struct bio_list hold; + struct bio_list lower, same; + + /* Create a fresh bio_list for all subordinate requests */ + bio_list_merge(&hold, &bio_list_on_stack); + bio_list_init(&bio_list_on_stack); ??? maybe init hold, and then merge bio_list_on_stack? ret = q->make_request_fn(q, bio); blk_queue_exit(q); + /* sort new bios into those for a lower level + * and those for the same level + */ + bio_list_init(&lower); + bio_list_init(&same); + while ((bio = bio_list_pop(&bio_list_on_stack)) != NULL) + if (q == bdev_get_queue(bio->bi_bdev)) + bio_list_add(&same, bio); + else + bio_list_add(&lower, bio); + /* now assemble so we handle the lowest level first */ + bio_list_merge(&bio_list_on_stack, &lower); + bio_list_merge(&bio_list_on_stack, &same); + bio_list_merge(&bio_list_on_stack, &hold); + bio = bio_list_pop(current->bio_list); } else { struct bio *bio_next = bio_list_pop(current->bio_list);
Seems we don't need bio_list hold at all, lower and seem merge back to bio_list_on_stack? I'm currently testing patch below, so far so good.
diff --git a/block/blk-core.c b/block/blk-core.c
index e8d15d8..9c56cf7 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c@@ -2064,10 +2064,24 @@ blk_qc_t generic_make_request(struct bio *bio) struct request_queue *q = bdev_get_queue(bio->bi_bdev); if (likely(blk_queue_enter(q, __GFP_DIRECT_RECLAIM) == 0)) { + struct bio_list lower, same; ret = q->make_request_fn(q, bio); blk_queue_exit(q); + /* sort new bios into those for a lower level + * and those for the same level + */ + bio_list_init(&lower); + bio_list_init(&same); + while ((bio = bio_list_pop(&bio_list_on_stack)) != NULL) + if (q == bdev_get_queue(bio->bi_bdev)) + bio_list_add(&same, bio); + else + bio_list_add(&lower, bio); + /* now assemble so we handle the lowest level first */ + bio_list_merge(&bio_list_on_stack, &lower); + bio_list_merge(&bio_list_on_stack, &same); bio = bio_list_pop(current->bio_list); } else {
--
Jinpu Wang
Linux Kernel Developer
ProfitBricks GmbH
Greifswalder Str. 207
D - 10405 Berlin
Tel: +49 30 577 008 042
Fax: +49 30 577 008 299
Email: jinpu.wang@profitbricks.com
URL: https://www.profitbricks.de
Sitz der Gesellschaft: Berlin
Registergericht: Amtsgericht Charlottenburg, HRB 125506 B
Geschäftsführer: Achim Weiss