diff options
-rw-r--r-- | include/linux/module.h | 1 | ||||
-rw-r--r-- | kernel/module.c | 37 | ||||
-rw-r--r-- | kernel/params.c | 17 |
3 files changed, 48 insertions, 7 deletions
diff --git a/include/linux/module.h b/include/linux/module.h index 90dc2542978c..419d3ef293dd 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -264,6 +264,7 @@ struct module | |||
264 | struct module_attribute *modinfo_attrs; | 264 | struct module_attribute *modinfo_attrs; |
265 | const char *version; | 265 | const char *version; |
266 | const char *srcversion; | 266 | const char *srcversion; |
267 | struct kobject *holders_dir; | ||
267 | 268 | ||
268 | /* Exported symbols */ | 269 | /* Exported symbols */ |
269 | const struct kernel_symbol *syms; | 270 | const struct kernel_symbol *syms; |
diff --git a/kernel/module.c b/kernel/module.c index 9de4209f6a67..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,15 +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 | ||
1147 | mod->holders_dir = kobject_add_dir(&mod->mkobj.kobj, "holders"); | ||
1148 | if (!mod->holders_dir) | ||
1149 | goto out_unreg; | ||
1150 | |||
1134 | err = module_param_sysfs_setup(mod, kparam, num_params); | 1151 | err = module_param_sysfs_setup(mod, kparam, num_params); |
1135 | if (err) | 1152 | if (err) |
1136 | goto out_unreg_drivers; | 1153 | goto out_unreg_holders; |
1137 | 1154 | ||
1138 | err = module_add_modinfo_attrs(mod); | 1155 | err = module_add_modinfo_attrs(mod); |
1139 | if (err) | 1156 | if (err) |
@@ -1144,7 +1161,9 @@ static int mod_sysfs_setup(struct module *mod, | |||
1144 | 1161 | ||
1145 | out_unreg_param: | 1162 | out_unreg_param: |
1146 | module_param_sysfs_remove(mod); | 1163 | module_param_sysfs_remove(mod); |
1147 | out_unreg_drivers: | 1164 | out_unreg_holders: |
1165 | kobject_unregister(mod->holders_dir); | ||
1166 | out_unreg: | ||
1148 | kobject_del(&mod->mkobj.kobj); | 1167 | kobject_del(&mod->mkobj.kobj); |
1149 | kobject_put(&mod->mkobj.kobj); | 1168 | kobject_put(&mod->mkobj.kobj); |
1150 | out: | 1169 | out: |
@@ -1157,6 +1176,8 @@ static void mod_kobject_remove(struct module *mod) | |||
1157 | module_param_sysfs_remove(mod); | 1176 | module_param_sysfs_remove(mod); |
1158 | if (mod->mkobj.drivers_dir) | 1177 | if (mod->mkobj.drivers_dir) |
1159 | kobject_unregister(mod->mkobj.drivers_dir); | 1178 | kobject_unregister(mod->mkobj.drivers_dir); |
1179 | if (mod->holders_dir) | ||
1180 | kobject_unregister(mod->holders_dir); | ||
1160 | 1181 | ||
1161 | kobject_unregister(&mod->mkobj.kobj); | 1182 | kobject_unregister(&mod->mkobj.kobj); |
1162 | } | 1183 | } |
@@ -1761,6 +1782,10 @@ static struct module *load_module(void __user *umod, | |||
1761 | /* Now we've moved module, initialize linked lists, etc. */ | 1782 | /* Now we've moved module, initialize linked lists, etc. */ |
1762 | module_unload_init(mod); | 1783 | module_unload_init(mod); |
1763 | 1784 | ||
1785 | /* Initialize kobject, so we can reference it. */ | ||
1786 | if (mod_sysfs_init(mod) != 0) | ||
1787 | goto cleanup; | ||
1788 | |||
1764 | /* Set up license info based on the info section */ | 1789 | /* Set up license info based on the info section */ |
1765 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); | 1790 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); |
1766 | 1791 | ||
diff --git a/kernel/params.c b/kernel/params.c index cbaac85942d5..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 == '-') |
@@ -671,6 +673,19 @@ static struct sysfs_ops module_sysfs_ops = { | |||
671 | .store = module_attr_store, | 673 | .store = module_attr_store, |
672 | }; | 674 | }; |
673 | 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 | |||
674 | #else | 689 | #else |
675 | static struct sysfs_ops module_sysfs_ops = { | 690 | static struct sysfs_ops module_sysfs_ops = { |
676 | .show = NULL, | 691 | .show = NULL, |
@@ -682,7 +697,7 @@ static struct kobj_type module_ktype = { | |||
682 | .sysfs_ops = &module_sysfs_ops, | 697 | .sysfs_ops = &module_sysfs_ops, |
683 | }; | 698 | }; |
684 | 699 | ||
685 | decl_subsys(module, &module_ktype, NULL); | 700 | decl_subsys(module, &module_ktype, &module_uevent_ops); |
686 | 701 | ||
687 | /* | 702 | /* |
688 | * param_sysfs_init - wrapper for built-in params support | 703 | * param_sysfs_init - wrapper for built-in params support |