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
This commit is contained in:
@@ -100,14 +100,14 @@ static void elevator_put(struct elevator_type *e)
|
||||
module_put(e->elevator_owner);
|
||||
}
|
||||
|
||||
static struct elevator_type *elevator_get(const char *name)
|
||||
static struct elevator_type *elevator_get(const char *name, bool try_loading)
|
||||
{
|
||||
struct elevator_type *e;
|
||||
|
||||
spin_lock(&elv_list_lock);
|
||||
|
||||
e = elevator_find(name);
|
||||
if (!e) {
|
||||
if (!e && try_loading) {
|
||||
spin_unlock(&elv_list_lock);
|
||||
request_module("%s-iosched", name);
|
||||
spin_lock(&elv_list_lock);
|
||||
@@ -136,6 +136,22 @@ static int __init elevator_setup(char *str)
|
||||
|
||||
__setup("elevator=", elevator_setup);
|
||||
|
||||
/* called during boot to load the elevator chosen by the elevator param */
|
||||
void __init load_default_elevator_module(void)
|
||||
{
|
||||
struct elevator_type *e;
|
||||
|
||||
if (!chosen_elevator[0])
|
||||
return;
|
||||
|
||||
spin_lock(&elv_list_lock);
|
||||
e = elevator_find(chosen_elevator);
|
||||
spin_unlock(&elv_list_lock);
|
||||
|
||||
if (!e)
|
||||
request_module("%s-iosched", chosen_elevator);
|
||||
}
|
||||
|
||||
static struct kobj_type elv_ktype;
|
||||
|
||||
static struct elevator_queue *elevator_alloc(struct request_queue *q,
|
||||
@@ -191,25 +207,30 @@ int elevator_init(struct request_queue *q, char *name)
|
||||
q->boundary_rq = NULL;
|
||||
|
||||
if (name) {
|
||||
e = elevator_get(name);
|
||||
e = elevator_get(name, true);
|
||||
if (!e)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the default elevator specified by config boot param or
|
||||
* config option. Don't try to load modules as we could be running
|
||||
* off async and request_module() isn't allowed from async.
|
||||
*/
|
||||
if (!e && *chosen_elevator) {
|
||||
e = elevator_get(chosen_elevator);
|
||||
e = elevator_get(chosen_elevator, false);
|
||||
if (!e)
|
||||
printk(KERN_ERR "I/O scheduler %s not found\n",
|
||||
chosen_elevator);
|
||||
}
|
||||
|
||||
if (!e) {
|
||||
e = elevator_get(CONFIG_DEFAULT_IOSCHED);
|
||||
e = elevator_get(CONFIG_DEFAULT_IOSCHED, false);
|
||||
if (!e) {
|
||||
printk(KERN_ERR
|
||||
"Default I/O scheduler not found. " \
|
||||
"Using noop.\n");
|
||||
e = elevator_get("noop");
|
||||
e = elevator_get("noop", false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -951,7 +972,7 @@ int elevator_change(struct request_queue *q, const char *name)
|
||||
return -ENXIO;
|
||||
|
||||
strlcpy(elevator_name, name, sizeof(elevator_name));
|
||||
e = elevator_get(strstrip(elevator_name));
|
||||
e = elevator_get(strstrip(elevator_name), true);
|
||||
if (!e) {
|
||||
printk(KERN_ERR "elevator: type %s not found\n", elevator_name);
|
||||
return -EINVAL;
|
||||
|
Reference in New Issue
Block a user