aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-20 01:10:26 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-20 01:10:26 -0500
commitece8e0b2f9c980e5511fe8db2d68c6f1859b9d83 (patch)
tree70f1e3363080884965686576d079d24da8863a58 /block
parent67cb104b4c30bd52292b6a7f526349aab2dd5cbd (diff)
parenta0327ff0eda915be623658babacef706099c11a8 (diff)
Merge branch 'for-3.9-async' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
Pull async changes from Tejun Heo: "These are followups for the earlier deadlock issue involving async ending up waiting for itself through block requesting module[1]. The following changes are made by these commits. - Instead of requesting default elevator on each request_queue init, block now requests it once early during boot. - Kmod triggers warning if invoked from an async worker. - Async synchronization implementation has been reimplemented. It's a lot simpler now." * 'for-3.9-async' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq: async: initialise list heads to fix crash async: replace list of active domains with global list of pending items async: keep pending tasks on async_domain and remove async_pending async: use ULLONG_MAX for infinity cookie value async: bring sanity to the use of words domain and running async, kmod: warn on synchronous request_module() from async workers block: don't request module during elevator init init, block: try to load default elevator module early during boot
Diffstat (limited to 'block')
-rw-r--r--block/elevator.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/block/elevator.c b/block/elevator.c
index 9edba1b8323e..603b2c178740 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -100,14 +100,14 @@ static void elevator_put(struct elevator_type *e)
100 module_put(e->elevator_owner); 100 module_put(e->elevator_owner);
101} 101}
102 102
103static struct elevator_type *elevator_get(const char *name) 103static struct elevator_type *elevator_get(const char *name, bool try_loading)
104{ 104{
105 struct elevator_type *e; 105 struct elevator_type *e;
106 106
107 spin_lock(&elv_list_lock); 107 spin_lock(&elv_list_lock);
108 108
109 e = elevator_find(name); 109 e = elevator_find(name);
110 if (!e) { 110 if (!e && try_loading) {
111 spin_unlock(&elv_list_lock); 111 spin_unlock(&elv_list_lock);
112 request_module("%s-iosched", name); 112 request_module("%s-iosched", name);
113 spin_lock(&elv_list_lock); 113 spin_lock(&elv_list_lock);
@@ -136,6 +136,22 @@ static int __init elevator_setup(char *str)
136 136
137__setup("elevator=", elevator_setup); 137__setup("elevator=", elevator_setup);
138 138
139/* called during boot to load the elevator chosen by the elevator param */
140void __init load_default_elevator_module(void)
141{
142 struct elevator_type *e;
143
144 if (!chosen_elevator[0])
145 return;
146
147 spin_lock(&elv_list_lock);
148 e = elevator_find(chosen_elevator);
149 spin_unlock(&elv_list_lock);
150
151 if (!e)
152 request_module("%s-iosched", chosen_elevator);
153}
154
139static struct kobj_type elv_ktype; 155static struct kobj_type elv_ktype;
140 156
141static struct elevator_queue *elevator_alloc(struct request_queue *q, 157static struct elevator_queue *elevator_alloc(struct request_queue *q,
@@ -191,25 +207,30 @@ int elevator_init(struct request_queue *q, char *name)
191 q->boundary_rq = NULL; 207 q->boundary_rq = NULL;
192 208
193 if (name) { 209 if (name) {
194 e = elevator_get(name); 210 e = elevator_get(name, true);
195 if (!e) 211 if (!e)
196 return -EINVAL; 212 return -EINVAL;
197 } 213 }
198 214
215 /*
216 * Use the default elevator specified by config boot param or
217 * config option. Don't try to load modules as we could be running
218 * off async and request_module() isn't allowed from async.
219 */
199 if (!e && *chosen_elevator) { 220 if (!e && *chosen_elevator) {
200 e = elevator_get(chosen_elevator); 221 e = elevator_get(chosen_elevator, false);
201 if (!e) 222 if (!e)
202 printk(KERN_ERR "I/O scheduler %s not found\n", 223 printk(KERN_ERR "I/O scheduler %s not found\n",
203 chosen_elevator); 224 chosen_elevator);
204 } 225 }
205 226
206 if (!e) { 227 if (!e) {
207 e = elevator_get(CONFIG_DEFAULT_IOSCHED); 228 e = elevator_get(CONFIG_DEFAULT_IOSCHED, false);
208 if (!e) { 229 if (!e) {
209 printk(KERN_ERR 230 printk(KERN_ERR
210 "Default I/O scheduler not found. " \ 231 "Default I/O scheduler not found. " \
211 "Using noop.\n"); 232 "Using noop.\n");
212 e = elevator_get("noop"); 233 e = elevator_get("noop", false);
213 } 234 }
214 } 235 }
215 236
@@ -951,7 +972,7 @@ int elevator_change(struct request_queue *q, const char *name)
951 return -ENXIO; 972 return -ENXIO;
952 973
953 strlcpy(elevator_name, name, sizeof(elevator_name)); 974 strlcpy(elevator_name, name, sizeof(elevator_name));
954 e = elevator_get(strstrip(elevator_name)); 975 e = elevator_get(strstrip(elevator_name), true);
955 if (!e) { 976 if (!e) {
956 printk(KERN_ERR "elevator: type %s not found\n", elevator_name); 977 printk(KERN_ERR "elevator: type %s not found\n", elevator_name);
957 return -EINVAL; 978 return -EINVAL;