diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 63 |
1 files changed, 41 insertions, 22 deletions
diff --git a/kernel/module.c b/kernel/module.c index e2564580f3f1..a8014bfb5a4e 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -77,6 +77,10 @@ | |||
77 | DEFINE_MUTEX(module_mutex); | 77 | DEFINE_MUTEX(module_mutex); |
78 | EXPORT_SYMBOL_GPL(module_mutex); | 78 | EXPORT_SYMBOL_GPL(module_mutex); |
79 | static LIST_HEAD(modules); | 79 | static LIST_HEAD(modules); |
80 | #ifdef CONFIG_KGDB_KDB | ||
81 | struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ | ||
82 | #endif /* CONFIG_KGDB_KDB */ | ||
83 | |||
80 | 84 | ||
81 | /* Block module loading/unloading? */ | 85 | /* Block module loading/unloading? */ |
82 | int modules_disabled = 0; | 86 | int modules_disabled = 0; |
@@ -561,33 +565,26 @@ int use_module(struct module *a, struct module *b) | |||
561 | struct module_use *use; | 565 | struct module_use *use; |
562 | int no_warn, err; | 566 | int no_warn, err; |
563 | 567 | ||
564 | if (b == NULL || already_uses(a, b)) return 1; | 568 | if (b == NULL || already_uses(a, b)) |
565 | |||
566 | /* If we're interrupted or time out, we fail. */ | ||
567 | if (wait_event_interruptible_timeout( | ||
568 | module_wq, (err = strong_try_module_get(b)) != -EBUSY, | ||
569 | 30 * HZ) <= 0) { | ||
570 | printk("%s: gave up waiting for init of module %s.\n", | ||
571 | a->name, b->name); | ||
572 | return 0; | 569 | return 0; |
573 | } | ||
574 | 570 | ||
575 | /* If strong_try_module_get() returned a different error, we fail. */ | 571 | /* If we're interrupted or time out, we fail. */ |
572 | err = strong_try_module_get(b); | ||
576 | if (err) | 573 | if (err) |
577 | return 0; | 574 | return err; |
578 | 575 | ||
579 | DEBUGP("Allocating new usage for %s.\n", a->name); | 576 | DEBUGP("Allocating new usage for %s.\n", a->name); |
580 | use = kmalloc(sizeof(*use), GFP_ATOMIC); | 577 | use = kmalloc(sizeof(*use), GFP_ATOMIC); |
581 | if (!use) { | 578 | if (!use) { |
582 | printk("%s: out of memory loading\n", a->name); | 579 | printk("%s: out of memory loading\n", a->name); |
583 | module_put(b); | 580 | module_put(b); |
584 | return 0; | 581 | return -ENOMEM; |
585 | } | 582 | } |
586 | 583 | ||
587 | use->module_which_uses = a; | 584 | use->module_which_uses = a; |
588 | list_add(&use->list, &b->modules_which_use_me); | 585 | list_add(&use->list, &b->modules_which_use_me); |
589 | no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); | 586 | no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); |
590 | return 1; | 587 | return 0; |
591 | } | 588 | } |
592 | EXPORT_SYMBOL_GPL(use_module); | 589 | EXPORT_SYMBOL_GPL(use_module); |
593 | 590 | ||
@@ -880,7 +877,7 @@ static inline void module_unload_free(struct module *mod) | |||
880 | 877 | ||
881 | int use_module(struct module *a, struct module *b) | 878 | int use_module(struct module *a, struct module *b) |
882 | { | 879 | { |
883 | return strong_try_module_get(b) == 0; | 880 | return strong_try_module_get(b); |
884 | } | 881 | } |
885 | EXPORT_SYMBOL_GPL(use_module); | 882 | EXPORT_SYMBOL_GPL(use_module); |
886 | 883 | ||
@@ -1051,17 +1048,39 @@ static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs, | |||
1051 | struct module *owner; | 1048 | struct module *owner; |
1052 | const struct kernel_symbol *sym; | 1049 | const struct kernel_symbol *sym; |
1053 | const unsigned long *crc; | 1050 | const unsigned long *crc; |
1051 | DEFINE_WAIT(wait); | ||
1052 | int err; | ||
1053 | long timeleft = 30 * HZ; | ||
1054 | 1054 | ||
1055 | again: | ||
1055 | sym = find_symbol(name, &owner, &crc, | 1056 | sym = find_symbol(name, &owner, &crc, |
1056 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); | 1057 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); |
1057 | /* use_module can fail due to OOM, | 1058 | if (!sym) |
1058 | or module initialization or unloading */ | 1059 | return NULL; |
1059 | if (sym) { | 1060 | |
1060 | if (!check_version(sechdrs, versindex, name, mod, crc, owner) | 1061 | if (!check_version(sechdrs, versindex, name, mod, crc, owner)) |
1061 | || !use_module(mod, owner)) | 1062 | return NULL; |
1062 | sym = NULL; | 1063 | |
1064 | prepare_to_wait(&module_wq, &wait, TASK_INTERRUPTIBLE); | ||
1065 | err = use_module(mod, owner); | ||
1066 | if (likely(!err) || err != -EBUSY || signal_pending(current)) { | ||
1067 | finish_wait(&module_wq, &wait); | ||
1068 | return err ? NULL : sym; | ||
1063 | } | 1069 | } |
1064 | return sym; | 1070 | |
1071 | /* Module is still loading. Drop lock and wait. */ | ||
1072 | mutex_unlock(&module_mutex); | ||
1073 | timeleft = schedule_timeout(timeleft); | ||
1074 | mutex_lock(&module_mutex); | ||
1075 | finish_wait(&module_wq, &wait); | ||
1076 | |||
1077 | /* Module might be gone entirely, or replaced. Re-lookup. */ | ||
1078 | if (timeleft) | ||
1079 | goto again; | ||
1080 | |||
1081 | printk(KERN_WARNING "%s: gave up waiting for init of module %s.\n", | ||
1082 | mod->name, owner->name); | ||
1083 | return NULL; | ||
1065 | } | 1084 | } |
1066 | 1085 | ||
1067 | /* | 1086 | /* |
@@ -1182,7 +1201,7 @@ struct module_notes_attrs { | |||
1182 | struct bin_attribute attrs[0]; | 1201 | struct bin_attribute attrs[0]; |
1183 | }; | 1202 | }; |
1184 | 1203 | ||
1185 | static ssize_t module_notes_read(struct kobject *kobj, | 1204 | static ssize_t module_notes_read(struct file *filp, struct kobject *kobj, |
1186 | struct bin_attribute *bin_attr, | 1205 | struct bin_attribute *bin_attr, |
1187 | char *buf, loff_t pos, size_t count) | 1206 | char *buf, loff_t pos, size_t count) |
1188 | { | 1207 | { |