From b863a25d3dca56d4c84c3cdcca089a42f1c088be Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 7 May 2004 00:22:49 -0700 Subject: Add modules to sysfs This patch adds basic kobject support to struct module, and it creates a /sys/module directory which contains all of the individual modules. Each module currently exports the refcount (if they are unloadable) and any module paramaters that are marked exportable in sysfs. Was written by me and Rusty over and over many times during the past 6 months. --- include/linux/module.h | 25 +++++++++++++++++++++++++ include/linux/moduleparam.h | 4 ++-- 2 files changed, 27 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/module.h b/include/linux/module.h index 0a86652fb1cb..9a3eb2f1f95d 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include @@ -207,6 +209,23 @@ enum module_state MODULE_STATE_GOING, }; +/* sysfs stuff */ +struct module_attribute +{ + struct attribute attr; + struct kernel_param *param; +}; + +struct module_kobject +{ + /* Everyone should have one of these. */ + struct kobject kobj; + + /* We always have refcnt, we may have others from module_param(). */ + unsigned int num_attributes; + struct module_attribute attr[0]; +}; + struct module { enum module_state state; @@ -217,6 +236,9 @@ struct module /* Unique handle for this module */ char name[MODULE_NAME_LEN]; + /* Sysfs stuff. */ + struct module_kobject *mkobj; + /* Exported symbols */ const struct kernel_symbol *syms; unsigned int num_syms; @@ -267,6 +289,9 @@ struct module /* Destruction function. */ void (*exit)(void); + + /* Fake kernel param for refcnt. */ + struct kernel_param refcnt_param; #endif #ifdef CONFIG_KALLSYMS diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index e9d6a16d3fef..f63de16cdf54 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -50,7 +50,7 @@ struct kparam_array not there, read bits mean it's readable, write bits mean it's writable. */ #define __module_param_call(prefix, name, set, get, arg, perm) \ - static char __param_str_##name[] __initdata = prefix #name; \ + static char __param_str_##name[] = prefix #name; \ static struct kernel_param const __param_##name \ __attribute_used__ \ __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ @@ -71,7 +71,7 @@ struct kparam_array /* Actually copy string: maxlen param is usually sizeof(string). */ #define module_param_string(name, string, len, perm) \ - static struct kparam_string __param_string_##name __initdata \ + static struct kparam_string __param_string_##name \ = { len, string }; \ module_param_call(name, param_set_copystring, param_get_charp, \ &__param_string_##name, perm) -- cgit v1.2.3 From 8bcb3f98404202e085120d21fcc6e66eb90677a7 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 11 May 2004 02:35:42 -0700 Subject: [PATCH] fix dev_printk to work even in the absence of an attached driver --- include/linux/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 9bc07b556eea..bd05cdfb326e 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -400,7 +400,7 @@ extern void firmware_unregister(struct subsystem *); /* debugging and troubleshooting/diagnostic helpers. */ #define dev_printk(level, dev, format, arg...) \ - printk(level "%s %s: " format , (dev)->driver->name , (dev)->bus_id , ## arg) + printk(level "%s %s: " format , (dev)->driver ? (dev)->driver->name : "" , (dev)->bus_id , ## arg) #ifdef DEBUG #define dev_dbg(dev, format, arg...) \ -- cgit v1.2.3 From 51c0c34c8f0ac464c97aaef4754e7dc163dd586e Mon Sep 17 00:00:00 2001 From: Maneesh Soni Date: Thu, 13 May 2004 22:13:00 -0700 Subject: [PATCH] sysfs_rename_dir-cleanup o The following patch cleans up sysfs_rename_dir(). It now checks the return code of kobject_set_name() and propagates the error code to its callers. Because of this there are changes in the following two APIs. Both return int instead of void. int sysfs_rename_dir(struct kobject * kobj, const char *new_name) int kobject_rename(struct kobject * kobj, char *new_name) --- drivers/base/class.c | 6 ++++-- fs/sysfs/dir.c | 19 ++++++++++++++----- include/linux/kobject.h | 2 +- include/linux/sysfs.h | 2 +- lib/kobject.c | 10 +++++++--- net/core/dev.c | 16 ++++++++++------ 6 files changed, 37 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/drivers/base/class.c b/drivers/base/class.c index b9fdce488e2c..ed13d9de0d1d 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -361,6 +361,8 @@ void class_device_unregister(struct class_device *class_dev) int class_device_rename(struct class_device *class_dev, char *new_name) { + int error = 0; + class_dev = class_device_get(class_dev); if (!class_dev) return -EINVAL; @@ -370,11 +372,11 @@ int class_device_rename(struct class_device *class_dev, char *new_name) strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); - kobject_rename(&class_dev->kobj, new_name); + error = kobject_rename(&class_dev->kobj, new_name); class_device_put(class_dev); - return 0; + return error; } struct class_device * class_device_get(struct class_device *class_dev) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index add2045e8c25..91b06a20cd76 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -154,24 +154,33 @@ restart: dput(dentry); } -void sysfs_rename_dir(struct kobject * kobj, const char *new_name) +int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { + int error = 0; struct dentry * new_dentry, * parent; if (!strcmp(kobject_name(kobj), new_name)) - return; + return -EINVAL; if (!kobj->parent) - return; + return -EINVAL; parent = kobj->parent->dentry; down(&parent->d_inode->i_sem); new_dentry = sysfs_get_dentry(parent, new_name); - d_move(kobj->dentry, new_dentry); - kobject_set_name(kobj,new_name); + if (!IS_ERR(new_dentry)) { + if (!new_dentry->d_inode) { + error = kobject_set_name(kobj,new_name); + if (!error) + d_move(kobj->dentry, new_dentry); + } + dput(new_dentry); + } up(&parent->d_inode->i_sem); + + return error; } EXPORT_SYMBOL(sysfs_create_dir); diff --git a/include/linux/kobject.h b/include/linux/kobject.h index f32f39b4cce6..6360d225884c 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -48,7 +48,7 @@ extern void kobject_cleanup(struct kobject *); extern int kobject_add(struct kobject *); extern void kobject_del(struct kobject *); -extern void kobject_rename(struct kobject *, char *new_name); +extern int kobject_rename(struct kobject *, char *new_name); extern int kobject_register(struct kobject *); extern void kobject_unregister(struct kobject *); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index de2083939b74..31f1c8b4428d 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -44,7 +44,7 @@ sysfs_create_dir(struct kobject *); extern void sysfs_remove_dir(struct kobject *); -extern void +extern int sysfs_rename_dir(struct kobject *, const char *new_name); extern int diff --git a/lib/kobject.c b/lib/kobject.c index 5e8d1ed70716..5c2ade5739be 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -385,13 +385,17 @@ EXPORT_SYMBOL(kobject_set_name); * @new_name: object's new name */ -void kobject_rename(struct kobject * kobj, char *new_name) +int kobject_rename(struct kobject * kobj, char *new_name) { + int error = 0; + kobj = kobject_get(kobj); if (!kobj) - return; - sysfs_rename_dir(kobj, new_name); + return -EINVAL; + error = sysfs_rename_dir(kobj, new_name); kobject_put(kobj); + + return error; } /** diff --git a/net/core/dev.c b/net/core/dev.c index 43c273e74a7d..b14b8a310e4a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -792,6 +792,8 @@ int dev_alloc_name(struct net_device *dev, const char *name) */ int dev_change_name(struct net_device *dev, char *newname) { + int err = 0; + ASSERT_RTNL(); if (dev->flags & IFF_UP) @@ -801,7 +803,7 @@ int dev_change_name(struct net_device *dev, char *newname) return -EINVAL; if (strchr(newname, '%')) { - int err = dev_alloc_name(dev, newname); + err = dev_alloc_name(dev, newname); if (err < 0) return err; strcpy(newname, dev->name); @@ -811,12 +813,14 @@ int dev_change_name(struct net_device *dev, char *newname) else strlcpy(dev->name, newname, IFNAMSIZ); - hlist_del(&dev->name_hlist); - hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); + err = class_device_rename(&dev->class_dev, dev->name); + if (!err) { + hlist_del(&dev->name_hlist); + hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); + notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); + } - class_device_rename(&dev->class_dev, dev->name); - notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); - return 0; + return err; } /** -- cgit v1.2.3