* initialize elevator private data (as_data), and alloc a arq for
  * each request on the free lists
  */
-static int as_init_queue(request_queue_t *q, elevator_t *e)
+static void *as_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct as_data *ad;
        int i;
 
        if (!arq_pool)
-               return -ENOMEM;
+               return NULL;
 
        ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
        if (!ad)
-               return -ENOMEM;
+               return NULL;
        memset(ad, 0, sizeof(*ad));
 
        ad->q = q; /* Identify what queue the data belongs to */
                                GFP_KERNEL, q->node);
        if (!ad->hash) {
                kfree(ad);
-               return -ENOMEM;
+               return NULL;
        }
 
        ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
        if (!ad->arq_pool) {
                kfree(ad->hash);
                kfree(ad);
-               return -ENOMEM;
+               return NULL;
        }
 
        /* anticipatory scheduling helpers */
        ad->antic_expire = default_antic_expire;
        ad->batch_expire[REQ_SYNC] = default_read_batch_expire;
        ad->batch_expire[REQ_ASYNC] = default_write_batch_expire;
-       e->elevator_data = ad;
 
        ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC];
        ad->write_batch_count = ad->batch_expire[REQ_ASYNC] / 10;
        if (ad->write_batch_count < 2)
                ad->write_batch_count = 2;
 
-       return 0;
+       return ad;
 }
 
 /*
 
        kfree(cfqd);
 }
 
-static int cfq_init_queue(request_queue_t *q, elevator_t *e)
+static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct cfq_data *cfqd;
        int i;
 
        cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
        if (!cfqd)
-               return -ENOMEM;
+               return NULL;
 
        memset(cfqd, 0, sizeof(*cfqd));
 
        for (i = 0; i < CFQ_QHASH_ENTRIES; i++)
                INIT_HLIST_HEAD(&cfqd->cfq_hash[i]);
 
-       e->elevator_data = cfqd;
-
        cfqd->queue = q;
 
        cfqd->max_queued = q->nr_requests / 4;
        cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
        cfqd->cfq_slice_idle = cfq_slice_idle;
 
-       return 0;
+       return cfqd;
 out_crqpool:
        kfree(cfqd->cfq_hash);
 out_cfqhash:
        kfree(cfqd->crq_hash);
 out_crqhash:
        kfree(cfqd);
-       return -ENOMEM;
+       return NULL;
 }
 
 static void cfq_slab_kill(void)
 
  * initialize elevator private data (deadline_data), and alloc a drq for
  * each request on the free lists
  */
-static int deadline_init_queue(request_queue_t *q, elevator_t *e)
+static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct deadline_data *dd;
        int i;
 
        if (!drq_pool)
-               return -ENOMEM;
+               return NULL;
 
        dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
        if (!dd)
-               return -ENOMEM;
+               return NULL;
        memset(dd, 0, sizeof(*dd));
 
        dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES,
                                GFP_KERNEL, q->node);
        if (!dd->hash) {
                kfree(dd);
-               return -ENOMEM;
+               return NULL;
        }
 
        dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
        if (!dd->drq_pool) {
                kfree(dd->hash);
                kfree(dd);
-               return -ENOMEM;
+               return NULL;
        }
 
        for (i = 0; i < DL_HASH_ENTRIES; i++)
        dd->writes_starved = writes_starved;
        dd->front_merges = 1;
        dd->fifo_batch = fifo_batch;
-       e->elevator_data = dd;
-       return 0;
+       return dd;
 }
 
 static void deadline_put_request(request_queue_t *q, struct request *rq)
 
        return e;
 }
 
-static int elevator_attach(request_queue_t *q, struct elevator_queue *eq)
+static void *elevator_init_queue(request_queue_t *q, struct elevator_queue *eq)
 {
-       int ret = 0;
+       return eq->ops->elevator_init_fn(q, eq);
+}
 
+static void elevator_attach(request_queue_t *q, struct elevator_queue *eq,
+                          void *data)
+{
        q->elevator = eq;
-
-       if (eq->ops->elevator_init_fn)
-               ret = eq->ops->elevator_init_fn(q, eq);
-
-       return ret;
+       eq->elevator_data = data;
 }
 
 static char chosen_elevator[16];
        struct elevator_type *e = NULL;
        struct elevator_queue *eq;
        int ret = 0;
+       void *data;
 
        INIT_LIST_HEAD(&q->queue_head);
        q->last_merge = NULL;
        if (!eq)
                return -ENOMEM;
 
-       ret = elevator_attach(q, eq);
-       if (ret)
+       data = elevator_init_queue(q, eq);
+       if (!data) {
                kobject_put(&eq->kobj);
+               return -ENOMEM;
+       }
 
+       elevator_attach(q, eq, data);
        return ret;
 }
 
        return error;
 }
 
+static void __elv_unregister_queue(elevator_t *e)
+{
+       kobject_uevent(&e->kobj, KOBJ_REMOVE);
+       kobject_del(&e->kobj);
+}
+
 void elv_unregister_queue(struct request_queue *q)
 {
-       if (q) {
-               elevator_t *e = q->elevator;
-               kobject_uevent(&e->kobj, KOBJ_REMOVE);
-               kobject_del(&e->kobj);
-       }
+       if (q)
+               __elv_unregister_queue(q->elevator);
 }
 
 int elv_register(struct elevator_type *e)
 static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
 {
        elevator_t *old_elevator, *e;
+       void *data;
 
        /*
         * Allocate new elevator
        if (!e)
                return 0;
 
+       data = elevator_init_queue(q, e);
+       if (!data) {
+               kobject_put(&e->kobj);
+               return 0;
+       }
+
        /*
         * Turn on BYPASS and drain all requests w/ elevator private data
         */
                elv_drain_elevator(q);
        }
 
-       spin_unlock_irq(q->queue_lock);
-
        /*
-        * unregister old elevator data
+        * Remember old elevator.
         */
-       elv_unregister_queue(q);
        old_elevator = q->elevator;
 
        /*
         * attach and start new elevator
         */
-       if (elevator_attach(q, e))
-               goto fail;
+       elevator_attach(q, e, data);
+
+       spin_unlock_irq(q->queue_lock);
+
+       __elv_unregister_queue(old_elevator);
 
        if (elv_register_queue(q))
                goto fail_register;
         */
        elevator_exit(e);
        e = NULL;
-fail:
        q->elevator = old_elevator;
        elv_register_queue(q);
        clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
 
        return list_entry(rq->queuelist.next, struct request, queuelist);
 }
 
-static int noop_init_queue(request_queue_t *q, elevator_t *e)
+static void *noop_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct noop_data *nd;
 
        nd = kmalloc(sizeof(*nd), GFP_KERNEL);
        if (!nd)
-               return -ENOMEM;
+               return NULL;
        INIT_LIST_HEAD(&nd->queue);
-       e->elevator_data = nd;
-       return 0;
+       return nd;
 }
 
 static void noop_exit_queue(elevator_t *e)
 
 typedef void (elevator_activate_req_fn) (request_queue_t *, struct request *);
 typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
 
-typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
+typedef void *(elevator_init_fn) (request_queue_t *, elevator_t *);
 typedef void (elevator_exit_fn) (elevator_t *);
 
 struct elevator_ops