diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 76 | ||||
-rw-r--r-- | kernel/params.c | 28 |
2 files changed, 79 insertions, 25 deletions
diff --git a/kernel/module.c b/kernel/module.c index d0f2260a0210..8a94e054230c 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -537,6 +537,8 @@ static int already_uses(struct module *a, struct module *b) | |||
537 | static int use_module(struct module *a, struct module *b) | 537 | static int use_module(struct module *a, struct module *b) |
538 | { | 538 | { |
539 | struct module_use *use; | 539 | struct module_use *use; |
540 | int no_warn; | ||
541 | |||
540 | if (b == NULL || already_uses(a, b)) return 1; | 542 | if (b == NULL || already_uses(a, b)) return 1; |
541 | 543 | ||
542 | if (!strong_try_module_get(b)) | 544 | if (!strong_try_module_get(b)) |
@@ -552,6 +554,7 @@ static int use_module(struct module *a, struct module *b) | |||
552 | 554 | ||
553 | use->module_which_uses = a; | 555 | use->module_which_uses = a; |
554 | list_add(&use->list, &b->modules_which_use_me); | 556 | list_add(&use->list, &b->modules_which_use_me); |
557 | no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); | ||
555 | return 1; | 558 | return 1; |
556 | } | 559 | } |
557 | 560 | ||
@@ -569,6 +572,7 @@ static void module_unload_free(struct module *mod) | |||
569 | module_put(i); | 572 | module_put(i); |
570 | list_del(&use->list); | 573 | list_del(&use->list); |
571 | kfree(use); | 574 | kfree(use); |
575 | sysfs_remove_link(i->holders_dir, mod->name); | ||
572 | /* There can be at most one match. */ | 576 | /* There can be at most one match. */ |
573 | break; | 577 | break; |
574 | } | 578 | } |
@@ -1106,9 +1110,7 @@ static void module_remove_modinfo_attrs(struct module *mod) | |||
1106 | kfree(mod->modinfo_attrs); | 1110 | kfree(mod->modinfo_attrs); |
1107 | } | 1111 | } |
1108 | 1112 | ||
1109 | static int mod_sysfs_setup(struct module *mod, | 1113 | static int mod_sysfs_init(struct module *mod) |
1110 | struct kernel_param *kparam, | ||
1111 | unsigned int num_params) | ||
1112 | { | 1114 | { |
1113 | int err; | 1115 | int err; |
1114 | 1116 | ||
@@ -1125,21 +1127,30 @@ static int mod_sysfs_setup(struct module *mod, | |||
1125 | kobj_set_kset_s(&mod->mkobj, module_subsys); | 1127 | kobj_set_kset_s(&mod->mkobj, module_subsys); |
1126 | mod->mkobj.mod = mod; | 1128 | mod->mkobj.mod = mod; |
1127 | 1129 | ||
1128 | /* delay uevent until full sysfs population */ | ||
1129 | kobject_init(&mod->mkobj.kobj); | 1130 | kobject_init(&mod->mkobj.kobj); |
1131 | |||
1132 | out: | ||
1133 | return err; | ||
1134 | } | ||
1135 | |||
1136 | static int mod_sysfs_setup(struct module *mod, | ||
1137 | struct kernel_param *kparam, | ||
1138 | unsigned int num_params) | ||
1139 | { | ||
1140 | int err; | ||
1141 | |||
1142 | /* delay uevent until full sysfs population */ | ||
1130 | err = kobject_add(&mod->mkobj.kobj); | 1143 | err = kobject_add(&mod->mkobj.kobj); |
1131 | if (err) | 1144 | if (err) |
1132 | goto out; | 1145 | goto out; |
1133 | 1146 | ||
1134 | mod->drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers"); | 1147 | mod->holders_dir = kobject_add_dir(&mod->mkobj.kobj, "holders"); |
1135 | if (!mod->drivers_dir) { | 1148 | if (!mod->holders_dir) |
1136 | err = -ENOMEM; | ||
1137 | goto out_unreg; | 1149 | goto out_unreg; |
1138 | } | ||
1139 | 1150 | ||
1140 | err = module_param_sysfs_setup(mod, kparam, num_params); | 1151 | err = module_param_sysfs_setup(mod, kparam, num_params); |
1141 | if (err) | 1152 | if (err) |
1142 | goto out_unreg_drivers; | 1153 | goto out_unreg_holders; |
1143 | 1154 | ||
1144 | err = module_add_modinfo_attrs(mod); | 1155 | err = module_add_modinfo_attrs(mod); |
1145 | if (err) | 1156 | if (err) |
@@ -1150,8 +1161,8 @@ static int mod_sysfs_setup(struct module *mod, | |||
1150 | 1161 | ||
1151 | out_unreg_param: | 1162 | out_unreg_param: |
1152 | module_param_sysfs_remove(mod); | 1163 | module_param_sysfs_remove(mod); |
1153 | out_unreg_drivers: | 1164 | out_unreg_holders: |
1154 | kobject_unregister(mod->drivers_dir); | 1165 | kobject_unregister(mod->holders_dir); |
1155 | out_unreg: | 1166 | out_unreg: |
1156 | kobject_del(&mod->mkobj.kobj); | 1167 | kobject_del(&mod->mkobj.kobj); |
1157 | kobject_put(&mod->mkobj.kobj); | 1168 | kobject_put(&mod->mkobj.kobj); |
@@ -1163,7 +1174,10 @@ static void mod_kobject_remove(struct module *mod) | |||
1163 | { | 1174 | { |
1164 | module_remove_modinfo_attrs(mod); | 1175 | module_remove_modinfo_attrs(mod); |
1165 | module_param_sysfs_remove(mod); | 1176 | module_param_sysfs_remove(mod); |
1166 | kobject_unregister(mod->drivers_dir); | 1177 | if (mod->mkobj.drivers_dir) |
1178 | kobject_unregister(mod->mkobj.drivers_dir); | ||
1179 | if (mod->holders_dir) | ||
1180 | kobject_unregister(mod->holders_dir); | ||
1167 | 1181 | ||
1168 | kobject_unregister(&mod->mkobj.kobj); | 1182 | kobject_unregister(&mod->mkobj.kobj); |
1169 | } | 1183 | } |
@@ -1768,6 +1782,10 @@ static struct module *load_module(void __user *umod, | |||
1768 | /* Now we've moved module, initialize linked lists, etc. */ | 1782 | /* Now we've moved module, initialize linked lists, etc. */ |
1769 | module_unload_init(mod); | 1783 | module_unload_init(mod); |
1770 | 1784 | ||
1785 | /* Initialize kobject, so we can reference it. */ | ||
1786 | if (mod_sysfs_init(mod) != 0) | ||
1787 | goto cleanup; | ||
1788 | |||
1771 | /* Set up license info based on the info section */ | 1789 | /* Set up license info based on the info section */ |
1772 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); | 1790 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); |
1773 | 1791 | ||
@@ -2340,19 +2358,43 @@ static char *make_driver_name(struct device_driver *drv) | |||
2340 | return driver_name; | 2358 | return driver_name; |
2341 | } | 2359 | } |
2342 | 2360 | ||
2361 | static void module_create_drivers_dir(struct module_kobject *mk) | ||
2362 | { | ||
2363 | if (!mk || mk->drivers_dir) | ||
2364 | return; | ||
2365 | |||
2366 | mk->drivers_dir = kobject_add_dir(&mk->kobj, "drivers"); | ||
2367 | } | ||
2368 | |||
2343 | void module_add_driver(struct module *mod, struct device_driver *drv) | 2369 | void module_add_driver(struct module *mod, struct device_driver *drv) |
2344 | { | 2370 | { |
2345 | char *driver_name; | 2371 | char *driver_name; |
2346 | int no_warn; | 2372 | int no_warn; |
2373 | struct module_kobject *mk = NULL; | ||
2374 | |||
2375 | if (!drv) | ||
2376 | return; | ||
2377 | |||
2378 | if (mod) | ||
2379 | mk = &mod->mkobj; | ||
2380 | else if (drv->mod_name) { | ||
2381 | struct kobject *mkobj; | ||
2382 | |||
2383 | /* Lookup built-in module entry in /sys/modules */ | ||
2384 | mkobj = kset_find_obj(&module_subsys.kset, drv->mod_name); | ||
2385 | if (mkobj) | ||
2386 | mk = container_of(mkobj, struct module_kobject, kobj); | ||
2387 | } | ||
2347 | 2388 | ||
2348 | if (!mod || !drv) | 2389 | if (!mk) |
2349 | return; | 2390 | return; |
2350 | 2391 | ||
2351 | /* Don't check return codes; these calls are idempotent */ | 2392 | /* Don't check return codes; these calls are idempotent */ |
2352 | no_warn = sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module"); | 2393 | no_warn = sysfs_create_link(&drv->kobj, &mk->kobj, "module"); |
2353 | driver_name = make_driver_name(drv); | 2394 | driver_name = make_driver_name(drv); |
2354 | if (driver_name) { | 2395 | if (driver_name) { |
2355 | no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj, | 2396 | module_create_drivers_dir(mk); |
2397 | no_warn = sysfs_create_link(mk->drivers_dir, &drv->kobj, | ||
2356 | driver_name); | 2398 | driver_name); |
2357 | kfree(driver_name); | 2399 | kfree(driver_name); |
2358 | } | 2400 | } |
@@ -2367,10 +2409,10 @@ void module_remove_driver(struct device_driver *drv) | |||
2367 | return; | 2409 | return; |
2368 | 2410 | ||
2369 | sysfs_remove_link(&drv->kobj, "module"); | 2411 | sysfs_remove_link(&drv->kobj, "module"); |
2370 | if (drv->owner && drv->owner->drivers_dir) { | 2412 | if (drv->owner && drv->owner->mkobj.drivers_dir) { |
2371 | driver_name = make_driver_name(drv); | 2413 | driver_name = make_driver_name(drv); |
2372 | if (driver_name) { | 2414 | if (driver_name) { |
2373 | sysfs_remove_link(drv->owner->drivers_dir, | 2415 | sysfs_remove_link(drv->owner->mkobj.drivers_dir, |
2374 | driver_name); | 2416 | driver_name); |
2375 | kfree(driver_name); | 2417 | kfree(driver_name); |
2376 | } | 2418 | } |
diff --git a/kernel/params.c b/kernel/params.c index 718945da8f58..553cf7d6a4be 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #define DEBUGP(fmt, a...) | 30 | #define DEBUGP(fmt, a...) |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | static struct kobj_type module_ktype; | ||
34 | |||
33 | static inline char dash2underscore(char c) | 35 | static inline char dash2underscore(char c) |
34 | { | 36 | { |
35 | if (c == '-') | 37 | if (c == '-') |
@@ -561,14 +563,11 @@ static void __init kernel_param_sysfs_setup(const char *name, | |||
561 | mk->mod = THIS_MODULE; | 563 | mk->mod = THIS_MODULE; |
562 | kobj_set_kset_s(mk, module_subsys); | 564 | kobj_set_kset_s(mk, module_subsys); |
563 | kobject_set_name(&mk->kobj, name); | 565 | kobject_set_name(&mk->kobj, name); |
564 | ret = kobject_register(&mk->kobj); | 566 | kobject_init(&mk->kobj); |
567 | ret = kobject_add(&mk->kobj); | ||
565 | BUG_ON(ret < 0); | 568 | BUG_ON(ret < 0); |
566 | 569 | param_sysfs_setup(mk, kparam, num_params, name_skip); | |
567 | /* no need to keep the kobject if no parameter is exported */ | 570 | kobject_uevent(&mk->kobj, KOBJ_ADD); |
568 | if (!param_sysfs_setup(mk, kparam, num_params, name_skip)) { | ||
569 | kobject_unregister(&mk->kobj); | ||
570 | kfree(mk); | ||
571 | } | ||
572 | } | 571 | } |
573 | 572 | ||
574 | /* | 573 | /* |
@@ -674,6 +673,19 @@ static struct sysfs_ops module_sysfs_ops = { | |||
674 | .store = module_attr_store, | 673 | .store = module_attr_store, |
675 | }; | 674 | }; |
676 | 675 | ||
676 | static int uevent_filter(struct kset *kset, struct kobject *kobj) | ||
677 | { | ||
678 | struct kobj_type *ktype = get_ktype(kobj); | ||
679 | |||
680 | if (ktype == &module_ktype) | ||
681 | return 1; | ||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | static struct kset_uevent_ops module_uevent_ops = { | ||
686 | .filter = uevent_filter, | ||
687 | }; | ||
688 | |||
677 | #else | 689 | #else |
678 | static struct sysfs_ops module_sysfs_ops = { | 690 | static struct sysfs_ops module_sysfs_ops = { |
679 | .show = NULL, | 691 | .show = NULL, |
@@ -685,7 +697,7 @@ static struct kobj_type module_ktype = { | |||
685 | .sysfs_ops = &module_sysfs_ops, | 697 | .sysfs_ops = &module_sysfs_ops, |
686 | }; | 698 | }; |
687 | 699 | ||
688 | decl_subsys(module, &module_ktype, NULL); | 700 | decl_subsys(module, &module_ktype, &module_uevent_ops); |
689 | 701 | ||
690 | /* | 702 | /* |
691 | * param_sysfs_init - wrapper for built-in params support | 703 | * param_sysfs_init - wrapper for built-in params support |