diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-10 12:26:55 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-10 12:26:55 -0400 |
| commit | dd76a786af1f09e9122e150d30156e094e2a94b4 (patch) | |
| tree | 97ff3d0d45d8df3294d3ec913eec728eb1c2ab57 | |
| parent | e7990d45bb88c2f0565b5ee4c32eefe81653faff (diff) | |
| parent | 360f92c2443073143467a0088daffec96a17910b (diff) | |
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Pull block layer fixes from Jens Axboe:
"A small collection of fixes that should go in before -rc1. The pull
request contains:
- A two patch fix for a regression with block enabled tagging caused
by a commit in the initial pull request. One patch is from Martin
and ensures that SCSI doesn't truncate 64-bit block flags, the
other one is from me and prevents us from double using struct
request queuelist for both completion and busy tags. This caused
anything from a boot crash for some, to crashes under load.
- A blk-mq fix for a potential soft stall when hot unplugging CPUs
with busy IO.
- percpu_counter fix is listed in here, that caused a suspend issue
with virtio-blk due to percpu counters having an inconsistent state
during CPU removal. Andrew sent this in separately a few days ago,
but it's here. JFYI.
- A few fixes for block integrity from Martin.
- A ratelimit fix for loop from Mike Galbraith, to avoid spewing too
much in error cases"
* 'for-linus' of git://git.kernel.dk/linux-block:
block: fix regression with block enabled tagging
scsi: Make sure cmd_flags are 64-bit
block: Ensure we only enable integrity metadata for reads and writes
block: Fix integrity verification
block: Fix for_each_bvec()
drivers/block/loop.c: ratelimit error messages
blk-mq: fix potential stall during CPU unplug with IO pending
percpu_counter: fix bad counter state during suspend
| -rw-r--r-- | block/blk-core.c | 2 | ||||
| -rw-r--r-- | block/blk-mq.c | 8 | ||||
| -rw-r--r-- | block/blk-softirq.c | 17 | ||||
| -rw-r--r-- | block/blk.h | 2 | ||||
| -rw-r--r-- | block/elevator.c | 2 | ||||
| -rw-r--r-- | drivers/block/loop.c | 8 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 4 | ||||
| -rw-r--r-- | fs/bio-integrity.c | 22 | ||||
| -rw-r--r-- | include/linux/bio.h | 6 | ||||
| -rw-r--r-- | include/linux/blk_types.h | 2 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 13 | ||||
| -rw-r--r-- | include/scsi/scsi_device.h | 4 |
12 files changed, 53 insertions, 37 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 34d7c196338b..a0e3096c4bb5 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
| @@ -1307,7 +1307,7 @@ void __blk_put_request(struct request_queue *q, struct request *req) | |||
| 1307 | struct request_list *rl = blk_rq_rl(req); | 1307 | struct request_list *rl = blk_rq_rl(req); |
| 1308 | 1308 | ||
| 1309 | BUG_ON(!list_empty(&req->queuelist)); | 1309 | BUG_ON(!list_empty(&req->queuelist)); |
| 1310 | BUG_ON(!hlist_unhashed(&req->hash)); | 1310 | BUG_ON(ELV_ON_HASH(req)); |
| 1311 | 1311 | ||
| 1312 | blk_free_request(rl, req); | 1312 | blk_free_request(rl, req); |
| 1313 | freed_request(rl, flags); | 1313 | freed_request(rl, flags); |
diff --git a/block/blk-mq.c b/block/blk-mq.c index b1bcc619d0ea..1d2a9bdbee57 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
| @@ -956,6 +956,7 @@ static void blk_mq_hctx_notify(void *data, unsigned long action, | |||
| 956 | unsigned int cpu) | 956 | unsigned int cpu) |
| 957 | { | 957 | { |
| 958 | struct blk_mq_hw_ctx *hctx = data; | 958 | struct blk_mq_hw_ctx *hctx = data; |
| 959 | struct request_queue *q = hctx->queue; | ||
| 959 | struct blk_mq_ctx *ctx; | 960 | struct blk_mq_ctx *ctx; |
| 960 | LIST_HEAD(tmp); | 961 | LIST_HEAD(tmp); |
| 961 | 962 | ||
| @@ -965,7 +966,7 @@ static void blk_mq_hctx_notify(void *data, unsigned long action, | |||
| 965 | /* | 966 | /* |
| 966 | * Move ctx entries to new CPU, if this one is going away. | 967 | * Move ctx entries to new CPU, if this one is going away. |
| 967 | */ | 968 | */ |
| 968 | ctx = __blk_mq_get_ctx(hctx->queue, cpu); | 969 | ctx = __blk_mq_get_ctx(q, cpu); |
| 969 | 970 | ||
| 970 | spin_lock(&ctx->lock); | 971 | spin_lock(&ctx->lock); |
| 971 | if (!list_empty(&ctx->rq_list)) { | 972 | if (!list_empty(&ctx->rq_list)) { |
| @@ -977,7 +978,7 @@ static void blk_mq_hctx_notify(void *data, unsigned long action, | |||
| 977 | if (list_empty(&tmp)) | 978 | if (list_empty(&tmp)) |
| 978 | return; | 979 | return; |
| 979 | 980 | ||
| 980 | ctx = blk_mq_get_ctx(hctx->queue); | 981 | ctx = blk_mq_get_ctx(q); |
| 981 | spin_lock(&ctx->lock); | 982 | spin_lock(&ctx->lock); |
| 982 | 983 | ||
| 983 | while (!list_empty(&tmp)) { | 984 | while (!list_empty(&tmp)) { |
| @@ -988,10 +989,13 @@ static void blk_mq_hctx_notify(void *data, unsigned long action, | |||
| 988 | list_move_tail(&rq->queuelist, &ctx->rq_list); | 989 | list_move_tail(&rq->queuelist, &ctx->rq_list); |
| 989 | } | 990 | } |
| 990 | 991 | ||
| 992 | hctx = q->mq_ops->map_queue(q, ctx->cpu); | ||
| 991 | blk_mq_hctx_mark_pending(hctx, ctx); | 993 | blk_mq_hctx_mark_pending(hctx, ctx); |
| 992 | 994 | ||
| 993 | spin_unlock(&ctx->lock); | 995 | spin_unlock(&ctx->lock); |
| 994 | blk_mq_put_ctx(ctx); | 996 | blk_mq_put_ctx(ctx); |
| 997 | |||
| 998 | blk_mq_run_hw_queue(hctx, true); | ||
| 995 | } | 999 | } |
| 996 | 1000 | ||
| 997 | static int blk_mq_init_hw_commands(struct blk_mq_hw_ctx *hctx, | 1001 | static int blk_mq_init_hw_commands(struct blk_mq_hw_ctx *hctx, |
diff --git a/block/blk-softirq.c b/block/blk-softirq.c index ebd6b6f1bdeb..53b1737e978d 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c | |||
| @@ -30,8 +30,8 @@ static void blk_done_softirq(struct softirq_action *h) | |||
| 30 | while (!list_empty(&local_list)) { | 30 | while (!list_empty(&local_list)) { |
| 31 | struct request *rq; | 31 | struct request *rq; |
| 32 | 32 | ||
| 33 | rq = list_entry(local_list.next, struct request, queuelist); | 33 | rq = list_entry(local_list.next, struct request, ipi_list); |
| 34 | list_del_init(&rq->queuelist); | 34 | list_del_init(&rq->ipi_list); |
| 35 | rq->q->softirq_done_fn(rq); | 35 | rq->q->softirq_done_fn(rq); |
| 36 | } | 36 | } |
| 37 | } | 37 | } |
| @@ -45,14 +45,9 @@ static void trigger_softirq(void *data) | |||
| 45 | 45 | ||
| 46 | local_irq_save(flags); | 46 | local_irq_save(flags); |
| 47 | list = this_cpu_ptr(&blk_cpu_done); | 47 | list = this_cpu_ptr(&blk_cpu_done); |
| 48 | /* | 48 | list_add_tail(&rq->ipi_list, list); |
| 49 | * We reuse queuelist for a list of requests to process. Since the | ||
| 50 | * queuelist is used by the block layer only for requests waiting to be | ||
| 51 | * submitted to the device it is unused now. | ||
| 52 | */ | ||
| 53 | list_add_tail(&rq->queuelist, list); | ||
| 54 | 49 | ||
| 55 | if (list->next == &rq->queuelist) | 50 | if (list->next == &rq->ipi_list) |
| 56 | raise_softirq_irqoff(BLOCK_SOFTIRQ); | 51 | raise_softirq_irqoff(BLOCK_SOFTIRQ); |
| 57 | 52 | ||
| 58 | local_irq_restore(flags); | 53 | local_irq_restore(flags); |
| @@ -141,7 +136,7 @@ void __blk_complete_request(struct request *req) | |||
| 141 | struct list_head *list; | 136 | struct list_head *list; |
| 142 | do_local: | 137 | do_local: |
| 143 | list = this_cpu_ptr(&blk_cpu_done); | 138 | list = this_cpu_ptr(&blk_cpu_done); |
| 144 | list_add_tail(&req->queuelist, list); | 139 | list_add_tail(&req->ipi_list, list); |
| 145 | 140 | ||
| 146 | /* | 141 | /* |
| 147 | * if the list only contains our just added request, | 142 | * if the list only contains our just added request, |
| @@ -149,7 +144,7 @@ do_local: | |||
| 149 | * entries there, someone already raised the irq but it | 144 | * entries there, someone already raised the irq but it |
| 150 | * hasn't run yet. | 145 | * hasn't run yet. |
| 151 | */ | 146 | */ |
| 152 | if (list->next == &req->queuelist) | 147 | if (list->next == &req->ipi_list) |
| 153 | raise_softirq_irqoff(BLOCK_SOFTIRQ); | 148 | raise_softirq_irqoff(BLOCK_SOFTIRQ); |
| 154 | } else if (raise_blk_irq(ccpu, req)) | 149 | } else if (raise_blk_irq(ccpu, req)) |
| 155 | goto do_local; | 150 | goto do_local; |
diff --git a/block/blk.h b/block/blk.h index d23b415b8a28..1d880f1f957f 100644 --- a/block/blk.h +++ b/block/blk.h | |||
| @@ -78,7 +78,7 @@ static inline void blk_clear_rq_complete(struct request *rq) | |||
| 78 | /* | 78 | /* |
| 79 | * Internal elevator interface | 79 | * Internal elevator interface |
| 80 | */ | 80 | */ |
| 81 | #define ELV_ON_HASH(rq) hash_hashed(&(rq)->hash) | 81 | #define ELV_ON_HASH(rq) ((rq)->cmd_flags & REQ_HASHED) |
| 82 | 82 | ||
| 83 | void blk_insert_flush(struct request *rq); | 83 | void blk_insert_flush(struct request *rq); |
| 84 | void blk_abort_flushes(struct request_queue *q); | 84 | void blk_abort_flushes(struct request_queue *q); |
diff --git a/block/elevator.c b/block/elevator.c index 42c45a7d6714..1e01b66a0b92 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
| @@ -247,6 +247,7 @@ EXPORT_SYMBOL(elevator_exit); | |||
| 247 | static inline void __elv_rqhash_del(struct request *rq) | 247 | static inline void __elv_rqhash_del(struct request *rq) |
| 248 | { | 248 | { |
| 249 | hash_del(&rq->hash); | 249 | hash_del(&rq->hash); |
| 250 | rq->cmd_flags &= ~REQ_HASHED; | ||
| 250 | } | 251 | } |
| 251 | 252 | ||
| 252 | static void elv_rqhash_del(struct request_queue *q, struct request *rq) | 253 | static void elv_rqhash_del(struct request_queue *q, struct request *rq) |
| @@ -261,6 +262,7 @@ static void elv_rqhash_add(struct request_queue *q, struct request *rq) | |||
| 261 | 262 | ||
| 262 | BUG_ON(ELV_ON_HASH(rq)); | 263 | BUG_ON(ELV_ON_HASH(rq)); |
| 263 | hash_add(e->hash, &rq->hash, rq_hash_key(rq)); | 264 | hash_add(e->hash, &rq->hash, rq_hash_key(rq)); |
| 265 | rq->cmd_flags |= REQ_HASHED; | ||
| 264 | } | 266 | } |
| 265 | 267 | ||
| 266 | static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) | 268 | static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 66e8c3b94ef3..f70a230a2945 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -237,7 +237,7 @@ static int __do_lo_send_write(struct file *file, | |||
| 237 | file_end_write(file); | 237 | file_end_write(file); |
| 238 | if (likely(bw == len)) | 238 | if (likely(bw == len)) |
| 239 | return 0; | 239 | return 0; |
| 240 | printk(KERN_ERR "loop: Write error at byte offset %llu, length %i.\n", | 240 | printk_ratelimited(KERN_ERR "loop: Write error at byte offset %llu, length %i.\n", |
| 241 | (unsigned long long)pos, len); | 241 | (unsigned long long)pos, len); |
| 242 | if (bw >= 0) | 242 | if (bw >= 0) |
| 243 | bw = -EIO; | 243 | bw = -EIO; |
| @@ -277,7 +277,7 @@ static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec, | |||
| 277 | return __do_lo_send_write(lo->lo_backing_file, | 277 | return __do_lo_send_write(lo->lo_backing_file, |
| 278 | page_address(page), bvec->bv_len, | 278 | page_address(page), bvec->bv_len, |
