aboutsummaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-02-16 14:53:41 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2006-02-16 14:53:41 -0800
commitba206a6c8edaa741a8d26393b37e037b3d65e862 (patch)
tree2e3a7bdb5b32b273124b2a338117c418b9de9587 /driver
parent371cbd72de3723629c9b9ff10364fbfd73154554 (diff)
downloadpatches-ba206a6c8edaa741a8d26393b37e037b3d65e862.tar.gz
added module reference count sysfs patch
Diffstat (limited to 'driver')
-rw-r--r--driver/module_sysfs_refcount.patch232
1 files changed, 232 insertions, 0 deletions
diff --git a/driver/module_sysfs_refcount.patch b/driver/module_sysfs_refcount.patch
new file mode 100644
index 0000000000000..2f8dd0a7a4278
--- /dev/null
+++ b/driver/module_sysfs_refcount.patch
@@ -0,0 +1,232 @@
+From foo@baz.com Thu Feb 16 07:01:47 2006
+Date: Thu, 16 Feb 2006 13:50:23 -0800
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: fix module sysfs files reference counting
+
+The module files, refcnt, version, and srcversion did not properly
+increment the owner's module reference count, allowing the modules to
+be removed while the files were open, causing oopses.
+
+This patch fixes this, and also fixes the problem that the version and
+srcversion files were not showing up, unless CONFIG_MODULE_UNLOAD was
+enabled, which is not correct.
+
+Cc: Nathan Lynch <ntl@pobox.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/module.h | 1
+ kernel/module.c | 77 +++++++++++++++++++------------------------------
+ kernel/params.c | 10 ------
+ 3 files changed, 32 insertions(+), 56 deletions(-)
+
+--- gregkh-2.6.orig/include/linux/module.h
++++ gregkh-2.6/include/linux/module.h
+@@ -242,6 +242,7 @@ struct module
+ /* Sysfs stuff. */
+ struct module_kobject mkobj;
+ struct module_param_attrs *param_attrs;
++ struct module_attribute *modinfo_attrs;
+ const char *version;
+ const char *srcversion;
+
+--- gregkh-2.6.orig/kernel/module.c
++++ gregkh-2.6/kernel/module.c
+@@ -379,7 +379,6 @@ static inline void percpu_modcopy(void *
+ }
+ #endif /* CONFIG_SMP */
+
+-#ifdef CONFIG_MODULE_UNLOAD
+ #define MODINFO_ATTR(field) \
+ static void setup_modinfo_##field(struct module *mod, const char *s) \
+ { \
+@@ -411,12 +410,7 @@ static struct module_attribute modinfo_#
+ MODINFO_ATTR(version);
+ MODINFO_ATTR(srcversion);
+
+-static struct module_attribute *modinfo_attrs[] = {
+- &modinfo_version,
+- &modinfo_srcversion,
+- NULL,
+-};
+-
++#ifdef CONFIG_MODULE_UNLOAD
+ /* Init the unload section of the module. */
+ static void module_unload_init(struct module *mod)
+ {
+@@ -731,6 +725,15 @@ static inline void module_unload_init(st
+ }
+ #endif /* CONFIG_MODULE_UNLOAD */
+
++static struct module_attribute *modinfo_attrs[] = {
++ &modinfo_version,
++ &modinfo_srcversion,
++#ifdef CONFIG_MODULE_UNLOAD
++ &refcnt,
++#endif
++ NULL,
++};
++
+ #ifdef CONFIG_OBSOLETE_MODPARM
+ /* Bounds checking done below */
+ static int obsparm_copy_string(const char *val, struct kernel_param *kp)
+@@ -1056,37 +1059,28 @@ static inline void remove_sect_attrs(str
+ }
+ #endif /* CONFIG_KALLSYMS */
+
+-
+-#ifdef CONFIG_MODULE_UNLOAD
+-static inline int module_add_refcnt_attr(struct module *mod)
+-{
+- return sysfs_create_file(&mod->mkobj.kobj, &refcnt.attr);
+-}
+-static void module_remove_refcnt_attr(struct module *mod)
+-{
+- return sysfs_remove_file(&mod->mkobj.kobj, &refcnt.attr);
+-}
+-#else
+-static inline int module_add_refcnt_attr(struct module *mod)
+-{
+- return 0;
+-}
+-static void module_remove_refcnt_attr(struct module *mod)
+-{
+-}
+-#endif
+-
+-#ifdef CONFIG_MODULE_UNLOAD
+ static int module_add_modinfo_attrs(struct module *mod)
+ {
+ struct module_attribute *attr;
++ struct module_attribute *temp_attr;
+ int error = 0;
+ int i;
+
++ mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) *
++ (ARRAY_SIZE(modinfo_attrs) + 1)),
++ GFP_KERNEL);
++ if (!mod->modinfo_attrs)
++ return -ENOMEM;
++
++ temp_attr = mod->modinfo_attrs;
+ for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {
+ if (!attr->test ||
+- (attr->test && attr->test(mod)))
+- error = sysfs_create_file(&mod->mkobj.kobj,&attr->attr);
++ (attr->test && attr->test(mod))) {
++ memcpy(temp_attr, attr, sizeof(*temp_attr));
++ temp_attr->attr.owner = mod;
++ error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);
++ ++temp_attr;
++ }
+ }
+ return error;
+ }
+@@ -1096,12 +1090,16 @@ static void module_remove_modinfo_attrs(
+ struct module_attribute *attr;
+ int i;
+
+- for (i = 0; (attr = modinfo_attrs[i]); i++) {
++ for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {
++ /* pick a field to test for end of list */
++ if (!attr->attr.name)
++ break;
+ sysfs_remove_file(&mod->mkobj.kobj,&attr->attr);
+- attr->free(mod);
++ if (attr->free)
++ attr->free(mod);
+ }
++ kfree(mod->modinfo_attrs);
+ }
+-#endif
+
+ static int mod_sysfs_setup(struct module *mod,
+ struct kernel_param *kparam,
+@@ -1119,19 +1117,13 @@ static int mod_sysfs_setup(struct module
+ if (err)
+ goto out;
+
+- err = module_add_refcnt_attr(mod);
+- if (err)
+- goto out_unreg;
+-
+ err = module_param_sysfs_setup(mod, kparam, num_params);
+ if (err)
+ goto out_unreg;
+
+-#ifdef CONFIG_MODULE_UNLOAD
+ err = module_add_modinfo_attrs(mod);
+ if (err)
+ goto out_unreg;
+-#endif
+
+ return 0;
+
+@@ -1143,10 +1135,7 @@ out:
+
+ static void mod_kobject_remove(struct module *mod)
+ {
+-#ifdef CONFIG_MODULE_UNLOAD
+ module_remove_modinfo_attrs(mod);
+-#endif
+- module_remove_refcnt_attr(mod);
+ module_param_sysfs_remove(mod);
+
+ kobject_unregister(&mod->mkobj.kobj);
+@@ -1424,7 +1413,6 @@ static char *get_modinfo(Elf_Shdr *sechd
+ return NULL;
+ }
+
+-#ifdef CONFIG_MODULE_UNLOAD
+ static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
+ unsigned int infoindex)
+ {
+@@ -1439,7 +1427,6 @@ static void setup_modinfo(struct module
+ attr->attr.name));
+ }
+ }
+-#endif
+
+ #ifdef CONFIG_KALLSYMS
+ int is_exported(const char *name, const struct module *mod)
+@@ -1755,10 +1742,8 @@ static struct module *load_module(void _
+ if (strcmp(mod->name, "driverloader") == 0)
+ add_taint(TAINT_PROPRIETARY_MODULE);
+
+-#ifdef CONFIG_MODULE_UNLOAD
+ /* Set up MODINFO_ATTR fields */
+ setup_modinfo(mod, sechdrs, infoindex);
+-#endif
+
+ /* Fix up syms, so that st_value is a pointer to location. */
+ err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
+--- gregkh-2.6.orig/kernel/params.c
++++ gregkh-2.6/kernel/params.c
+@@ -638,13 +638,8 @@ static ssize_t module_attr_show(struct k
+ if (!attribute->show)
+ return -EIO;
+
+- if (!try_module_get(mk->mod))
+- return -ENODEV;
+-
+ ret = attribute->show(attribute, mk->mod, buf);
+
+- module_put(mk->mod);
+-
+ return ret;
+ }
+
+@@ -662,13 +657,8 @@ static ssize_t module_attr_store(struct
+ if (!attribute->store)
+ return -EIO;
+
+- if (!try_module_get(mk->mod))
+- return -ENODEV;
+-
+ ret = attribute->store(attribute, mk->mod, buf, len);
+
+- module_put(mk->mod);
+-
+ return ret;
+ }
+