Patch "blk: Ensure users for current->bio_list can see the full list." has been added to the 4.4-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
blk: Ensure users for current->bio_list can see the full list.
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
blk-ensure-users-for-current-bio_list-can-see-the-full-list.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
f5fe1b51905df7cfe4fdfd85c5fb7bc5b71a094fMon Sep 17 00:00:00 2001
From: NeilBrown <[email protected]>
Date: Fri, 10 Mar 2017 17:00:47 +1100
Subject: blk: Ensure users for current->bio_list can see the full list.
From: NeilBrown <[email protected]>
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.
--- block/bio.c | 12 +++++++++--- block/blk-core.c | 31 +++++++++++++++++++------------ drivers/md/raid1.c | 3 ++- drivers/md/raid10.c | 3 ++- 4 files changed, 32 insertions(+), 17 deletions(-)
block/bio.c +9 -3
@@ -373,10 +373,14 @@ static void punt_bios_to_rescuer(structbio_list_init (&punt);bio_list_init (&nopunt); -while ((bio =bio_list_pop (current->bio_list))) +while ((bio =bio_list_pop (¤t->bio_list[0 ])))bio_list_add (bio->bi_pool == bs ? &punt : &nopunt, bio); + current->bio_list[0 ] = nopunt; - *current->bio_list = nopunt; +bio_list_init (&nopunt); +while ((bio =bio_list_pop (¤t->bio_list[1 ]))) +bio_list_add (bio->bi_pool == bs ? &punt : &nopunt, bio); + current->bio_list[1 ] = nopunt;spin_lock (&bs->rescue_lock);bio_list_merge (&bs->rescue_list, &punt);
@@ -464,7 +468,9 @@ struct bio *bio_alloc_bioset(gfp_t gfp_m* we retry with the original gfp_flags. */ -if (current->bio_list && !bio_list_empty (current->bio_list)) +if (current->bio_list && + (!bio_list_empty (¤t->bio_list[0 ]) || + !bio_list_empty (¤t->bio_list[1 ]))) gfp_mask &= ~__GFP_DIRECT_RECLAIM; p =mempool_alloc (bs->bio_pool, gfp_mask);
block/blk-core.c +19 -12
@@ -2021,7 +2021,14 @@ end_io:*/ blk_qc_t generic_make_request (struct bio *bio) { -struct bio_list bio_list_on_stack; +/* +* bio_list_on_stack[0] contains bios submitted by the current +* make_request_fn. +* bio_list_on_stack[1] contains bios that were submitted before +* the current make_request_fn, but that haven't been processed +* yet. +*/ +struct bio_list bio_list_on_stack[2 ];blk_qc_t ret =BLK_QC_T_NONE ;if (!generic_make_request_checks (bio))
@@ -2038,7 +2045,7 @@ blk_qc_t generic_make_request(struct bio* should be added at the tail */ if (current->bio_list) { -bio_list_add (current->bio_list, bio); +bio_list_add (¤t->bio_list[0 ], bio); goto out; }
@@ -2057,17 +2064,17 @@ blk_qc_t generic_make_request(struct bio* bio_list, and call into ->make_request() again. */ BUG_ON (bio->bi_next); -bio_list_init (&bio_list_on_stack); - current->bio_list = &bio_list_on_stack; +bio_list_init (&bio_list_on_stack[0 ]); + current->bio_list = bio_list_on_stack; do { 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, hold; + struct bio_list lower, same; /* Create a fresh bio_list for all subordinate requests */ - hold = bio_list_on_stack; - bio_list_init(&bio_list_on_stack); + bio_list_on_stack[1] = bio_list_on_stack[0]; + bio_list_init(&bio_list_on_stack[0]); ret = q->make_request_fn(q, bio);
@@ -2077,19 +2084,19 @@ blk_qc_t generic_make_request(struct bio*/ bio_list_init (&lower);bio_list_init (&same); -while ((bio =bio_list_pop (&bio_list_on_stack)) !=NULL ) +while ((bio =bio_list_pop (&bio_list_on_stack[0 ])) !=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_list_merge (&bio_list_on_stack[0 ], &lower); +bio_list_merge (&bio_list_on_stack[0 ], &same); +bio_list_merge (&bio_list_on_stack[0 ], &bio_list_on_stack[1 ]); }else {bio_io_error (bio); } - bio =bio_list_pop (current->bio_list); + bio =bio_list_pop (&bio_list_on_stack[0 ]); }while (bio); current->bio_list =NULL ;/* deactivate */
drivers/md/raid1.c +2 -1
@@ -877,7 +877,8 @@ static sector_t wait_barrier(struct r1co ((conf->start_next_window < conf->next_resync +RESYNC_SECTORS ) && current->bio_list && - !bio_list_empty(current->bio_list))), + (!bio_list_empty (¤t->bio_list[0 ]) || + !bio_list_empty(¤t->bio_list[1])))), conf->resync_lock); conf->nr_waiting--; }
drivers/md/raid10.c +2 -1
@@ -946,7 +946,8 @@ static void wait_barrier(struct r10conf !conf->barrier || (conf->nr_pending && current->bio_list && - !bio_list_empty (current->bio_list)), + (!bio_list_empty (¤t->bio_list[0 ]) || + !bio_list_empty (¤t->bio_list[1 ]))), conf->resync_lock); conf->nr_waiting--; }
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/blk-improve-order-of-bio-handling-in-generic_make_request.patch queue-4.4/blk-ensure-users-for-current-bio_list-can-see-the-full-list.patch