aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorTatyana Brokhman <tlinder@codeaurora.org>2012-12-04 15:54:43 +0200
committerPawit Pornkitprasan <p.pawit@gmail.com>2013-02-09 14:17:16 +0700
commitab8ebd66d16b2e79d13ba756d63461e52a0300bc (patch)
treed4e2e48413223266f997d8571b7703b20ff6a8a5 /block
parent1ed5a74475ef50b3fff3c0f64fb8b27ff1d6d5e8 (diff)
downloadkernel_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.c44
-rw-r--r--block/elevator.c35
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;