diff options
author | Tatyana Brokhman <tlinder@codeaurora.org> | 2012-12-04 15:54:43 +0200 |
---|---|---|
committer | Pawit Pornkitprasan <p.pawit@gmail.com> | 2013-02-09 14:17:16 +0700 |
commit | ab8ebd66d16b2e79d13ba756d63461e52a0300bc (patch) | |
tree | d4e2e48413223266f997d8571b7703b20ff6a8a5 /block | |
parent | 1ed5a74475ef50b3fff3c0f64fb8b27ff1d6d5e8 (diff) | |
download | kernel_samsung_aries-ab8ebd66d16b2e79d13ba756d63461e52a0300bc.zip kernel_samsung_aries-ab8ebd66d16b2e79d13ba756d63461e52a0300bc.tar.gz kernel_samsung_aries-ab8ebd66d16b2e79d13ba756d63461e52a0300bc.tar.bz2 |
block: Add support for reinsert a dispatched req
Add support for reinserting a dispatched request back to the
scheduler's internal data structures.
This capability is used by the device driver when it chooses to
interrupt the current request transmission and execute another (more
urgent) pending request. For example: interrupting long write in order
to handle pending read. The device driver re-inserts the
remaining write request back to the scheduler, to be rescheduled
for transmission later on.
Add API for verifying whether the current scheduler
supports reinserting requests mechanism. If reinsert mechanism isn't
supported by the scheduler, this code path will never be activated.
Change-Id: I5c982a66b651ebf544aae60063ac8a340d79e67f
Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
Signed-off-by: franciscofranco <franciscofranco.1990@gmail.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-core.c | 44 | ||||
-rw-r--r-- | block/elevator.c | 35 |
2 files changed, 79 insertions, 0 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 35ae52d..160f31d 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -929,6 +929,50 @@ void blk_requeue_request(struct request_queue *q, struct request *rq) } EXPORT_SYMBOL(blk_requeue_request); +/** + * blk_reinsert_request() - Insert a request back to the scheduler + * @q: request queue + * @rq: request to be inserted + * + * This function inserts the request back to the scheduler as if + * it was never dispatched. + * + * Return: 0 on success, error code on fail + */ +int blk_reinsert_request(struct request_queue *q, struct request *rq) +{ + if (unlikely(!rq) || unlikely(!q)) + return -EIO; + + blk_delete_timer(rq); + blk_clear_rq_complete(rq); + trace_block_rq_requeue(q, rq); + + if (blk_rq_tagged(rq)) + blk_queue_end_tag(q, rq); + + BUG_ON(blk_queued_rq(rq)); + + return elv_reinsert_request(q, rq); +} +EXPORT_SYMBOL(blk_reinsert_request); + +/** + * blk_reinsert_req_sup() - check whether the scheduler supports + * reinsertion of requests + * @q: request queue + * + * Returns true if the current scheduler supports reinserting + * request. False otherwise + */ +bool blk_reinsert_req_sup(struct request_queue *q) +{ + if (unlikely(!q)) + return false; + return q->elevator->elevator_type->ops.elevator_reinsert_req_fn ? true : false; +} +EXPORT_SYMBOL(blk_reinsert_req_sup); + static void add_acct_request(struct request_queue *q, struct request *rq, int where) { diff --git a/block/elevator.c b/block/elevator.c index b0b38ce..01075fe 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -606,6 +606,41 @@ void elv_requeue_request(struct request_queue *q, struct request *rq) __elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE); } +/** + * elv_reinsert_request() - Insert a request back to the scheduler + * @q: request queue where request should be inserted + * @rq: request to be inserted + * + * This function returns the request back to the scheduler to be + * inserted as if it was never dispatched + * + * Return: 0 on success, error code on failure + */ +int elv_reinsert_request(struct request_queue *q, struct request *rq) +{ + int res; + + if (!q->elevator->elevator_type->ops.elevator_reinsert_req_fn) + return -EPERM; + + res = q->elevator->elevator_type->ops.elevator_reinsert_req_fn(q, rq); + if (!res) { + /* + * it already went through dequeue, we need to decrement the + * in_flight count again + */ + if (blk_account_rq(rq)) { + q->in_flight[rq_is_sync(rq)]--; + if (rq->cmd_flags & REQ_SORTED) + elv_deactivate_rq(q, rq); + } + rq->cmd_flags &= ~REQ_STARTED; + q->nr_sorted++; + } + + return res; +} + void elv_drain_elevator(struct request_queue *q) { static int printed; |