diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-12-05 18:33:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-12-05 18:33:27 -0500 |
commit | 5ee540613db504a10e15fafaf4c08cac96aa1823 (patch) | |
tree | dc0b348debbb557866285dbee51e29ff3496ffa4 /block | |
parent | 29be6345bbaec8502a70c4e2204d5818b48c4e8f (diff) | |
parent | 0d11e6aca396e679c07b2dd6af5dc8b7f041fbbd (diff) |
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Pull block layer fixes from Jens Axboe:
"A small collection of fixes for the current series. It contains:
- A fix for a use-after-free of a request in blk-mq. From Ming Lei
- A fix for a blk-mq bug that could attempt to dereference a NULL rq
if allocation failed
- Two xen-blkfront small fixes
- Cleanup of submit_bio_wait() type uses in the kernel, unifying
that. From Kent
- A fix for 32-bit blkg_rwstat reading. I apologize for this one
looking mangled in the shortlog, it's entirely my fault for missing
an empty line between the description and body of the text"
* 'for-linus' of git://git.kernel.dk/linux-block:
blk-mq: fix use-after-free of request
blk-mq: fix dereference of rq->mq_ctx if allocation fails
block: xen-blkfront: Fix possible NULL ptr dereference
xen-blkfront: Silence pfn maybe-uninitialized warning
block: submit_bio_wait() conversions
Update of blkg_stat and blkg_rwstat may happen in bh context
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-cgroup.h | 8 | ||||
-rw-r--r-- | block/blk-flush.c | 19 | ||||
-rw-r--r-- | block/blk-mq.c | 16 |
3 files changed, 15 insertions, 28 deletions
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 1610b22edf09..86154eab9523 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h | |||
@@ -435,9 +435,9 @@ static inline uint64_t blkg_stat_read(struct blkg_stat *stat) | |||
435 | uint64_t v; | 435 | uint64_t v; |
436 | 436 | ||
437 | do { | 437 | do { |
438 | start = u64_stats_fetch_begin(&stat->syncp); | 438 | start = u64_stats_fetch_begin_bh(&stat->syncp); |
439 | v = stat->cnt; | 439 | v = stat->cnt; |
440 | } while (u64_stats_fetch_retry(&stat->syncp, start)); | 440 | } while (u64_stats_fetch_retry_bh(&stat->syncp, start)); |
441 | 441 | ||
442 | return v; | 442 | return v; |
443 | } | 443 | } |
@@ -508,9 +508,9 @@ static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat) | |||
508 | struct blkg_rwstat tmp; | 508 | struct blkg_rwstat tmp; |
509 | 509 | ||
510 | do { | 510 | do { |
511 | start = u64_stats_fetch_begin(&rwstat->syncp); | 511 | start = u64_stats_fetch_begin_bh(&rwstat->syncp); |
512 | tmp = *rwstat; | 512 | tmp = *rwstat; |
513 | } while (u64_stats_fetch_retry(&rwstat->syncp, start)); | 513 | } while (u64_stats_fetch_retry_bh(&rwstat->syncp, start)); |
514 | 514 | ||
515 | return tmp; | 515 | return tmp; |
516 | } | 516 | } |
diff --git a/block/blk-flush.c b/block/blk-flush.c index 331e627301ea..fb6f3c0ffa49 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c | |||
@@ -502,15 +502,6 @@ void blk_abort_flushes(struct request_queue *q) | |||
502 | } | 502 | } |
503 | } | 503 | } |
504 | 504 | ||
505 | static void bio_end_flush(struct bio *bio, int err) | ||
506 | { | ||
507 | if (err) | ||
508 | clear_bit(BIO_UPTODATE, &bio->bi_flags); | ||
509 | if (bio->bi_private) | ||
510 | complete(bio->bi_private); | ||
511 | bio_put(bio); | ||
512 | } | ||
513 | |||
514 | /** | 505 | /** |
515 | * blkdev_issue_flush - queue a flush | 506 | * blkdev_issue_flush - queue a flush |
516 | * @bdev: blockdev to issue flush for | 507 | * @bdev: blockdev to issue flush for |
@@ -526,7 +517,6 @@ static void bio_end_flush(struct bio *bio, int err) | |||
526 | int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, | 517 | int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, |
527 | sector_t *error_sector) | 518 | sector_t *error_sector) |
528 | { | 519 | { |
529 | DECLARE_COMPLETION_ONSTACK(wait); | ||
530 | struct request_queue *q; | 520 | struct request_queue *q; |
531 | struct bio *bio; | 521 | struct bio *bio; |
532 | int ret = 0; | 522 | int ret = 0; |
@@ -548,13 +538,9 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, | |||
548 | return -ENXIO; | 538 | return -ENXIO; |
549 | 539 | ||
550 | bio = bio_alloc(gfp_mask, 0); | 540 | bio = bio_alloc(gfp_mask, 0); |
551 | bio->bi_end_io = bio_end_flush; | ||
552 | bio->bi_bdev = bdev; | 541 | bio->bi_bdev = bdev; |
553 | bio->bi_private = &wait; | ||
554 | 542 | ||
555 | bio_get(bio); | 543 | ret = submit_bio_wait(WRITE_FLUSH, bio); |
556 | submit_bio(WRITE_FLUSH, bio); | ||
557 | wait_for_completion_io(&wait); | ||
558 | 544 | ||
559 | /* | 545 | /* |
560 | * The driver must store the error location in ->bi_sector, if | 546 | * The driver must store the error location in ->bi_sector, if |
@@ -564,9 +550,6 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, | |||
564 | if (error_sector) | 550 | if (error_sector) |
565 | *error_sector = bio->bi_sector; | 551 | *error_sector = bio->bi_sector; |
566 | 552 | ||
567 | if (!bio_flagged(bio, BIO_UPTODATE)) | ||
568 | ret = -EIO; | ||
569 | |||
570 | bio_put(bio); | 553 | bio_put(bio); |
571 | return ret; | 554 | return ret; |
572 | } | 555 | } |
diff --git a/block/blk-mq.c b/block/blk-mq.c index cdc629cf075b..c79126e11030 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
@@ -202,10 +202,12 @@ static struct request *blk_mq_alloc_request_pinned(struct request_queue *q, | |||
202 | if (rq) { | 202 | if (rq) { |
203 | blk_mq_rq_ctx_init(q, ctx, rq, rw); | 203 | blk_mq_rq_ctx_init(q, ctx, rq, rw); |
204 | break; | 204 | break; |
205 | } else if (!(gfp & __GFP_WAIT)) | 205 | } |
206 | break; | ||
207 | 206 | ||
208 | blk_mq_put_ctx(ctx); | 207 | blk_mq_put_ctx(ctx); |
208 | if (!(gfp & __GFP_WAIT)) | ||
209 | break; | ||
210 | |||
209 | __blk_mq_run_hw_queue(hctx); | 211 | __blk_mq_run_hw_queue(hctx); |
210 | blk_mq_wait_for_tags(hctx->tags); | 212 | blk_mq_wait_for_tags(hctx->tags); |
211 | } while (1); | 213 | } while (1); |
@@ -222,7 +224,8 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw, | |||
222 | return NULL; | 224 | return NULL; |
223 | 225 | ||
224 | rq = blk_mq_alloc_request_pinned(q, rw, gfp, reserved); | 226 | rq = blk_mq_alloc_request_pinned(q, rw, gfp, reserved); |
225 | blk_mq_put_ctx(rq->mq_ctx); | 227 | if (rq) |
228 | blk_mq_put_ctx(rq->mq_ctx); | ||
226 | return rq; | 229 | return rq; |
227 | } | 230 | } |
228 | 231 | ||
@@ -235,7 +238,8 @@ struct request *blk_mq_alloc_reserved_request(struct request_queue *q, int rw, | |||
235 | return NULL; | 238 | return NULL; |
236 | 239 | ||
237 | rq = blk_mq_alloc_request_pinned(q, rw, gfp, true); | 240 | rq = blk_mq_alloc_request_pinned(q, rw, gfp, true); |
238 | blk_mq_put_ctx(rq->mq_ctx); | 241 | if (rq) |
242 | blk_mq_put_ctx(rq->mq_ctx); | ||
239 | return rq; | 243 | return rq; |
240 | } | 244 | } |
241 | EXPORT_SYMBOL(blk_mq_alloc_reserved_request); | 245 | EXPORT_SYMBOL(blk_mq_alloc_reserved_request); |
@@ -308,12 +312,12 @@ void blk_mq_complete_request(struct request *rq, int error) | |||
308 | 312 | ||
309 | blk_account_io_completion(rq, bytes); | 313 | blk_account_io_completion(rq, bytes); |
310 | 314 | ||
315 | blk_account_io_done(rq); | ||
316 | |||
311 | if (rq->end_io) | 317 | if (rq->end_io) |
312 | rq->end_io(rq, error); | 318 | rq->end_io(rq, error); |
313 | else | 319 | else |
314 | blk_mq_free_request(rq); | 320 | blk_mq_free_request(rq); |
315 | |||
316 | blk_account_io_done(rq); | ||
317 | } | 321 | } |
318 | 322 | ||
319 | void __blk_mq_end_io(struct request *rq, int error) | 323 | void __blk_mq_end_io(struct request *rq, int error) |