diff options
author | Jens Axboe <axboe@fb.com> | 2015-11-05 18:44:55 +0100 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-11-07 18:40:47 +0100 |
commit | 05229beeddf7e75e2e616ddaad4b70e7fca9528d (patch) | |
tree | 2f8c5efffcdba6f6fd113960da9009979cf679e4 /block/blk-core.c | |
parent | blk-mq: return tag/queue combo in the make_request_fn handlers (diff) | |
download | linux-05229beeddf7e75e2e616ddaad4b70e7fca9528d.tar.xz linux-05229beeddf7e75e2e616ddaad4b70e7fca9528d.zip |
block: add block polling support
Add basic support for polling for specific IO to complete. This uses
the cookie that blk-mq passes back, which enables the block layer
to pass this cookie to the driver to spin for a specific request.
This will be combined with request latency tracking, so we can make
qualified decisions about when to poll and when not to. For now, for
benchmark purposes, we add a sysfs file that controls whether polling
is enabled or not.
Signed-off-by: Jens Axboe <axboe@fb.com>
Acked-by: Christoph Hellwig <hch@lst.de>
Acked-by: Keith Busch <keith.busch@intel.com>
Diffstat (limited to 'block/blk-core.c')
-rw-r--r-- | block/blk-core.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index e93df6d386a0..fa36b4ff7d63 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -3312,6 +3312,47 @@ void blk_finish_plug(struct blk_plug *plug) } EXPORT_SYMBOL(blk_finish_plug); +bool blk_poll(struct request_queue *q, blk_qc_t cookie) +{ + struct blk_plug *plug; + long state; + + if (!q->mq_ops || !q->mq_ops->poll || !blk_qc_t_valid(cookie) || + !test_bit(QUEUE_FLAG_POLL, &q->queue_flags)) + return false; + + plug = current->plug; + if (plug) + blk_flush_plug_list(plug, false); + + state = current->state; + while (!need_resched()) { + unsigned int queue_num = blk_qc_t_to_queue_num(cookie); + struct blk_mq_hw_ctx *hctx = q->queue_hw_ctx[queue_num]; + int ret; + + hctx->poll_invoked++; + + ret = q->mq_ops->poll(hctx, blk_qc_t_to_tag(cookie)); + if (ret > 0) { + hctx->poll_success++; + set_current_state(TASK_RUNNING); + return true; + } + + if (signal_pending_state(state, current)) + set_current_state(TASK_RUNNING); + + if (current->state == TASK_RUNNING) + return true; + if (ret < 0) + break; + cpu_relax(); + } + + return false; +} + #ifdef CONFIG_PM /** * blk_pm_runtime_init - Block layer runtime PM initialization routine |