diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-15 19:54:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-15 19:54:58 -0400 |
commit | 69eea5a4ab9c705496e912b55a9d312325de19e6 (patch) | |
tree | 7643a4c90017a83f4497c9884c1b8bbcce097d83 | |
parent | 95422dec6bd4a7c57444743f7b1bb375335a6298 (diff) | |
parent | 9c62110454b088b4914ffe375c2dbc19643eac34 (diff) |
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Pull block fixes from Jens Axboe:
"Four small fixes for this cycle:
- followup fix from Neil for a fix that went in before -rc2, ensuring
that we always see the full per-task bio_list.
- fix for blk-mq-sched from me that ensures that we retain similar
direct-to-issue behavior on running the queue.
- fix from Sagi fixing a potential NULL pointer dereference in blk-mq
on spurious CPU unplug.
- a memory leak fix in writeback from Tahsin, fixing a case where
device removal of a mounted device can leak a struct
wb_writeback_work"
* 'for-linus' of git://git.kernel.dk/linux-block:
blk-mq-sched: don't run the queue async from blk_mq_try_issue_directly()
writeback: fix memory leak in wb_queue_work()
blk-mq: Fix tagset reinit in the presence of cpu hot-unplug
blk: Ensure users for current->bio_list can see the full list.
-rw-r--r-- | block/bio.c | 12 | ||||
-rw-r--r-- | block/blk-core.c | 30 | ||||
-rw-r--r-- | block/blk-mq-tag.c | 3 | ||||
-rw-r--r-- | block/blk-mq.c | 9 | ||||
-rw-r--r-- | drivers/md/dm.c | 29 | ||||
-rw-r--r-- | drivers/md/raid10.c | 3 | ||||
-rw-r--r-- | fs/fs-writeback.c | 35 |
7 files changed, 74 insertions, 47 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/block/blk-mq-tag.c b/block/blk-mq-tag.c index e48bc2c72615..9d97bfc4d465 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c | |||
@@ -295,6 +295,9 @@ int blk_mq_reinit_tagset(struct blk_mq_tag_set *set) | |||
295 | for (i = 0; i < set->nr_hw_queues; i++) { | 295 | for (i = 0; i < set->nr_hw_queues; i++) { |
296 | struct blk_mq_tags *tags = set->tags[i]; | 296 | struct blk_mq_tags *tags = set->tags[i]; |
297 | 297 | ||
298 | if (!tags) | ||
299 | continue; | ||
300 | |||
298 | for (j = 0; j < tags->nr_tags; j++) { | 301 | for (j = 0; j < tags->nr_tags; j++) { |
299 | if (!tags->static_rqs[j]) | 302 | if (!tags->static_rqs[j]) |
300 | continue; | 303 | continue; |
diff --git a/block/blk-mq.c b/block/blk-mq.c index 159187a28d66..a4546f060e80 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
@@ -1434,7 +1434,8 @@ static blk_qc_t request_to_qc_t(struct blk_mq_hw_ctx *hctx, struct request *rq) | |||
1434 | return blk_tag_to_qc_t(rq->internal_tag, hctx->queue_num, true); | 1434 | return blk_tag_to_qc_t(rq->internal_tag, hctx->queue_num, true); |
1435 | } | 1435 | } |
1436 | 1436 | ||
1437 | static void blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie) | 1437 | static void blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie, |
1438 | bool may_sleep) | ||
1438 | { | 1439 | { |
1439 | struct request_queue *q = rq->q; | 1440 | struct request_queue *q = rq->q; |
1440 | struct blk_mq_queue_data bd = { | 1441 | struct blk_mq_queue_data bd = { |
@@ -1475,7 +1476,7 @@ static void blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie) | |||
1475 | } | 1476 | } |
1476 | 1477 | ||
1477 | insert: | 1478 | insert: |
1478 | blk_mq_sched_insert_request(rq, false, true, true, false); | 1479 | blk_mq_sched_insert_request(rq, false, true, false, may_sleep); |
1479 | } | 1480 | } |
1480 | 1481 | ||
1481 | /* | 1482 | /* |
@@ -1569,11 +1570,11 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) | |||
1569 | 1570 | ||
1570 | if (!(data.hctx->flags & BLK_MQ_F_BLOCKING)) { | 1571 | if (!(data.hctx->flags & BLK_MQ_F_BLOCKING)) { |
1571 | rcu_read_lock(); | 1572 | rcu_read_lock(); |
1572 | blk_mq_try_issue_directly(old_rq, &cookie); | 1573 | blk_mq_try_issue_directly(old_rq, &cookie, false); |
1573 | rcu_read_unlock(); | 1574 | rcu_read_unlock(); |
1574 | } else { | 1575 | } else { |
1575 | srcu_idx = srcu_read_lock(&data.hctx->queue_rq_srcu); | 1576 | srcu_idx = srcu_read_lock(&data.hctx->queue_rq_srcu); |
1576 | blk_mq_try_issue_directly(old_rq, &cookie); | 1577 | blk_mq_try_issue_directly(old_rq, &cookie, true); |
1577 | srcu_read_unlock(&data.hctx->queue_rq_srcu, srcu_idx); | 1578 | srcu_read_unlock(&data.hctx->queue_rq_srcu, srcu_idx); |
1578 | } | 1579 | } |
1579 | goto done; | 1580 | goto done; |
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) |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ef600591d96f..63ee2940775c 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -173,19 +173,33 @@ static void wb_wakeup(struct bdi_writeback *wb) | |||
173 | spin_unlock_bh(&wb->work_lock); | 173 | spin_unlock_bh(&wb->work_lock); |
174 | } | 174 | } |
175 | 175 | ||
176 | static void finish_writeback_work(struct bdi_writeback *wb, | ||
177 | struct wb_writeback_work *work) | ||
178 | { | ||
179 | struct wb_completion *done = work->done; | ||
180 | |||
181 | if (work->auto_free) | ||
182 | kfree(work); | ||
183 | if (done && atomic_dec_and_test(&done->cnt)) | ||
184 | wake_up_all(&wb->bdi->wb_waitq); | ||
185 | } | ||
186 | |||
176 | static void wb_queue_work(struct bdi_writeback *wb, | 187 | static void wb_queue_work(struct bdi_writeback *wb, |
177 | struct wb_writeback_work *work) | 188 | struct wb_writeback_work *work) |
178 | { | 189 | { |
179 | trace_writeback_queue(wb, work); | 190 | trace_writeback_queue(wb, work); |
180 | 191 | ||
181 | spin_lock_bh(&wb->work_lock); | ||
182 | if (!test_bit(WB_registered, &wb->state)) | ||
183 | goto out_unlock; | ||
184 | if (work->done) | 192 | if (work->done) |
185 | atomic_inc(&work->done->cnt); | 193 | atomic_inc(&work->done->cnt); |
186 | list_add_tail(&work->list, &wb->work_list); | 194 | |
187 | mod_delayed_work(bdi_wq, &wb->dwork, 0); | 195 | spin_lock_bh(&wb->work_lock); |
188 | out_unlock: | 196 | |
197 | if (test_bit(WB_registered, &wb->state)) { | ||
198 | list_add_tail(&work->list, &wb->work_list); | ||
199 | mod_delayed_work(bdi_wq, &wb->dwork, 0); | ||
200 | } else | ||
201 | finish_writeback_work(wb, work); | ||
202 | |||
189 | spin_unlock_bh(&wb->work_lock); | 203 | spin_unlock_bh(&wb->work_lock); |
190 | } | 204 | } |
191 | 205 | ||
@@ -1873,16 +1887,9 @@ static long wb_do_writeback(struct bdi_writeback *wb) | |||
1873 | 1887 | ||
1874 | set_bit(WB_writeback_running, &wb->state); | 1888 | set_bit(WB_writeback_running, &wb->state); |
1875 | while ((work = get_next_work_item(wb)) != NULL) { | 1889 | while ((work = get_next_work_item(wb)) != NULL) { |
1876 | struct wb_completion *done = work->done; | ||
1877 | |||
1878 | trace_writeback_exec(wb, work); | 1890 | trace_writeback_exec(wb, work); |
1879 | |||
1880 | wrote += wb_writeback(wb, work); | 1891 | wrote += wb_writeback(wb, work); |
1881 | 1892 | finish_writeback_work(wb, work); | |
1882 | if (work->auto_free) | ||
1883 | kfree(work); | ||
1884 | if (done && atomic_dec_and_test(&done->cnt)) | ||
1885 | wake_up_all(&wb->bdi->wb_waitq); | ||
1886 | } | 1893 | } |
1887 | 1894 | ||
1888 | /* | 1895 | /* |