From 27beaee60b98133c0a677932e139afa0fbed9f67 Mon Sep 17 00:00:00 2001 From: Denis Cheng Date: Fri, 18 Jan 2008 14:29:30 +0800 Subject: [PATCH] [module system]: put all modules under /sys/module no matter whether built-in under /sys/module Index: linux-2.6.24-rc8/include/asm-generic/vmlinux.lds.h =================================================================== --- include/asm-generic/vmlinux.lds.h | 7 ++ include/linux/moduleparam.h | 15 +++- kernel/module.c | 166 ++++++++++++++++++++++++++++++++++++- 3 files changed, 184 insertions(+), 4 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 9f584cc..896f0fe 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -137,6 +137,13 @@ VMLINUX_SYMBOL(__start___param) = .; \ *(__param) \ VMLINUX_SYMBOL(__stop___param) = .; \ + } \ + \ + /* Built-in module information. */ \ + .modinfo : AT(ADDR(.modinfo) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start___modinfo) = .; \ + *(.modinfo) \ + VMLINUX_SYMBOL(__stop___modinfo) = .; \ VMLINUX_SYMBOL(__end_rodata) = .; \ } \ \ diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 13410b2..aaed3b0 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -13,16 +13,27 @@ #define MODULE_PARAM_PREFIX KBUILD_MODNAME "." #endif -#ifdef MODULE #define ___module_cat(a,b) __mod_ ## a ## b #define __module_cat(a,b) ___module_cat(a,b) + +#ifdef MODULE #define __MODULE_INFO(tag, name, info) \ static const char __module_cat(name,__LINE__)[] \ __attribute_used__ \ __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info #else /* !MODULE */ -#define __MODULE_INFO(tag, name, info) +struct builtin_modinfo { + char *modname; + char *name; + char *content; +}; +#define __MODULE_INFO(tag, name, info) \ +static const struct builtin_modinfo __module_cat(name, __LINE__) \ + __attribute_used__ \ + __attribute__((section(".modinfo"), unused)) = \ + { KBUILD_MODNAME, __stringify(tag), info } #endif + #define __MODULE_PARM_TYPE(name, _type) \ __MODULE_INFO(parmtype, name##type, #name ":" _type) diff --git a/kernel/module.c b/kernel/module.c index c2e3e2e..485a3dd 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -49,7 +49,7 @@ extern int module_sysfs_initialized; -#if 0 +#if 1 #define DEBUGP printk #else #define DEBUGP(fmt , a...) @@ -1876,7 +1876,7 @@ static struct module *load_module(void __user *umod, sechdrs[i].sh_size); /* Update sh_addr to point to copy in image. */ sechdrs[i].sh_addr = (unsigned long)dest; - DEBUGP("\t0x%lx %s\n", sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name); + DEBUGP("\t0x%lx %s\n", (unsigned long)sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name); } /* Module has been moved. */ mod = (void *)sechdrs[modindex].sh_addr; @@ -2609,3 +2609,165 @@ void module_update_markers(struct module *probe_module, int *refcount) mutex_unlock(&module_mutex); } #endif + +struct modinfo_attribute +{ + struct module_attribute mattr; + const struct builtin_modinfo *modinfo; +}; + +struct module_modinfo_attrs +{ + struct attribute_group grp; + struct modinfo_attribute attrs[0]; +}; + +#ifdef CONFIG_SYSFS +#define to_modinfo_attr(n) container_of(n, struct modinfo_attribute, mattr) + +static ssize_t modinfo_attr_show(struct module_attribute *mattr, + struct module *mod, char *buf) +{ + const struct builtin_modinfo *bm = to_modinfo_attr(mattr)->modinfo; + return snprintf(buf, PAGE_SIZE, "%s\n", bm->content); +} + +#endif + +static __init int modinfo_skip(char *name) +{ + DEBUGP("info: %s, len: %u, ncmp: %u,%u\n", name, strlen(name), + !strncmp(name, "parm", 4), !strncmp(name, "parmtype", 8)); + return (strlen(name) == 4 && !strncmp(name, "parm", 4)) || + (strlen(name) == 8 && !strncmp(name, "parmtype", 8)); +} + +static __init void modinfo_sysfs_setup(struct module_kobject *mk, + const struct builtin_modinfo bm_begin[], + unsigned int num_params) +{ + struct module_modinfo_attrs *mp; + unsigned int valid_attrs = 0; + unsigned int i, size[2]; + struct modinfo_attribute *pattr; + struct attribute **gattr; + + DEBUGP("modname: %s\n", bm_begin[0].modname); + for (i = 0; i < num_params; ++i) { + if (!modinfo_skip(bm_begin[i].name)) { + valid_attrs++; + DEBUGP("modinfo: %s, %s, %s\n", + bm_begin[i].modname, bm_begin[i].name, + bm_begin[i].content); + } else { + DEBUGP("modinfo: %s, %s, %s, skipped\n", + bm_begin[i].modname, bm_begin[i].name, + bm_begin[i].content); + } + } + + if (!valid_attrs) + return; + + size[0] = ALIGN(sizeof(*mp) + + valid_attrs * sizeof(mp->attrs[0]), + sizeof(mp->grp.attrs[0])); + size[1] = (valid_attrs + 1) * sizeof(mp->grp.attrs[0]); + + mp = kzalloc(size[0] + size[1], GFP_KERNEL); + if (!mp) + return; + + mp->grp.attrs = (void *)mp + size[0]; + + pattr = &mp->attrs[0]; + gattr = &mp->grp.attrs[0]; + for (i = 0; i < valid_attrs; i++) { + const struct builtin_modinfo *bm = &bm_begin[i]; + if (!modinfo_skip(bm_begin[i].name)) { + pattr->modinfo = bm; + pattr->mattr.show = modinfo_attr_show; + pattr->mattr.attr.name = bm->name; + pattr->mattr.attr.mode = 0444; + *(gattr++) = &(pattr++)->mattr.attr; + } + } + + if (sysfs_create_group(&mk->kobj, &mp->grp)) { + kfree(mp); + } +} + +static void __init kernel_modinfo_sysfs_setup(const char *modname, + const struct builtin_modinfo bm_begin[], + unsigned int num_params) +{ + struct kobject *mkobj; + struct module_kobject *mk; + int ret; + + mkobj = kset_find_obj(&module_subsys, modname); + DEBUGP("mkobj: %p\n", mkobj); + + if (mkobj) + mk = container_of(mkobj, struct module_kobject, kobj); + else { + mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL); + + kobj_set_kset_s(mk, module_subsys); + kobject_set_name(&mk->kobj, modname); + kobject_init(&mk->kobj); + ret = kobject_add(&mk->kobj); + if (ret) { + printk(KERN_ERR "Module '%s' failed to be added to sysfs, " + "error number %d\n", modname, ret); + printk(KERN_ERR "The system will be unstable now.\n"); + return; + } + } + + modinfo_sysfs_setup(mk, bm_begin, num_params); + + if (mkobj) + kobject_put(mkobj); + else + kobject_uevent(&mk->kobj, KOBJ_ADD); +} + +/* + * module_info_sysfs_init is for built-in modules + * + * __initcall is later than subsys_init + */ +static int __init builtin_modinfo_sysfs_init(void) +{ + const struct builtin_modinfo *bm_info, *bm_info_begin = NULL; + unsigned int i, count = 0; + char *modname = NULL; + + extern const struct builtin_modinfo __start___modinfo[], __stop___modinfo[]; + for (i = 0; i < __stop___modinfo - __start___modinfo; i++) { + bm_info = &__start___modinfo[i]; + + /* new kbuild_modname? */ + if (bm_info->modname != modname) { + /* add a new kobject for previous kernel_params. */ + if (count) + kernel_modinfo_sysfs_setup(modname, + bm_info_begin, + count); + + modname = bm_info->modname; + count = 0; + bm_info_begin = bm_info; + } + count++; + } + + /* last kernel_params need to be registered as well */ + if (count) + kernel_modinfo_sysfs_setup(modname, bm_info_begin, count); + + return 0; +} +__initcall(builtin_modinfo_sysfs_init); -- 1.5.3.5