Merge master.kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6
[pandora-kernel.git] / block / as-iosched.c
index 66015bc..ef12627 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Anticipatory & deadline i/o scheduler.
  *
- *  Copyright (C) 2002 Jens Axboe <axboe@suse.de>
+ *  Copyright (C) 2002 Jens Axboe <axboe@kernel.dk>
  *                     Nick Piggin <nickpiggin@yahoo.com.au>
  *
  */
@@ -149,7 +149,7 @@ enum arq_state {
 #define RQ_STATE(rq)   ((enum arq_state)(rq)->elevator_private2)
 #define RQ_SET_STATE(rq, state)        ((rq)->elevator_private2 = (void *) state)
 
-static atomic_t ioc_count = ATOMIC_INIT(0);
+static DEFINE_PER_CPU(unsigned long, ioc_count);
 static struct completion *ioc_gone;
 
 static void as_move_to_dispatch(struct as_data *ad, struct request *rq);
@@ -163,7 +163,8 @@ static void as_antic_stop(struct as_data *ad);
 static void free_as_io_context(struct as_io_context *aic)
 {
        kfree(aic);
-       if (atomic_dec_and_test(&ioc_count) && ioc_gone)
+       elv_ioc_count_dec(ioc_count);
+       if (ioc_gone && !elv_ioc_count_read(ioc_count))
                complete(ioc_gone);
 }
 
@@ -199,7 +200,7 @@ static struct as_io_context *alloc_as_io_context(void)
                ret->seek_total = 0;
                ret->seek_samples = 0;
                ret->seek_mean = 0;
-               atomic_inc(&ioc_count);
+               elv_ioc_count_inc(ioc_count);
        }
 
        return ret;
@@ -209,9 +210,9 @@ static struct as_io_context *alloc_as_io_context(void)
  * If the current task has no AS IO context then create one and initialise it.
  * Then take a ref on the task's io context and return it.
  */
-static struct io_context *as_get_io_context(void)
+static struct io_context *as_get_io_context(int node)
 {
-       struct io_context *ioc = get_io_context(GFP_ATOMIC);
+       struct io_context *ioc = get_io_context(GFP_ATOMIC, node);
        if (ioc && !ioc->aic) {
                ioc->aic = alloc_as_io_context();
                if (!ioc->aic) {
@@ -1147,7 +1148,7 @@ static void as_add_request(request_queue_t *q, struct request *rq)
 
        data_dir = rq_is_sync(rq);
 
-       rq->elevator_private = as_get_io_context();
+       rq->elevator_private = as_get_io_context(q->node);
 
        if (RQ_IOC(rq)) {
                as_update_iohist(ad, RQ_IOC(rq)->aic, rq);
@@ -1273,14 +1274,14 @@ static void as_merged_requests(request_queue_t *q, struct request *req,
  *
  * FIXME! dispatch queue is not a queue at all!
  */
-static void as_work_handler(void *data)
+static void as_work_handler(struct work_struct *work)
 {
-       struct request_queue *q = data;
+       struct as_data *ad = container_of(work, struct as_data, antic_work);
+       struct request_queue *q = ad->q;
        unsigned long flags;
 
        spin_lock_irqsave(q->queue_lock, flags);
-       if (!as_queue_empty(q))
-               q->request_fn(q);
+       blk_start_queueing(q);
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
@@ -1291,7 +1292,7 @@ static int as_may_queue(request_queue_t *q, int rw)
        struct io_context *ioc;
        if (ad->antic_status == ANTIC_WAIT_REQ ||
                        ad->antic_status == ANTIC_WAIT_NEXT) {
-               ioc = as_get_io_context();
+               ioc = as_get_io_context(q->node);
                if (ad->io_context == ioc)
                        ret = ELV_MQUEUE_MUST;
                put_io_context(ioc);
@@ -1317,7 +1318,7 @@ static void as_exit_queue(elevator_t *e)
 /*
  * initialize elevator private data (as_data).
  */
-static void *as_init_queue(request_queue_t *q, elevator_t *e)
+static void *as_init_queue(request_queue_t *q)
 {
        struct as_data *ad;
 
@@ -1332,7 +1333,7 @@ static void *as_init_queue(request_queue_t *q, elevator_t *e)
        ad->antic_timer.function = as_antic_timeout;
        ad->antic_timer.data = (unsigned long)q;
        init_timer(&ad->antic_timer);
-       INIT_WORK(&ad->antic_work, as_work_handler, q);
+       INIT_WORK(&ad->antic_work, as_work_handler);
 
        INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]);
        INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
@@ -1461,30 +1462,17 @@ static struct elevator_type iosched_as = {
 
 static int __init as_init(void)
 {
-       int ret;
-
-       ret = elv_register(&iosched_as);
-       if (!ret) {
-               /*
-                * don't allow AS to get unregistered, since we would have
-                * to browse all tasks in the system and release their
-                * as_io_context first
-                */
-               __module_get(THIS_MODULE);
-               return 0;
-       }
-
-       return ret;
+       return elv_register(&iosched_as);
 }
 
 static void __exit as_exit(void)
 {
-       DECLARE_COMPLETION(all_gone);
+       DECLARE_COMPLETION_ONSTACK(all_gone);
        elv_unregister(&iosched_as);
        ioc_gone = &all_gone;
        /* ioc_gone's update must be visible before reading ioc_count */
        smp_wmb();
-       if (atomic_read(&ioc_count))
+       if (elv_ioc_count_read(ioc_count))
                wait_for_completion(ioc_gone);
        synchronize_rcu();
 }