diff options
| -rw-r--r-- | block/blk-flush.c | 2 | ||||
| -rw-r--r-- | block/blk-mq-tag.c | 48 | ||||
| -rw-r--r-- | block/blk-mq-tag.h | 2 | ||||
| -rw-r--r-- | block/blk-mq.c | 83 | ||||
| -rw-r--r-- | block/blk-mq.h | 45 | ||||
| -rw-r--r-- | drivers/block/mtip32xx/mtip32xx.c | 4 | ||||
| -rw-r--r-- | include/linux/blk-mq.h | 2 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 2 |
8 files changed, 123 insertions, 65 deletions
diff --git a/block/blk-flush.c b/block/blk-flush.c index ff87c664b7df..8ffee4b5f93d 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c | |||
| @@ -225,7 +225,7 @@ static void flush_end_io(struct request *flush_rq, int error) | |||
| 225 | 225 | ||
| 226 | if (q->mq_ops) { | 226 | if (q->mq_ops) { |
| 227 | spin_lock_irqsave(&q->mq_flush_lock, flags); | 227 | spin_lock_irqsave(&q->mq_flush_lock, flags); |
| 228 | q->flush_rq->cmd_flags = 0; | 228 | q->flush_rq->tag = -1; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | running = &q->flush_queue[q->flush_running_idx]; | 231 | running = &q->flush_queue[q->flush_running_idx]; |
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index d90c4aeb7dd3..1aab39f71d95 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c | |||
| @@ -221,8 +221,10 @@ static struct bt_wait_state *bt_wait_ptr(struct blk_mq_bitmap_tags *bt, | |||
| 221 | return bs; | 221 | return bs; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | static int bt_get(struct blk_mq_bitmap_tags *bt, struct blk_mq_hw_ctx *hctx, | 224 | static int bt_get(struct blk_mq_alloc_data *data, |
| 225 | unsigned int *last_tag, gfp_t gfp) | 225 | struct blk_mq_bitmap_tags *bt, |
| 226 | struct blk_mq_hw_ctx *hctx, | ||
| 227 | unsigned int *last_tag) | ||
| 226 | { | 228 | { |
| 227 | struct bt_wait_state *bs; | 229 | struct bt_wait_state *bs; |
| 228 | DEFINE_WAIT(wait); | 230 | DEFINE_WAIT(wait); |
| @@ -232,7 +234,7 @@ static int bt_get(struct blk_mq_bitmap_tags *bt, struct blk_mq_hw_ctx *hctx, | |||
| 232 | if (tag != -1) | 234 | if (tag != -1) |
| 233 | return tag; | 235 | return tag; |
| 234 | 236 | ||
| 235 | if (!(gfp & __GFP_WAIT)) | 237 | if (!(data->gfp & __GFP_WAIT)) |
| 236 | return -1; | 238 | return -1; |
| 237 | 239 | ||
| 238 | bs = bt_wait_ptr(bt, hctx); | 240 | bs = bt_wait_ptr(bt, hctx); |
| @@ -249,50 +251,62 @@ static int bt_get(struct blk_mq_bitmap_tags *bt, struct blk_mq_hw_ctx *hctx, | |||
| 249 | if (was_empty) | 251 | if (was_empty) |
| 250 | atomic_set(&bs->wait_cnt, bt->wake_cnt); | 252 | atomic_set(&bs->wait_cnt, bt->wake_cnt); |
| 251 | 253 | ||
| 254 | blk_mq_put_ctx(data->ctx); | ||
| 255 | |||
| 252 | io_schedule(); | 256 | io_schedule(); |
| 257 | |||
| 258 | data->ctx = blk_mq_get_ctx(data->q); | ||
| 259 | data->hctx = data->q->mq_ops->map_queue(data->q, | ||
| 260 | data->ctx->cpu); | ||
| 261 | if (data->reserved) { | ||
| 262 | bt = &data->hctx->tags->breserved_tags; | ||
| 263 | } else { | ||
| 264 | last_tag = &data->ctx->last_tag; | ||
| 265 | hctx = data->hctx; | ||
| 266 | bt = &hctx->tags->bitmap_tags; | ||
| 267 | } | ||
| 268 | finish_wait(&bs->wait, &wait); | ||
| 269 | bs = bt_wait_ptr(bt, hctx); | ||
| 253 | } while (1); | 270 | } while (1); |
| 254 | 271 | ||
| 255 | finish_wait(&bs->wait, &wait); | 272 | finish_wait(&bs->wait, &wait); |
| 256 | return tag; | 273 | return tag; |
| 257 | } | 274 | } |
| 258 | 275 | ||
| 259 | static unsigned int __blk_mq_get_tag(struct blk_mq_tags *tags, | 276 | static unsigned int __blk_mq_get_tag(struct blk_mq_alloc_data *data) |
| 260 | struct blk_mq_hw_ctx *hctx, | ||
| 261 | unsigned int *last_tag, gfp_t gfp) | ||
| 262 | { | 277 | { |
| 263 | int tag; | 278 | int tag; |
| 264 | 279 | ||
| 265 | tag = bt_get(&tags->bitmap_tags, hctx, last_tag, gfp); | 280 | tag = bt_get(data, &data->hctx->tags->bitmap_tags, data->hctx, |
| 281 | &data->ctx->last_tag); | ||
| 266 | if (tag >= 0) | 282 | if (tag >= 0) |
| 267 | return tag + tags->nr_reserved_tags; | 283 | return tag + data->hctx->tags->nr_reserved_tags; |
| 268 | 284 | ||
| 269 | return BLK_MQ_TAG_FAIL; | 285 | return BLK_MQ_TAG_FAIL; |
| 270 | } | 286 | } |
| 271 | 287 | ||
| 272 | static unsigned int __blk_mq_get_reserved_tag(struct blk_mq_tags *tags, | 288 | static unsigned int __blk_mq_get_reserved_tag(struct blk_mq_alloc_data *data) |
| 273 | gfp_t gfp) | ||
| 274 | { | 289 | { |
| 275 | int tag, zero = 0; | 290 | int tag, zero = 0; |
| 276 | 291 | ||
| 277 | if (unlikely(!tags->nr_reserved_tags)) { | 292 | if (unlikely(!data->hctx->tags->nr_reserved_tags)) { |
| 278 | WARN_ON_ONCE(1); | 293 | WARN_ON_ONCE(1); |
| 279 | return BLK_MQ_TAG_FAIL; | 294 | return BLK_MQ_TAG_FAIL; |
| 280 | } | 295 | } |
| 281 | 296 | ||
| 282 | tag = bt_get(&tags->breserved_tags, NULL, &zero, gfp); | 297 | tag = bt_get(data, &data->hctx->tags->breserved_tags, NULL, &zero); |
| 283 | if (tag < 0) | 298 | if (tag < 0) |
| 284 | return BLK_MQ_TAG_FAIL; | 299 | return BLK_MQ_TAG_FAIL; |
| 285 | 300 | ||
| 286 | return tag; | 301 | return tag; |
| 287 | } | 302 | } |
| 288 | 303 | ||
| 289 | unsigned int blk_mq_get_tag(struct blk_mq_hw_ctx *hctx, unsigned int *last_tag, | 304 | unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data) |
| 290 | gfp_t gfp, bool reserved) | ||
| 291 | { | 305 | { |
| 292 | if (!reserved) | 306 | if (!data->reserved) |
| 293 | return __blk_mq_get_tag(hctx->tags, hctx, last_tag, gfp); | 307 | return __blk_mq_get_tag(data); |
| 294 | 308 | ||
| 295 | return __blk_mq_get_reserved_tag(hctx->tags, gfp); | 309 | return __blk_mq_get_reserved_tag(data); |
| 296 | } | 310 | } |
| 297 | 311 | ||
| 298 | static struct bt_wait_state *bt_wake_ptr(struct blk_mq_bitmap_tags *bt) | 312 | static struct bt_wait_state *bt_wake_ptr(struct blk_mq_bitmap_tags *bt) |
diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h index c959de58d2a5..98696a65d4d4 100644 --- a/block/blk-mq-tag.h +++ b/block/blk-mq-tag.h | |||
| @@ -48,7 +48,7 @@ struct blk_mq_tags { | |||
| 48 | extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, unsigned int reserved_tags, int node); | 48 | extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, unsigned int reserved_tags, int node); |
| 49 | extern void blk_mq_free_tags(struct blk_mq_tags *tags); | 49 | extern void blk_mq_free_tags(struct blk_mq_tags *tags); |
| 50 | 50 | ||
| 51 | extern unsigned int blk_mq_get_tag(struct blk_mq_hw_ctx *hctx, unsigned int *last_tag, gfp_t gfp, bool reserved); | 51 | extern unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data); |
| 52 | extern void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, unsigned int tag, unsigned int *last_tag); | 52 | extern void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, unsigned int tag, unsigned int *last_tag); |
| 53 | extern bool blk_mq_has_free_tags(struct blk_mq_tags *tags); | 53 | extern bool blk_mq_has_free_tags(struct blk_mq_tags *tags); |
| 54 | extern ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page); | 54 | extern ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page); |
diff --git a/block/blk-mq.c b/block/blk-mq.c index 0f5879c42dcd..4e4cd6208052 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
| @@ -33,28 +33,6 @@ static LIST_HEAD(all_q_list); | |||
| 33 | 33 | ||
| 34 | static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx); | 34 | static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx); |
| 35 | 35 | ||
| 36 | static struct blk_mq_ctx *__blk_mq_get_ctx(struct request_queue *q, | ||
| 37 | unsigned int cpu) | ||
| 38 | { | ||
| 39 | return per_cpu_ptr(q->queue_ctx, cpu); | ||
| 40 | } | ||
| 41 | |||
| 42 | /* | ||
| 43 | * This assumes per-cpu software queueing queues. They could be per-node | ||
| 44 | * as well, for instance. For now this is hardcoded as-is. Note that we don't | ||
| 45 | * care about preemption, since we know the ctx's are persistent. This does | ||
| 46 | * mean that we can't rely on ctx always matching the currently running CPU. | ||
| 47 | */ | ||
| 48 | static struct blk_mq_ctx *blk_mq_get_ctx(struct request_queue *q) | ||
| 49 | { | ||
| 50 | return __blk_mq_get_ctx(q, get_cpu()); | ||
| 51 | } | ||
| 52 | |||
| 53 | static void blk_mq_put_ctx(struct blk_mq_ctx *ctx) | ||
| 54 | { | ||
| 55 | put_cpu(); | ||
| 56 | } | ||
| 57 | |||
| 58 | /* | 36 | /* |
| 59 | * Check if any of the ctx's have pending work in this hardware queue | 37 | * Check if any of the ctx's have pending work in this hardware queue |
| 60 | */ | 38 | */ |
| @@ -232,24 +210,23 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx, | |||
| 232 | } | 210 | } |
| 233 | 211 | ||
| 234 | static struct request * | 212 | static struct request * |
| 235 | __blk_mq_alloc_request(struct request_queue *q, struct blk_mq_hw_ctx *hctx, | 213 | __blk_mq_alloc_request(struct blk_mq_alloc_data *data, int rw) |
| 236 | struct blk_mq_ctx *ctx, int rw, gfp_t gfp, bool reserved) | ||
| 237 | { | 214 | { |
| 238 | struct request *rq; | 215 | struct request *rq; |
| 239 | unsigned int tag; | 216 | unsigned int tag; |
| 240 | 217 | ||
| 241 | tag = blk_mq_get_tag(hctx, &ctx->last_tag, gfp, reserved); | 218 | tag = blk_mq_get_tag(data); |
| 242 | if (tag != BLK_MQ_TAG_FAIL) { | ||
