aboutsummaryrefslogtreecommitdiffstats
path: root/block/elevator.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/elevator.c')
-rw-r--r--block/elevator.c171
1 files changed, 118 insertions, 53 deletions
diff --git a/block/elevator.c b/block/elevator.c
index 24b702d649a9..db3d0d8296a0 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -120,15 +120,10 @@ static struct elevator_type *elevator_get(const char *name)
120 return e; 120 return e;
121} 121}
122 122
123static int elevator_attach(request_queue_t *q, struct elevator_type *e, 123static int elevator_attach(request_queue_t *q, struct elevator_queue *eq)
124 struct elevator_queue *eq)
125{ 124{
126 int ret = 0; 125 int ret = 0;
127 126
128 memset(eq, 0, sizeof(*eq));
129 eq->ops = &e->ops;
130 eq->elevator_type = e;
131
132 q->elevator = eq; 127 q->elevator = eq;
133 128
134 if (eq->ops->elevator_init_fn) 129 if (eq->ops->elevator_init_fn)
@@ -154,6 +149,32 @@ static int __init elevator_setup(char *str)
154 149
155__setup("elevator=", elevator_setup); 150__setup("elevator=", elevator_setup);
156 151
152static struct kobj_type elv_ktype;
153
154static elevator_t *elevator_alloc(struct elevator_type *e)
155{
156 elevator_t *eq = kmalloc(sizeof(elevator_t), GFP_KERNEL);
157 if (eq) {
158 memset(eq, 0, sizeof(*eq));
159 eq->ops = &e->ops;
160 eq->elevator_type = e;
161 kobject_init(&eq->kobj);
162 snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched");
163 eq->kobj.ktype = &elv_ktype;
164 mutex_init(&eq->sysfs_lock);
165 } else {
166 elevator_put(e);
167 }
168 return eq;
169}
170
171static void elevator_release(struct kobject *kobj)
172{
173 elevator_t *e = container_of(kobj, elevator_t, kobj);
174 elevator_put(e->elevator_type);
175 kfree(e);
176}
177
157int elevator_init(request_queue_t *q, char *name) 178int elevator_init(request_queue_t *q, char *name)
158{ 179{
159 struct elevator_type *e = NULL; 180 struct elevator_type *e = NULL;
@@ -176,29 +197,26 @@ int elevator_init(request_queue_t *q, char *name)
176 e = elevator_get("noop"); 197 e = elevator_get("noop");
177 } 198 }
178 199
179 eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); 200 eq = elevator_alloc(e);
180 if (!eq) { 201 if (!eq)
181 elevator_put(e);
182 return -ENOMEM; 202 return -ENOMEM;
183 }
184 203
185 ret = elevator_attach(q, e, eq); 204 ret = elevator_attach(q, eq);
186 if (ret) { 205 if (ret)
187 kfree(eq); 206 kobject_put(&eq->kobj);
188 elevator_put(e);
189 }
190 207
191 return ret; 208 return ret;
192} 209}
193 210
194void elevator_exit(elevator_t *e) 211void elevator_exit(elevator_t *e)
195{ 212{
213 mutex_lock(&e->sysfs_lock);
196 if (e->ops->elevator_exit_fn) 214 if (e->ops->elevator_exit_fn)
197 e->ops->elevator_exit_fn(e); 215 e->ops->elevator_exit_fn(e);
216 e->ops = NULL;
217 mutex_unlock(&e->sysfs_lock);
198 218
199 elevator_put(e->elevator_type); 219 kobject_put(&e->kobj);
200 e->elevator_type = NULL;
201 kfree(e);
202} 220}
203 221
204/* 222/*
@@ -627,26 +645,79 @@ void elv_completed_request(request_queue_t *q, struct request *rq)
627 } 645 }
628} 646}
629 647
630int elv_register_queue(struct request_queue *q) 648#define to_elv(atr) container_of((atr), struct elv_fs_entry, attr)
649
650static ssize_t
651elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
631{ 652{
632 elevator_t *e = q->elevator; 653 elevator_t *e = container_of(kobj, elevator_t, kobj);
654 struct elv_fs_entry *entry = to_elv(attr);
655 ssize_t error;
633 656
634 e->kobj.parent = kobject_get(&q->kobj); 657 if (!entry->show)
635 if (!e->kobj.parent) 658 return -EIO;
636 return -EBUSY;
637 659
638 snprintf(e->kobj.name, KOBJ_NAME_LEN, "%s", "iosched"); 660 mutex_lock(&e->sysfs_lock);
639 e->kobj.ktype = e->elevator_type->elevator_ktype; 661 error = e->ops ? entry->show(e, page) : -ENOENT;
662 mutex_unlock(&e->sysfs_lock);
663 return error;
664}
665
666static ssize_t
667elv_attr_store(struct kobject *kobj, struct attribute *attr,
668 const char *page, size_t length)
669{
670 elevator_t *e = container_of(kobj, elevator_t, kobj);
671 struct elv_fs_entry *entry = to_elv(attr);
672 ssize_t error;
673
674 if (!entry->store)
675 return -EIO;
676
677 mutex_lock(&e->sysfs_lock);
678 error = e->ops ? entry->store(e, page, length) : -ENOENT;
679 mutex_unlock(&e->sysfs_lock);
680 return error;
681}
682
683static struct sysfs_ops elv_sysfs_ops = {
684 .show = elv_attr_show,
685 .store = elv_attr_store,
686};
687
688static struct kobj_type elv_ktype = {
689 .sysfs_ops = &elv_sysfs_ops,
690 .release = elevator_release,
691};
640 692
641 return kobject_register(&e->kobj); 693int elv_register_queue(struct request_queue *q)
694{
695 elevator_t *e = q->elevator;
696 int error;
697
698 e->kobj.parent = &q->kobj;
699
700 error = kobject_add(&e->kobj);
701 if (!error) {
702 struct elv_fs_entry *attr = e->elevator_type->elevator_attrs;
703 if (attr) {
704 while (attr->attr.name) {
705 if (sysfs_create_file(&e->kobj, &attr->attr))
706 break;
707 attr++;
708 }
709 }
710 kobject_uevent(&e->kobj, KOBJ_ADD);
711 }
712 return error;
642} 713}
643 714
644void elv_unregister_queue(struct request_queue *q) 715void elv_unregister_queue(struct request_queue *q)
645{ 716{
646 if (q) { 717 if (q) {
647 elevator_t *e = q->elevator; 718 elevator_t *e = q->elevator;
648 kobject_unregister(&e->kobj); 719 kobject_uevent(&e->kobj, KOBJ_REMOVE);
649 kobject_put(&q->kobj); 720 kobject_del(&e->kobj);
650 } 721 }
651} 722}
652 723
@@ -675,21 +746,15 @@ void elv_unregister(struct elevator_type *e)
675 /* 746 /*
676 * Iterate every thread in the process to remove the io contexts. 747 * Iterate every thread in the process to remove the io contexts.
677 */ 748 */
678 read_lock(&tasklist_lock); 749 if (e->ops.trim) {
679 do_each_thread(g, p) { 750 read_lock(&tasklist_lock);
680 struct io_context *ioc = p->io_context; 751 do_each_thread(g, p) {
681 if (ioc && ioc->cic) { 752 task_lock(p);
682 ioc->cic->exit(ioc->cic); 753 e->ops.trim(p->io_context);
683 ioc->cic->dtor(ioc->cic); 754 task_unlock(p);
684 ioc->cic = NULL; 755 } while_each_thread(g, p);
685 } 756 read_unlock(&tasklist_lock);
686 if (ioc && ioc->aic) { 757 }
687 ioc->aic->exit(ioc->aic);
688 ioc->aic->dtor(ioc->aic);
689 ioc->aic = NULL;
690 }
691 } while_each_thread(g, p);
692 read_unlock(&tasklist_lock);
693 758
694 spin_lock_irq(&elv_list_lock); 759 spin_lock_irq(&elv_list_lock);
695 list_del_init(&e->list); 760 list_del_init(&e->list);
@@ -703,16 +768,16 @@ EXPORT_SYMBOL_GPL(elv_unregister);
703 * need for the new one. this way we have a chance of going back to the old 768 * need for the new one. this way we have a chance of going back to the old
704 * one, if the new one fails init for some reason. 769 * one, if the new one fails init for some reason.
705 */ 770 */
706static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) 771static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
707{ 772{
708 elevator_t *old_elevator, *e; 773 elevator_t *old_elevator, *e;
709 774
710 /* 775 /*
711 * Allocate new elevator 776 * Allocate new elevator
712 */ 777 */
713 e = kmalloc(sizeof(elevator_t), GFP_KERNEL); 778 e = elevator_alloc(new_e);
714 if (!e) 779 if (!e)
715 goto error; 780 return 0;
716 781
717 /* 782 /*
718 * Turn on BYPASS and drain all requests w/ elevator private data 783 * Turn on BYPASS and drain all requests w/ elevator private data
@@ -743,7 +808,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
743 /* 808 /*
744 * attach and start new elevator 809 * attach and start new elevator
745 */ 810 */
746 if (elevator_attach(q, new_e, e)) 811 if (elevator_attach(q, e))
747 goto fail; 812 goto fail;
748 813
749 if (elv_register_queue(q)) 814 if (elv_register_queue(q))
@@ -754,7 +819,7 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
754 */ 819 */
755 elevator_exit(old_elevator); 820 elevator_exit(old_elevator);
756 clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); 821 clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
757 return; 822 return 1;
758 823
759fail_register: 824fail_register:
760 /* 825 /*
@@ -767,10 +832,9 @@ fail:
767 q->elevator = old_elevator; 832 q->elevator = old_elevator;
768 elv_register_queue(q); 833 elv_register_queue(q);
769 clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); 834 clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
770 kfree(e); 835 if (e)
771error: 836 kobject_put(&e->kobj);
772 elevator_put(new_e); 837 return 0;
773 printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name);
774} 838}
775 839
776ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) 840ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count)
@@ -797,7 +861,8 @@ ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count)
797 return count; 861 return count;
798 } 862 }
799 863
800 elevator_switch(q, e); 864 if (!elevator_switch(q, e))
865 printk(KERN_ERR "elevator: switch to %s failed\n",elevator_name);
801 return count; 866 return count;
802} 867}
803 868