diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-25 19:48:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-25 19:48:30 -0400 |
commit | 218ce7351413b8287a80fab1d7b94906a5559f01 (patch) | |
tree | 36ba694491fa39fbde719b889a89cadbedd1f357 /kernel/module.c | |
parent | ec96e2fe954c23a54bfdf2673437a39e193a1822 (diff) |
Revert "module: drop the lock while waiting for module to complete initialization."
This reverts commit 480b02df3aa9f07d1c7df0cd8be7a5ca73893455, since
Rafael reports that it causes occasional kernel paging request faults in
load_module().
Dropping the module lock and re-taking it deep in the call-chain is
definitely not the right thing to do. That just turns the mutex from a
lock into a "random non-locking data structure" that doesn't actually
protect what it's supposed to protect.
Requested-and-tested-by: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Brandon Philips <brandon@ifup.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 59 |
1 files changed, 22 insertions, 37 deletions
diff --git a/kernel/module.c b/kernel/module.c index 625985e70e9d..333fbcc96978 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -563,26 +563,33 @@ int use_module(struct module *a, struct module *b) | |||
563 | struct module_use *use; | 563 | struct module_use *use; |
564 | int no_warn, err; | 564 | int no_warn, err; |
565 | 565 | ||
566 | if (b == NULL || already_uses(a, b)) | 566 | if (b == NULL || already_uses(a, b)) return 1; |
567 | return 0; | ||
568 | 567 | ||
569 | /* If we're interrupted or time out, we fail. */ | 568 | /* If we're interrupted or time out, we fail. */ |
570 | err = strong_try_module_get(b); | 569 | if (wait_event_interruptible_timeout( |
570 | module_wq, (err = strong_try_module_get(b)) != -EBUSY, | ||
571 | 30 * HZ) <= 0) { | ||
572 | printk("%s: gave up waiting for init of module %s.\n", | ||
573 | a->name, b->name); | ||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | /* If strong_try_module_get() returned a different error, we fail. */ | ||
571 | if (err) | 578 | if (err) |
572 | return err; | 579 | return 0; |
573 | 580 | ||
574 | DEBUGP("Allocating new usage for %s.\n", a->name); | 581 | DEBUGP("Allocating new usage for %s.\n", a->name); |
575 | use = kmalloc(sizeof(*use), GFP_ATOMIC); | 582 | use = kmalloc(sizeof(*use), GFP_ATOMIC); |
576 | if (!use) { | 583 | if (!use) { |
577 | printk("%s: out of memory loading\n", a->name); | 584 | printk("%s: out of memory loading\n", a->name); |
578 | module_put(b); | 585 | module_put(b); |
579 | return -ENOMEM; | 586 | return 0; |
580 | } | 587 | } |
581 | 588 | ||
582 | use->module_which_uses = a; | 589 | use->module_which_uses = a; |
583 | list_add(&use->list, &b->modules_which_use_me); | 590 | list_add(&use->list, &b->modules_which_use_me); |
584 | no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); | 591 | no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); |
585 | return 0; | 592 | return 1; |
586 | } | 593 | } |
587 | EXPORT_SYMBOL_GPL(use_module); | 594 | EXPORT_SYMBOL_GPL(use_module); |
588 | 595 | ||
@@ -875,7 +882,7 @@ static inline void module_unload_free(struct module *mod) | |||
875 | 882 | ||
876 | int use_module(struct module *a, struct module *b) | 883 | int use_module(struct module *a, struct module *b) |
877 | { | 884 | { |
878 | return strong_try_module_get(b); | 885 | return strong_try_module_get(b) == 0; |
879 | } | 886 | } |
880 | EXPORT_SYMBOL_GPL(use_module); | 887 | EXPORT_SYMBOL_GPL(use_module); |
881 | 888 | ||
@@ -1046,39 +1053,17 @@ static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs, | |||
1046 | struct module *owner; | 1053 | struct module *owner; |
1047 | const struct kernel_symbol *sym; | 1054 | const struct kernel_symbol *sym; |
1048 | const unsigned long *crc; | 1055 | const unsigned long *crc; |
1049 | DEFINE_WAIT(wait); | ||
1050 | int err; | ||
1051 | long timeleft = 30 * HZ; | ||
1052 | 1056 | ||
1053 | again: | ||
1054 | sym = find_symbol(name, &owner, &crc, | 1057 | sym = find_symbol(name, &owner, &crc, |
1055 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); | 1058 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); |
1056 | if (!sym) | 1059 | /* use_module can fail due to OOM, |
1057 | return NULL; | 1060 | or module initialization or unloading */ |
1058 | 1061 | if (sym) { | |
1059 | if (!check_version(sechdrs, versindex, name, mod, crc, owner)) | 1062 | if (!check_version(sechdrs, versindex, name, mod, crc, owner) |
1060 | return NULL; | 1063 | || !use_module(mod, owner)) |
1061 | 1064 | sym = NULL; | |
1062 | prepare_to_wait(&module_wq, &wait, TASK_INTERRUPTIBLE); | 1065 | } |
1063 | err = use_module(mod, owner); | 1066 | return sym; |
1064 | if (likely(!err) || err != -EBUSY || signal_pending(current)) { | ||
1065 | finish_wait(&module_wq, &wait); | ||
1066 | return err ? NULL : sym; | ||
1067 | } | ||
1068 | |||
1069 | /* Module is still loading. Drop lock and wait. */ | ||
1070 | mutex_unlock(&module_mutex); | ||
1071 | timeleft = schedule_timeout(timeleft); | ||
1072 | mutex_lock(&module_mutex); | ||
1073 | finish_wait(&module_wq, &wait); | ||
1074 | |||
1075 | /* Module might be gone entirely, or replaced. Re-lookup. */ | ||
1076 | if (timeleft) | ||
1077 | goto again; | ||
1078 | |||
1079 | printk(KERN_WARNING "%s: gave up waiting for init of module %s.\n", | ||
1080 | mod->name, owner->name); | ||
1081 | return NULL; | ||
1082 | } | 1067 | } |
1083 | 1068 | ||
1084 | /* | 1069 | /* |