summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2005-11-10 18:21:30 +0100
committerJens Axboe <axboe@nelson.home.kernel.dk>2005-11-12 10:56:52 +0100
commit5a7c47eefb31f6b4982add7473ef3e551b058ea4 (patch)
tree6bff2f1ab58080d759c8788680e05359ba0d5f69
parentb740d98f5614e34b4cff2e1e67826f007c8d4f30 (diff)
[BLOCK] noop-iosched: reimplementation of request dispatching
The original implementation directly used dispatch queue. As new generic dispatch queue imposes stricter rules over ioscheds and dispatch queue usage, this direct use becomes somewhat problematic. This patch reimplements noop-iosched such that it complies to generic iosched model better. Request merging with q->last_merge and rq->queuelist.prev/next work again now. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jens Axboe <axboe@suse.de
-rw-r--r--block/noop-iosched.c85
1 files changed, 79 insertions, 6 deletions
diff --git a/block/noop-iosched.c b/block/noop-iosched.c
index e54f006e7e60..f370e4a7fe6d 100644
--- a/block/noop-iosched.c
+++ b/block/noop-iosched.c
@@ -7,21 +7,94 @@
#include <linux/module.h>
#include <linux/init.h>
-static void elevator_noop_add_request(request_queue_t *q, struct request *rq)
+struct noop_data {
+ struct list_head queue;
+};
+
+static void noop_merged_requests(request_queue_t *q, struct request *rq,
+ struct request *next)
+{
+ list_del_init(&next->queuelist);
+}
+
+static int noop_dispatch(request_queue_t *q, int force)
+{
+ struct noop_data *nd = q->elevator->elevator_data;
+
+ if (!list_empty(&nd->queue)) {
+ struct request *rq;
+ rq = list_entry(nd->queue.next, struct request, queuelist);
+ list_del_init(&rq->queuelist);
+ elv_dispatch_sort(q, rq);
+ return 1;
+ }
+ return 0;
+}
+
+static void noop_add_request(request_queue_t *q, struct request *rq)
+{
+ struct noop_data *nd = q->elevator->elevator_data;
+
+ list_add_tail(&rq->queuelist, &nd->queue);
+}
+
+static int noop_queue_empty(request_queue_t *q)
{
- rq->flags |= REQ_NOMERGE;
- elv_dispatch_add_tail(q, rq);
+ struct noop_data *nd = q->elevator->elevator_data;
+
+ return list_empty(&nd->queue);
+}
+
+static struct request *
+noop_former_request(request_queue_t *q, struct request *rq)
+{
+ struct noop_data *nd = q->elevator->elevator_data;
+
+ if (rq->queuelist.prev == &nd->queue)
+ return NULL;
+ return list_entry(rq->queuelist.prev, struct request, queuelist);
+}
+
+static struct request *
+noop_latter_request(request_queue_t *q, struct request *rq)
+{
+ struct noop_data *nd = q->elevator->elevator_data;
+
+ if (rq->queuelist.next == &nd->queue)
+ return NULL;
+ return list_entry(rq->queuelist.next, struct request, queuelist);
}
-static int elevator_noop_dispatch(request_queue_t *q, int force)
+static int noop_init_queue(request_queue_t *q, elevator_t *e)
{
+ struct noop_data *nd;
+
+ nd = kmalloc(sizeof(*nd), GFP_KERNEL);
+ if (!nd)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&nd->queue);
+ e->elevator_data = nd;
return 0;
}
+static void noop_exit_queue(elevator_t *e)
+{
+ struct noop_data *nd = e->elevator_data;
+
+ BUG_ON(!list_empty(&nd->queue));
+ kfree(nd);
+}
+
static struct elevator_type elevator_noop = {
.ops = {
- .elevator_dispatch_fn = elevator_noop_dispatch,
- .elevator_add_req_fn = elevator_noop_add_request,
+ .elevator_merge_req_fn = noop_merged_requests,
+ .elevator_dispatch_fn = noop_dispatch,
+ .elevator_add_req_fn = noop_add_request,
+ .elevator_queue_empty_fn = noop_queue_empty,
+ .elevator_former_req_fn = noop_former_request,
+ .elevator_latter_req_fn = noop_latter_request,
+ .elevator_init_fn = noop_init_queue,
+ .elevator_exit_fn = noop_exit_queue,
},
.elevator_name = "noop",
.elevator_owner = THIS_MODULE,