aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-01-17 18:34:51 -0500
committerDavid Woodhouse <dwmw2@infradead.org>2007-01-17 18:34:51 -0500
commit9cdf083f981b8d37b3212400a359368661385099 (patch)
treeaa15a6a08ad87e650dea40fb59b3180bef0d345b /kernel/module.c
parente499e01d234a31d59679b7b1e1cf628d917ba49a (diff)
parenta8b3485287731978899ced11f24628c927890e78 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c103
1 files changed, 95 insertions, 8 deletions
diff --git a/kernel/module.c b/kernel/module.c
index f0166563c602..d0f2260a0210 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -34,10 +34,10 @@
34#include <linux/err.h> 34#include <linux/err.h>
35#include <linux/vermagic.h> 35#include <linux/vermagic.h>
36#include <linux/notifier.h> 36#include <linux/notifier.h>
37#include <linux/sched.h>
37#include <linux/stop_machine.h> 38#include <linux/stop_machine.h>
38#include <linux/device.h> 39#include <linux/device.h>
39#include <linux/string.h> 40#include <linux/string.h>
40#include <linux/sched.h>
41#include <linux/mutex.h> 41#include <linux/mutex.h>
42#include <linux/unwind.h> 42#include <linux/unwind.h>
43#include <asm/uaccess.h> 43#include <asm/uaccess.h>
@@ -790,6 +790,19 @@ static struct module_attribute refcnt = {
790 .show = show_refcnt, 790 .show = show_refcnt,
791}; 791};
792 792
793void module_put(struct module *module)
794{
795 if (module) {
796 unsigned int cpu = get_cpu();
797 local_dec(&module->ref[cpu].count);
798 /* Maybe they're waiting for us to drop reference? */
799 if (unlikely(!module_is_live(module)))
800 wake_up_process(module->waiter);
801 put_cpu();
802 }
803}
804EXPORT_SYMBOL(module_put);
805
793#else /* !CONFIG_MODULE_UNLOAD */ 806#else /* !CONFIG_MODULE_UNLOAD */
794static void print_unload_info(struct seq_file *m, struct module *mod) 807static void print_unload_info(struct seq_file *m, struct module *mod)
795{ 808{
@@ -811,9 +824,34 @@ static inline void module_unload_init(struct module *mod)
811} 824}
812#endif /* CONFIG_MODULE_UNLOAD */ 825#endif /* CONFIG_MODULE_UNLOAD */
813 826
827static ssize_t show_initstate(struct module_attribute *mattr,
828 struct module *mod, char *buffer)
829{
830 const char *state = "unknown";
831
832 switch (mod->state) {
833 case MODULE_STATE_LIVE:
834 state = "live";
835 break;
836 case MODULE_STATE_COMING:
837 state = "coming";
838 break;
839 case MODULE_STATE_GOING:
840 state = "going";
841 break;
842 }
843 return sprintf(buffer, "%s\n", state);
844}
845
846static struct module_attribute initstate = {
847 .attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },
848 .show = show_initstate,
849};
850
814static struct module_attribute *modinfo_attrs[] = { 851static struct module_attribute *modinfo_attrs[] = {
815 &modinfo_version, 852 &modinfo_version,
816 &modinfo_srcversion, 853 &modinfo_srcversion,
854 &initstate,
817#ifdef CONFIG_MODULE_UNLOAD 855#ifdef CONFIG_MODULE_UNLOAD
818 &refcnt, 856 &refcnt,
819#endif 857#endif
@@ -1086,22 +1124,37 @@ static int mod_sysfs_setup(struct module *mod,
1086 goto out; 1124 goto out;
1087 kobj_set_kset_s(&mod->mkobj, module_subsys); 1125 kobj_set_kset_s(&mod->mkobj, module_subsys);
1088 mod->mkobj.mod = mod; 1126 mod->mkobj.mod = mod;
1089 err = kobject_register(&mod->mkobj.kobj); 1127
1128 /* delay uevent until full sysfs population */
1129 kobject_init(&mod->mkobj.kobj);
1130 err = kobject_add(&mod->mkobj.kobj);
1090 if (err) 1131 if (err)
1091 goto out; 1132 goto out;
1092 1133
1134 mod->drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers");
1135 if (!mod->drivers_dir) {
1136 err = -ENOMEM;
1137 goto out_unreg;
1138 }
1139
1093 err = module_param_sysfs_setup(mod, kparam, num_params); 1140 err = module_param_sysfs_setup(mod, kparam, num_params);
1094 if (err) 1141 if (err)
1095 goto out_unreg; 1142 goto out_unreg_drivers;
1096 1143
1097 err = module_add_modinfo_attrs(mod); 1144 err = module_add_modinfo_attrs(mod);
1098 if (err) 1145 if (err)
1099 goto out_unreg; 1146 goto out_unreg_param;
1100 1147
1148 kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
1101 return 0; 1149 return 0;
1102 1150
1151out_unreg_param:
1152 module_param_sysfs_remove(mod);
1153out_unreg_drivers:
1154 kobject_unregister(mod->drivers_dir);
1103out_unreg: 1155out_unreg:
1104 kobject_unregister(&mod->mkobj.kobj); 1156 kobject_del(&mod->mkobj.kobj);
1157 kobject_put(&mod->mkobj.kobj);
1105out: 1158out:
1106 return err; 1159 return err;
1107} 1160}
@@ -1110,6 +1163,7 @@ static void mod_kobject_remove(struct module *mod)
1110{ 1163{
1111 module_remove_modinfo_attrs(mod); 1164 module_remove_modinfo_attrs(mod);
1112 module_param_sysfs_remove(mod); 1165 module_param_sysfs_remove(mod);
1166 kobject_unregister(mod->drivers_dir);
1113 1167
1114 kobject_unregister(&mod->mkobj.kobj); 1168 kobject_unregister(&mod->mkobj.kobj);
1115} 1169}
@@ -2182,7 +2236,7 @@ static int m_show(struct seq_file *m, void *p)
2182 Where refcount is a number or -, and deps is a comma-separated list 2236 Where refcount is a number or -, and deps is a comma-separated list
2183 of depends or -. 2237 of depends or -.
2184*/ 2238*/
2185struct seq_operations modules_op = { 2239const struct seq_operations modules_op = {
2186 .start = m_start, 2240 .start = m_start,
2187 .next = m_next, 2241 .next = m_next,
2188 .stop = m_stop, 2242 .stop = m_stop,
@@ -2273,21 +2327,54 @@ void print_modules(void)
2273 printk("\n"); 2327 printk("\n");
2274} 2328}
2275 2329
2330static char *make_driver_name(struct device_driver *drv)
2331{
2332 char *driver_name;
2333
2334 driver_name = kmalloc(strlen(drv->name) + strlen(drv->bus->name) + 2,
2335 GFP_KERNEL);
2336 if (!driver_name)
2337 return NULL;
2338
2339 sprintf(driver_name, "%s:%s", drv->bus->name, drv->name);
2340 return driver_name;
2341}
2342
2276void module_add_driver(struct module *mod, struct device_driver *drv) 2343void module_add_driver(struct module *mod, struct device_driver *drv)
2277{ 2344{
2345 char *driver_name;
2346 int no_warn;
2347
2278 if (!mod || !drv) 2348 if (!mod || !drv)
2279 return; 2349 return;
2280 2350
2281 /* Don't check return code; this call is idempotent */ 2351 /* Don't check return codes; these calls are idempotent */
2282 sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module"); 2352 no_warn = sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module");
2353 driver_name = make_driver_name(drv);
2354 if (driver_name) {
2355 no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj,
2356 driver_name);
2357 kfree(driver_name);
2358 }
2283} 2359}
2284EXPORT_SYMBOL(module_add_driver); 2360EXPORT_SYMBOL(module_add_driver);
2285 2361
2286void module_remove_driver(struct device_driver *drv) 2362void module_remove_driver(struct device_driver *drv)
2287{ 2363{
2364 char *driver_name;
2365
2288 if (!drv) 2366 if (!drv)
2289 return; 2367 return;
2368
2290 sysfs_remove_link(&drv->kobj, "module"); 2369 sysfs_remove_link(&drv->kobj, "module");
2370 if (drv->owner && drv->owner->drivers_dir) {
2371 driver_name = make_driver_name(drv);
2372 if (driver_name) {
2373 sysfs_remove_link(drv->owner->drivers_dir,
2374 driver_name);
2375 kfree(driver_name);
2376 }
2377 }
2291} 2378}
2292EXPORT_SYMBOL(module_remove_driver); 2379EXPORT_SYMBOL(module_remove_driver);
2293 2380