diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-14 11:07:02 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-14 11:07:02 -0400 |
| commit | 4a319a490ca59a746b3d36768c0e29ee19832366 (patch) | |
| tree | 41c34e68fdf2477aa9ae40d8c3d77cdec93f568b /block | |
| parent | f0094b28f3038936c1985be64dbe83f0e950b671 (diff) | |
| parent | d97a86c170b4e432f76db072a827fe30b4d6f659 (diff) | |
Merge branch 'for-3.17/core' of git://git.kernel.dk/linux-block
Pull block core bits from Jens Axboe:
"Small round this time, after the massive blk-mq dump for 3.16. This
pull request contains:
- Fixes for max_sectors overflow in ioctls from Akinoby Mita.
- Partition off-by-one bug fix in aix partitions from Dan Carpenter.
- Various small partition cleanups from Fabian Frederick.
- Fix for the block integrity code sometimes returning the wrong
vector count from Gu Zheng.
- Cleanup an re-org of the blk-mq queue enter/exit percpu counters
from Tejun. Dependent on the percpu pull for 3.17 (which was in
the block tree too), that you have already pulled in.
- A blkcg oops fix, also from Tejun"
* 'for-3.17/core' of git://git.kernel.dk/linux-block:
partitions: aix.c: off by one bug
blkcg: don't call into policy draining if root_blkg is already gone
Revert "bio: modify __bio_add_page() to accept pages that don't start a new segment"
bio: modify __bio_add_page() to accept pages that don't start a new segment
block: fix SG_[GS]ET_RESERVED_SIZE ioctl when max_sectors is huge
block: fix BLKSECTGET ioctl when max_sectors is greater than USHRT_MAX
block/partitions/efi.c: kerneldoc fixing
block/partitions/msdos.c: code clean-up
block/partitions/amiga.c: replace nolevel printk by pr_err
block/partitions/aix.c: replace count*size kzalloc by kcalloc
bio-integrity: add "bip_max_vcnt" into struct bio_integrity_payload
blk-mq: use percpu_ref for mq usage count
blk-mq: collapse __blk_mq_drain_queue() into blk_mq_freeze_queue()
blk-mq: decouble blk-mq freezing from generic bypassing
block, blk-mq: draining can't be skipped even if bypass_depth was non-zero
blk-mq: fix a memory ordering bug in blk_mq_queue_enter()
Diffstat (limited to 'block')
| -rw-r--r-- | block/bio-integrity.c | 12 | ||||
| -rw-r--r-- | block/blk-core.c | 13 | ||||
| -rw-r--r-- | block/blk-mq.c | 81 | ||||
| -rw-r--r-- | block/blk-mq.h | 2 | ||||
| -rw-r--r-- | block/blk-sysfs.c | 2 | ||||
| -rw-r--r-- | block/compat_ioctl.c | 6 | ||||
| -rw-r--r-- | block/ioctl.c | 5 | ||||
| -rw-r--r-- | block/partitions/aix.c | 4 | ||||
| -rw-r--r-- | block/partitions/amiga.c | 12 | ||||
| -rw-r--r-- | block/partitions/efi.c | 46 | ||||
| -rw-r--r-- | block/partitions/msdos.c | 13 | ||||
| -rw-r--r-- | block/scsi_ioctl.c | 15 |
12 files changed, 102 insertions, 109 deletions
diff --git a/block/bio-integrity.c b/block/bio-integrity.c index 9e241063a616..bc423f7b02da 100644 --- a/block/bio-integrity.c +++ b/block/bio-integrity.c | |||
| @@ -70,8 +70,10 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio, | |||
| 70 | bs->bvec_integrity_pool); | 70 | bs->bvec_integrity_pool); |
| 71 | if (!bip->bip_vec) | 71 | if (!bip->bip_vec) |
| 72 | goto err; | 72 | goto err; |
| 73 | bip->bip_max_vcnt = bvec_nr_vecs(idx); | ||
| 73 | } else { | 74 | } else { |
| 74 | bip->bip_vec = bip->bip_inline_vecs; | 75 | bip->bip_vec = bip->bip_inline_vecs; |
| 76 | bip->bip_max_vcnt = inline_vecs; | ||
| 75 | } | 77 | } |
| 76 | 78 | ||
| 77 | bip->bip_slab = idx; | 79 | bip->bip_slab = idx; |
| @@ -114,14 +116,6 @@ void bio_integrity_free(struct bio *bio) | |||
| 114 | } | 116 | } |
| 115 | EXPORT_SYMBOL(bio_integrity_free); | 117 | EXPORT_SYMBOL(bio_integrity_free); |
| 116 | 118 | ||
| 117 | static inline unsigned int bip_integrity_vecs(struct bio_integrity_payload *bip) | ||
| 118 | { | ||
| 119 | if (bip->bip_slab == BIO_POOL_NONE) | ||
| 120 | return BIP_INLINE_VECS; | ||
| 121 | |||
| 122 | return bvec_nr_vecs(bip->bip_slab); | ||
| 123 | } | ||
| 124 | |||
| 125 | /** | 119 | /** |
| 126 | * bio_integrity_add_page - Attach integrity metadata | 120 | * bio_integrity_add_page - Attach integrity metadata |
| 127 | * @bio: bio to update | 121 | * @bio: bio to update |
| @@ -137,7 +131,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, | |||
| 137 | struct bio_integrity_payload *bip = bio->bi_integrity; | 131 | struct bio_integrity_payload *bip = bio->bi_integrity; |
| 138 | struct bio_vec *iv; | 132 | struct bio_vec *iv; |
| 139 | 133 | ||
| 140 | if (bip->bip_vcnt >= bip_integrity_vecs(bip)) { | 134 | if (bip->bip_vcnt >= bip->bip_max_vcnt) { |
| 141 | printk(KERN_ERR "%s: bip_vec full\n", __func__); | 135 | printk(KERN_ERR "%s: bip_vec full\n", __func__); |
| 142 | return 0; | 136 | return 0; |
| 143 | } | 137 | } |
diff --git a/block/blk-core.c b/block/blk-core.c index 6f8dba161bfe..c359d72e9d76 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
| @@ -438,14 +438,17 @@ static void __blk_drain_queue(struct request_queue *q, bool drain_all) | |||
| 438 | */ | 438 | */ |
| 439 | void blk_queue_bypass_start(struct request_queue *q) | 439 | void blk_queue_bypass_start(struct request_queue *q) |
| 440 | { | 440 | { |
| 441 | bool drain; | ||
| 442 | |||
| 443 | spin_lock_irq(q->queue_lock); | 441 | spin_lock_irq(q->queue_lock); |
| 444 | drain = !q->bypass_depth++; | 442 | q->bypass_depth++; |
| 445 | queue_flag_set(QUEUE_FLAG_BYPASS, q); | 443 | queue_flag_set(QUEUE_FLAG_BYPASS, q); |
| 446 | spin_unlock_irq(q->queue_lock); | 444 | spin_unlock_irq(q->queue_lock); |
| 447 | 445 | ||
| 448 | if (drain) { | 446 | /* |
| 447 | * Queues start drained. Skip actual draining till init is | ||
| 448 | * complete. This avoids lenghty delays during queue init which | ||
| 449 | * can happen many times during boot. | ||
| 450 | */ | ||
| 451 | if (blk_queue_init_done(q)) { | ||
| 449 | spin_lock_irq(q->queue_lock); | 452 | spin_lock_irq(q->queue_lock); |
| 450 | __blk_drain_queue(q, false); | 453 | __blk_drain_queue(q, false); |
| 451 | spin_unlock_irq(q->queue_lock); | 454 | spin_unlock_irq(q->queue_lock); |
| @@ -511,7 +514,7 @@ void blk_cleanup_queue(struct request_queue *q) | |||
| 511 | * prevent that q->request_fn() gets invoked after draining finished. | 514 | * prevent that q->request_fn() gets invoked after draining finished. |
| 512 | */ | 515 | */ |
| 513 | if (q->mq_ops) { | 516 | if (q->mq_ops) { |
| 514 | blk_mq_drain_queue(q); | 517 | blk_mq_freeze_queue(q); |
| 515 | spin_lock_irq(lock); | 518 | spin_lock_irq(lock); |
| 516 | } else { | 519 | } else { |
| 517 | spin_lock_irq(lock); | 520 | spin_lock_irq(lock); |
diff --git a/block/blk-mq.c b/block/blk-mq.c index ad69ef657e85..5189cb1e478a 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
| @@ -78,68 +78,47 @@ static void blk_mq_hctx_clear_pending(struct blk_mq_hw_ctx *hctx, | |||
| 78 | 78 | ||
| 79 | static int blk_mq_queue_enter(struct request_queue *q) | 79 | static int blk_mq_queue_enter(struct request_queue *q) |
| 80 | { | 80 | { |
| 81 | int ret; | 81 | while (true) { |
| 82 | 82 | int ret; | |
| 83 | __percpu_counter_add(&q->mq_usage_counter, 1, 1000000); | ||
| 84 | smp_wmb(); | ||
| 85 | |||
| 86 | /* we have problems freezing the queue if it's initializing */ | ||
| 87 | if (!blk_queue_dying(q) && | ||
| 88 | (!blk_queue_bypass(q) || !blk_queue_init_done(q))) | ||
| 89 | return 0; | ||
| 90 | |||
| 91 | __percpu_counter_add(&q->mq_usage_counter, -1, 1000000); | ||
| 92 | 83 | ||
| 93 | spin_lock_irq(q->queue_lock); | 84 | if (percpu_ref_tryget_live(&q->mq_usage_counter)) |
| 94 | ret = wait_event_interruptible_lock_irq(q->mq_freeze_wq, | 85 | return 0; |
| 95 | !blk_queue_bypass(q) || blk_queue_dying(q), | ||
| 96 | *q->queue_lock); | ||
| 97 | /* inc usage with lock hold to avoid freeze_queue runs here */ | ||
| 98 | if (!ret && !blk_queue_dying(q)) | ||
| 99 | __percpu_counter_add(&q->mq_usage_counter, 1, 1000000); | ||
| 100 | else if (blk_queue_dying(q)) | ||
| 101 | ret = -ENODEV; | ||
| 102 | spin_unlock_irq(q->queue_lock); | ||
| 103 | 86 | ||
| 104 | return ret; | 87 | ret = wait_event_interruptible(q->mq_freeze_wq, |
| 88 | !q->mq_freeze_depth || blk_queue_dying(q)); | ||
| 89 | if (blk_queue_dying(q)) | ||
| 90 | return -ENODEV; | ||
| 91 | if (ret) | ||
| 92 | return ret; | ||
| 93 | } | ||
| 105 | } | 94 | } |
| 106 | 95 | ||
| 107 | static void blk_mq_queue_exit(struct request_queue *q) | 96 | static void blk_mq_queue_exit(struct request_queue *q) |
| 108 | { | 97 | { |
| 109 | __percpu_counter_add(&q->mq_usage_counter, -1, 1000000); | 98 | percpu_ref_put(&q->mq_usage_counter); |
| 110 | } | 99 | } |
| 111 | 100 | ||
| 112 | void blk_mq_drain_queue(struct request_queue *q) | 101 | static void blk_mq_usage_counter_release(struct percpu_ref *ref) |
| 113 | { | 102 | { |
| 114 | while (true) { | 103 | struct request_queue *q = |
| 115 | s64 count; | 104 | container_of(ref, struct request_queue, mq_usage_counter); |
| 116 | |||
| 117 | spin_lock_irq(q->queue_lock); | ||
| 118 | count = percpu_counter_sum(&q->mq_usage_counter); | ||
| 119 | spin_unlock_irq(q->queue_lock); | ||
| 120 | 105 | ||
| 121 | if (count == 0) | 106 | wake_up_all(&q->mq_freeze_wq); |
| 122 | break; | ||
| 123 | blk_mq_start_hw_queues(q); | ||
| 124 | msleep(10); | ||
| 125 | } | ||
| 126 | } | 107 | } |
| 127 | 108 | ||
| 128 | /* | 109 | /* |
| 129 | * Guarantee no request is in use, so we can change any data structure of | 110 | * Guarantee no request is in use, so we can change any data structure of |
| 130 | * the queue afterward. | 111 | * the queue afterward. |
| 131 | */ | 112 | */ |
| 132 | static void blk_mq_freeze_queue(struct request_queue *q) | 113 | void blk_mq_freeze_queue(struct request_queue *q) |
| 133 | { | 114 | { |
| 134 | bool drain; | ||
| 135 | |||
| 136 | spin_lock_irq(q->queue_lock); | 115 | spin_lock_irq(q->queue_lock); |
| 137 | drain = !q->bypass_depth++; | 116 | q->mq_freeze_depth++; |
| 138 | queue_flag_set(QUEUE_FLAG_BYPASS, q); | ||
| 139 | spin_unlock_irq(q->queue_lock); | 117 | spin_unlock_irq(q->queue_lock); |
| 140 | 118 | ||
