diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-30 13:26:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-30 13:26:20 -0500 |
commit | c6169202e40868fd00de7ce35ee16c81b1f9e123 (patch) | |
tree | de36c7ec8fce13d477bbbbc5942ecf0e1109f60f | |
parent | 866be88a1a313688d94a7708a1f4649af0cdbd97 (diff) | |
parent | c3293a9ac2a4f9160b85b5e986a8e0c54986e7f7 (diff) |
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Pull block fixes from Jens Axboe:
"Make the block layer great again.
Basically three amazing fixes in this pull request, split into 4
patches. Believe me, they should go into 4.4. Two of them fix a
regression, the third and last fixes an easy-to-trigger bug.
- Fix a bad irq enable through null_blk, for queue_mode=1 and using
timer completions. Add a block helper to restart a queue
asynchronously, and use that from null_blk. From me.
- Fix a performance issue in NVMe. Some devices (Intel Pxxxx) expose
a stripe boundary, and performance suffers if we cross it. We took
that into account for merging, but not for the newer splitting
code. Fix from Keith.
- Fix a kernel oops in lightnvm with multiple channels. From Matias"
* 'for-linus' of git://git.kernel.dk/linux-block:
lightnvm: wrong offset in bad blk lun calculation
null_blk: use async queue restart helper
block: add blk_start_queue_async()
block: Split bios on chunk boundaries
-rw-r--r-- | block/blk-core.c | 16 | ||||
-rw-r--r-- | block/blk-merge.c | 2 | ||||
-rw-r--r-- | drivers/block/null_blk.c | 11 | ||||
-rw-r--r-- | drivers/lightnvm/gennvm.c | 2 | ||||
-rw-r--r-- | include/linux/blkdev.h | 1 |
5 files changed, 24 insertions, 8 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index c487b94c59e3..33e2f62d5062 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -207,6 +207,22 @@ void blk_delay_queue(struct request_queue *q, unsigned long msecs) | |||
207 | EXPORT_SYMBOL(blk_delay_queue); | 207 | EXPORT_SYMBOL(blk_delay_queue); |
208 | 208 | ||
209 | /** | 209 | /** |
210 | * blk_start_queue_async - asynchronously restart a previously stopped queue | ||
211 | * @q: The &struct request_queue in question | ||
212 | * | ||
213 | * Description: | ||
214 | * blk_start_queue_async() will clear the stop flag on the queue, and | ||
215 | * ensure that the request_fn for the queue is run from an async | ||
216 | * context. | ||
217 | **/ | ||
218 | void blk_start_queue_async(struct request_queue *q) | ||
219 | { | ||
220 | queue_flag_clear(QUEUE_FLAG_STOPPED, q); | ||
221 | blk_run_queue_async(q); | ||
222 | } | ||
223 | EXPORT_SYMBOL(blk_start_queue_async); | ||
224 | |||
225 | /** | ||
210 | * blk_start_queue - restart a previously stopped queue | 226 | * blk_start_queue - restart a previously stopped queue |
211 | * @q: The &struct request_queue in question | 227 | * @q: The &struct request_queue in question |
212 | * | 228 | * |
diff --git a/block/blk-merge.c b/block/blk-merge.c index e01405a3e8b3..e73846a3d08a 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
@@ -81,7 +81,7 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, | |||
81 | struct bio *new = NULL; | 81 | struct bio *new = NULL; |
82 | 82 | ||
83 | bio_for_each_segment(bv, bio, iter) { | 83 | bio_for_each_segment(bv, bio, iter) { |
84 | if (sectors + (bv.bv_len >> 9) > queue_max_sectors(q)) | 84 | if (sectors + (bv.bv_len >> 9) > blk_max_size_offset(q, bio->bi_iter.bi_sector)) |
85 | goto split; | 85 | goto split; |
86 | 86 | ||
87 | /* | 87 | /* |
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index a428e4ef71fd..09e3c0d87ecc 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c | |||
@@ -232,20 +232,19 @@ static void end_cmd(struct nullb_cmd *cmd) | |||
232 | break; | 232 | break; |
233 | case NULL_Q_BIO: | 233 | case NULL_Q_BIO: |
234 | bio_endio(cmd->bio); | 234 | bio_endio(cmd->bio); |
235 | goto free_cmd; | 235 | break; |
236 | } | 236 | } |
237 | 237 | ||
238 | free_cmd(cmd); | ||
239 | |||
238 | /* Restart queue if needed, as we are freeing a tag */ | 240 | /* Restart queue if needed, as we are freeing a tag */ |
239 | if (q && !q->mq_ops && blk_queue_stopped(q)) { | 241 | if (queue_mode == NULL_Q_RQ && blk_queue_stopped(q)) { |
240 | unsigned long flags; | 242 | unsigned long flags; |
241 | 243 | ||
242 | spin_lock_irqsave(q->queue_lock, flags); | 244 | spin_lock_irqsave(q->queue_lock, flags); |
243 | if (blk_queue_stopped(q)) | 245 | blk_start_queue_async(q); |
244 | blk_start_queue(q); | ||
245 | spin_unlock_irqrestore(q->queue_lock, flags); | 246 | spin_unlock_irqrestore(q->queue_lock, flags); |
246 | } | 247 | } |
247 | free_cmd: | ||
248 | free_cmd(cmd); | ||
249 | } | 248 | } |
250 | 249 | ||
251 | static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) | 250 | static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) |
diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c index f434e89e1c7a..a54b339951a3 100644 --- a/drivers/lightnvm/gennvm.c +++ b/drivers/lightnvm/gennvm.c | |||
@@ -75,7 +75,7 @@ static int gennvm_block_bb(struct ppa_addr ppa, int nr_blocks, u8 *blks, | |||
75 | struct nvm_block *blk; | 75 | struct nvm_block *blk; |
76 | int i; | 76 | int i; |
77 | 77 | ||
78 | lun = &gn->luns[(dev->nr_luns * ppa.g.ch) + ppa.g.lun]; | 78 | lun = &gn->luns[(dev->luns_per_chnl * ppa.g.ch) + ppa.g.lun]; |
79 | 79 | ||
80 | for (i = 0; i < nr_blocks; i++) { | 80 | for (i = 0; i < nr_blocks; i++) { |
81 | if (blks[i] == 0) | 81 | if (blks[i] == 0) |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 0169ba2e2e64..c70e3588a48c 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -797,6 +797,7 @@ extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t, | |||
797 | extern int blk_queue_enter(struct request_queue *q, gfp_t gfp); | 797 | extern int blk_queue_enter(struct request_queue *q, gfp_t gfp); |
798 | extern void blk_queue_exit(struct request_queue *q); | 798 | extern void blk_queue_exit(struct request_queue *q); |
799 | extern void blk_start_queue(struct request_queue *q); | 799 | extern void blk_start_queue(struct request_queue *q); |
800 | extern void blk_start_queue_async(struct request_queue *q); | ||
800 | extern void blk_stop_queue(struct request_queue *q); | 801 | extern void blk_stop_queue(struct request_queue *q); |
801 | extern void blk_sync_queue(struct request_queue *q); | 802 | extern void blk_sync_queue(struct request_queue *q); |
802 | extern void __blk_stop_queue(struct request_queue *q); | 803 | extern void __blk_stop_queue(struct request_queue *q); |