From d4acd722b7bb5f48b9fc3848e8c2a845b100d84f Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 31 Oct 2007 09:38:04 -0500 Subject: [SCSI] sysfs: add filter function to groups This patch allows the various users of attribute_groups to selectively allow the appearance of group attributes. The primary consumer of this will be the transport classes in which we currently have elaborate attribute selection algorithms to do this same thing. Acked-by: Greg KH Signed-off-by: James Bottomley --- kernel/params.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/params.c b/kernel/params.c index 7686417ee00e..dfef46474e55 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -472,7 +472,7 @@ param_sysfs_setup(struct module_kobject *mk, sizeof(mp->grp.attrs[0])); size[1] = (valid_attrs + 1) * sizeof(mp->grp.attrs[0]); - mp = kmalloc(size[0] + size[1], GFP_KERNEL); + mp = kzalloc(size[0] + size[1], GFP_KERNEL); if (!mp) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From fabe874a48de45b137f99b4ed3641e0413f465ce Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 24 Jan 2008 07:00:45 +0100 Subject: lockdep: fix kernel crash on module unload Michael Wu noticed in his lkml post at http://marc.info/?l=linux-kernel&m=119396182726091&w=2 that certain wireless drivers ended up having their name in module memory, which would then crash the kernel on module unload. The patch he proposed was a bit clumsy in that it increased the size of a lockdep entry significantly; the patch below tries another approach, it checks, on module teardown, if the name of a class is in module space and then zaps the class. This is very similar to what we already do with keys that are in module space. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Signed-off-by: Linus Torvalds --- kernel/lockdep.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 4335f12a27c6..e2c07ece367d 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -2932,7 +2932,7 @@ static void zap_class(struct lock_class *class) } -static inline int within(void *addr, void *start, unsigned long size) +static inline int within(const void *addr, void *start, unsigned long size) { return addr >= start && addr < start + size; } @@ -2955,9 +2955,12 @@ void lockdep_free_key_range(void *start, unsigned long size) head = classhash_table + i; if (list_empty(head)) continue; - list_for_each_entry_safe(class, next, head, hash_entry) + list_for_each_entry_safe(class, next, head, hash_entry) { if (within(class->key, start, size)) zap_class(class); + else if (within(class->name, start, size)) + zap_class(class); + } } if (locked) -- cgit v1.2.3 From 3514faca19a6fdc209734431c509631ea92b094e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Oct 2007 10:11:44 -0600 Subject: kobject: remove struct kobj_type from struct kset We don't need a "default" ktype for a kset. We should set this explicitly every time for each kset. This change is needed so that we can make ksets dynamic, and cleans up one of the odd, undocumented assumption that the kset/kobject/ktype model has. This patch is based on a lot of help from Kay Sievers. Nasty bug in the block code was found by Dave Young Cc: Kay Sievers Cc: Dave Young Signed-off-by: Greg Kroah-Hartman --- kernel/ksysfs.c | 2 +- kernel/module.c | 2 +- kernel/params.c | 9 +++++---- kernel/power/main.c | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) (limited to 'kernel') diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 65daa5373ca6..094e2bc101a8 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -94,7 +94,7 @@ static struct bin_attribute notes_attr = { .read = ¬es_read, }; -decl_subsys(kernel, NULL, NULL); +decl_subsys(kernel, NULL); EXPORT_SYMBOL_GPL(kernel_subsys); static struct attribute * kernel_attrs[] = { diff --git a/kernel/module.c b/kernel/module.c index c2e3e2e98801..68df79738b3b 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1223,7 +1223,7 @@ int mod_sysfs_init(struct module *mod) err = kobject_set_name(&mod->mkobj.kobj, "%s", mod->name); if (err) goto out; - kobj_set_kset_s(&mod->mkobj, module_subsys); + mod->mkobj.kobj.kset = &module_subsys; mod->mkobj.mod = mod; kobject_init(&mod->mkobj.kobj); diff --git a/kernel/params.c b/kernel/params.c index 7686417ee00e..9f051824097d 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -30,6 +30,8 @@ #define DEBUGP(fmt, a...) #endif +static struct kobj_type module_ktype; + static inline char dash2underscore(char c) { if (c == '-') @@ -560,7 +562,8 @@ static void __init kernel_param_sysfs_setup(const char *name, BUG_ON(!mk); mk->mod = THIS_MODULE; - kobj_set_kset_s(mk, module_subsys); + mk->kobj.kset = &module_subsys; + mk->kobj.ktype = &module_ktype; kobject_set_name(&mk->kobj, name); kobject_init(&mk->kobj); ret = kobject_add(&mk->kobj); @@ -679,8 +682,6 @@ static struct sysfs_ops module_sysfs_ops = { .store = module_attr_store, }; -static struct kobj_type module_ktype; - static int uevent_filter(struct kset *kset, struct kobject *kobj) { struct kobj_type *ktype = get_ktype(kobj); @@ -694,7 +695,7 @@ static struct kset_uevent_ops module_uevent_ops = { .filter = uevent_filter, }; -decl_subsys(module, &module_ktype, &module_uevent_ops); +decl_subsys(module, &module_uevent_ops); int module_sysfs_initialized; static void module_release(struct kobject *kobj) diff --git a/kernel/power/main.c b/kernel/power/main.c index f71c9504a5c5..1ef31c91ce0e 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -276,7 +276,7 @@ EXPORT_SYMBOL(pm_suspend); #endif /* CONFIG_SUSPEND */ -decl_subsys(power,NULL,NULL); +decl_subsys(power, NULL); /** -- cgit v1.2.3 From 4ff6abff832fbc6cb1d769f6106c841bc2b09f63 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Nov 2007 22:24:43 -0800 Subject: kobject: get rid of kobject_add_dir kobject_create_and_add is the same as kobject_add_dir, so drop kobject_add_dir. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'kernel') diff --git a/kernel/module.c b/kernel/module.c index 68df79738b3b..55142775c581 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1122,7 +1122,7 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, ++loaded; } - notes_attrs->dir = kobject_add_dir(&mod->mkobj.kobj, "notes"); + notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj); if (!notes_attrs->dir) goto out; @@ -1243,7 +1243,7 @@ int mod_sysfs_setup(struct module *mod, if (err) goto out; - mod->holders_dir = kobject_add_dir(&mod->mkobj.kobj, "holders"); + mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj); if (!mod->holders_dir) { err = -ENOMEM; goto out_unreg; @@ -2521,7 +2521,7 @@ static void module_create_drivers_dir(struct module_kobject *mk) if (!mk || mk->drivers_dir) return; - mk->drivers_dir = kobject_add_dir(&mk->kobj, "drivers"); + mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj); } void module_add_driver(struct module *mod, struct device_driver *drv) -- cgit v1.2.3 From bd35b93d8049ab47b5bfaf6b10ba39badf21d1c3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 29 Oct 2007 20:13:17 +0100 Subject: kset: convert kernel_subsys to use kset_create Dynamically create the kset instead of declaring it statically. We also rename kernel_subsys to kernel_kset to catch all users of this symbol with a build error instead of an easy-to-ignore build warning. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/ksysfs.c | 42 ++++++++++++++++++++++++++++++------------ kernel/user.c | 4 ++-- 2 files changed, 32 insertions(+), 14 deletions(-) (limited to 'kernel') diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 094e2bc101a8..cf02d4ba9add 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -94,8 +94,8 @@ static struct bin_attribute notes_attr = { .read = ¬es_read, }; -decl_subsys(kernel, NULL); -EXPORT_SYMBOL_GPL(kernel_subsys); +struct kset *kernel_kset; +EXPORT_SYMBOL_GPL(kernel_kset); static struct attribute * kernel_attrs[] = { #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) @@ -116,24 +116,42 @@ static struct attribute_group kernel_attr_group = { static int __init ksysfs_init(void) { - int error = subsystem_register(&kernel_subsys); - if (!error) - error = sysfs_create_group(&kernel_subsys.kobj, - &kernel_attr_group); + int error; - if (!error && notes_size > 0) { + kernel_kset = kset_create_and_add("kernel", NULL, NULL); + if (!kernel_kset) { + error = -ENOMEM; + goto exit; + } + error = sysfs_create_group(&kernel_kset->kobj, &kernel_attr_group); + if (error) + goto kset_exit; + + if (notes_size > 0) { notes_attr.size = notes_size; - error = sysfs_create_bin_file(&kernel_subsys.kobj, - ¬es_attr); + error = sysfs_create_bin_file(&kernel_kset->kobj, ¬es_attr); + if (error) + goto group_exit; } /* * Create "/sys/kernel/uids" directory and corresponding root user's * directory under it. */ - if (!error) - error = uids_kobject_init(); - + error = uids_kobject_init(); + if (error) + goto notes_exit; + + return 0; + +notes_exit: + if (notes_size > 0) + sysfs_remove_bin_file(&kernel_kset->kobj, ¬es_attr); +group_exit: + sysfs_remove_group(&kernel_kset->kobj, &kernel_attr_group); +kset_exit: + kset_unregister(kernel_kset); +exit: return error; } diff --git a/kernel/user.c b/kernel/user.c index 8320a87f3e5a..80f1116b8fcd 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -198,8 +198,8 @@ int __init uids_kobject_init(void) int error; /* create under /sys/kernel dir */ - uids_kobject.parent = &kernel_subsys.kobj; - uids_kobject.kset = &kernel_subsys; + uids_kobject.parent = &kernel_kset->kobj; + uids_kobject.kset = kernel_kset; kobject_set_name(&uids_kobject, "uids"); kobject_init(&uids_kobject); -- cgit v1.2.3 From 7405c1e15edfe43b137bfbc5882f1af34d6d414d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 1 Nov 2007 10:39:50 -0700 Subject: kset: convert /sys/module to use kset_create Dynamically create the kset instead of declaring it statically. We also rename module_subsys to module_kset to catch all users of the variable. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 7 +++---- kernel/params.c | 29 +++++++++-------------------- 2 files changed, 12 insertions(+), 24 deletions(-) (limited to 'kernel') diff --git a/kernel/module.c b/kernel/module.c index 55142775c581..d03fcd9d652c 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -47,8 +47,6 @@ #include #include -extern int module_sysfs_initialized; - #if 0 #define DEBUGP printk #else @@ -1223,7 +1221,8 @@ int mod_sysfs_init(struct module *mod) err = kobject_set_name(&mod->mkobj.kobj, "%s", mod->name); if (err) goto out; - mod->mkobj.kobj.kset = &module_subsys; + mod->mkobj.kobj.kset = module_kset; + mod->mkobj.kobj.ktype = &module_ktype; mod->mkobj.mod = mod; kobject_init(&mod->mkobj.kobj); @@ -2539,7 +2538,7 @@ void module_add_driver(struct module *mod, struct device_driver *drv) struct kobject *mkobj; /* Lookup built-in module entry in /sys/modules */ - mkobj = kset_find_obj(&module_subsys, drv->mod_name); + mkobj = kset_find_obj(module_kset, drv->mod_name); if (mkobj) { mk = container_of(mkobj, struct module_kobject, kobj); /* remember our module structure */ diff --git a/kernel/params.c b/kernel/params.c index 9f051824097d..97e092312155 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -30,8 +30,6 @@ #define DEBUGP(fmt, a...) #endif -static struct kobj_type module_ktype; - static inline char dash2underscore(char c) { if (c == '-') @@ -562,7 +560,7 @@ static void __init kernel_param_sysfs_setup(const char *name, BUG_ON(!mk); mk->mod = THIS_MODULE; - mk->kobj.kset = &module_subsys; + mk->kobj.kset = module_kset; mk->kobj.ktype = &module_ktype; kobject_set_name(&mk->kobj, name); kobject_init(&mk->kobj); @@ -695,7 +693,7 @@ static struct kset_uevent_ops module_uevent_ops = { .filter = uevent_filter, }; -decl_subsys(module, &module_uevent_ops); +struct kset *module_kset; int module_sysfs_initialized; static void module_release(struct kobject *kobj) @@ -707,7 +705,7 @@ static void module_release(struct kobject *kobj) */ } -static struct kobj_type module_ktype = { +struct kobj_type module_ktype = { .sysfs_ops = &module_sysfs_ops, .release = module_release, }; @@ -717,13 +715,11 @@ static struct kobj_type module_ktype = { */ static int __init param_sysfs_init(void) { - int ret; - - ret = subsystem_register(&module_subsys); - if (ret < 0) { - printk(KERN_WARNING "%s (%d): subsystem_register error: %d\n", - __FILE__, __LINE__, ret); - return ret; + module_kset = kset_create_and_add("module", &module_uevent_ops, NULL); + if (!module_kset) { + printk(KERN_WARNING "%s (%d): error creating kset\n", + __FILE__, __LINE__); + return -ENOMEM; } module_sysfs_initialized = 1; @@ -733,14 +729,7 @@ static int __init param_sysfs_init(void) } subsys_initcall(param_sysfs_init); -#else -#if 0 -static struct sysfs_ops module_sysfs_ops = { - .show = NULL, - .store = NULL, -}; -#endif -#endif +#endif /* CONFIG_SYSFS */ EXPORT_SYMBOL(param_set_byte); EXPORT_SYMBOL(param_get_byte); -- cgit v1.2.3 From 039a5dcd2fc45188a2d522df630db4f7ef903a0f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 1 Nov 2007 10:39:50 -0700 Subject: kset: convert /sys/power to use kset_create Dynamically create the kset instead of declaring it statically. We also rename power_subsys to power_kset to catch all users of the variable and we properly export it so that people don't have to guess that it really is present in the system. The pseries code is wierd, why is it createing /sys/power if CONFIG_PM is disabled? Oh well, stupid big boxes ignoring config options... Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/power/disk.c | 2 +- kernel/power/main.c | 11 +++++------ kernel/power/power.h | 2 -- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'kernel') diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 05b64790fe83..c3f0e61365dd 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -708,7 +708,7 @@ static struct attribute_group attr_group = { static int __init pm_disk_init(void) { - return sysfs_create_group(&power_subsys.kobj, &attr_group); + return sysfs_create_group(&power_kset->kobj, &attr_group); } core_initcall(pm_disk_init); diff --git a/kernel/power/main.c b/kernel/power/main.c index 1ef31c91ce0e..dce2d76d66de 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -276,8 +276,7 @@ EXPORT_SYMBOL(pm_suspend); #endif /* CONFIG_SUSPEND */ -decl_subsys(power, NULL); - +struct kset *power_kset; /** * state - control system power state. @@ -386,10 +385,10 @@ static struct attribute_group attr_group = { static int __init pm_init(void) { - int error = subsystem_register(&power_subsys); - if (!error) - error = sysfs_create_group(&power_subsys.kobj,&attr_group); - return error; + power_kset = kset_create_and_add("power", NULL, NULL); + if (!power_kset) + return -ENOMEM; + return sysfs_create_group(&power_kset->kobj, &attr_group); } core_initcall(pm_init); diff --git a/kernel/power/power.h b/kernel/power/power.h index 195dc4611764..1083e6b188ab 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -63,8 +63,6 @@ static struct subsys_attribute _name##_attr = { \ .store = _name##_store, \ } -extern struct kset power_subsys; - /* Preferred image size in bytes (default 500 MB) */ extern unsigned long image_size; extern int in_suspend; -- cgit v1.2.3 From 386f275f5d097758f867bc99ddeaeb7a03b6b190 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 2 Nov 2007 13:47:53 +0100 Subject: Driver Core: switch all dynamic ksets to kobj_sysfs_ops Switch all dynamically created ksets, that export simple attributes, to kobj_attribute from subsys_attribute. Struct subsys_attribute will be removed. Signed-off-by: Kay Sievers Cc: Mike Halcrow Cc: Phillip Hellewell Signed-off-by: Greg Kroah-Hartman --- kernel/ksysfs.c | 35 +++++++++++++++++++++-------------- kernel/power/disk.c | 18 ++++++++++++------ kernel/power/main.c | 12 ++++++++---- kernel/power/power.h | 2 +- 4 files changed, 42 insertions(+), 25 deletions(-) (limited to 'kernel') diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index cf02d4ba9add..dd0f9e7f3414 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -17,30 +17,34 @@ #include #define KERNEL_ATTR_RO(_name) \ -static struct subsys_attribute _name##_attr = __ATTR_RO(_name) +static struct kobj_attribute _name##_attr = __ATTR_RO(_name) #define KERNEL_ATTR_RW(_name) \ -static struct subsys_attribute _name##_attr = \ +static struct kobj_attribute _name##_attr = \ __ATTR(_name, 0644, _name##_show, _name##_store) #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) /* current uevent sequence number */ -static ssize_t uevent_seqnum_show(struct kset *kset, char *page) +static ssize_t uevent_seqnum_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { - return sprintf(page, "%llu\n", (unsigned long long)uevent_seqnum); + return sprintf(buf, "%llu\n", (unsigned long long)uevent_seqnum); } KERNEL_ATTR_RO(uevent_seqnum); /* uevent helper program, used during early boo */ -static ssize_t uevent_helper_show(struct kset *kset, char *page) +static ssize_t uevent_helper_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { - return sprintf(page, "%s\n", uevent_helper); + return sprintf(buf, "%s\n", uevent_helper); } -static ssize_t uevent_helper_store(struct kset *kset, const char *page, size_t count) +static ssize_t uevent_helper_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) { if (count+1 > UEVENT_HELPER_PATH_LEN) return -ENOENT; - memcpy(uevent_helper, page, count); + memcpy(uevent_helper, buf, count); uevent_helper[count] = '\0'; if (count && uevent_helper[count-1] == '\n') uevent_helper[count-1] = '\0'; @@ -50,21 +54,24 @@ KERNEL_ATTR_RW(uevent_helper); #endif #ifdef CONFIG_KEXEC -static ssize_t kexec_loaded_show(struct kset *kset, char *page) +static ssize_t kexec_loaded_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { - return sprintf(page, "%d\n", !!kexec_image); + return sprintf(buf, "%d\n", !!kexec_image); } KERNEL_ATTR_RO(kexec_loaded); -static ssize_t kexec_crash_loaded_show(struct kset *kset, char *page) +static ssize_t kexec_crash_loaded_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { - return sprintf(page, "%d\n", !!kexec_crash_image); + return sprintf(buf, "%d\n", !!kexec_crash_image); } KERNEL_ATTR_RO(kexec_crash_loaded); -static ssize_t vmcoreinfo_show(struct kset *kset, char *page) +static ssize_t vmcoreinfo_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { - return sprintf(page, "%lx %x\n", + return sprintf(buf, "%lx %x\n", paddr_vmcoreinfo_note(), (unsigned int)vmcoreinfo_max_size); } diff --git a/kernel/power/disk.c b/kernel/power/disk.c index c3f0e61365dd..ef5aa2ca0ab0 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -567,7 +567,8 @@ static const char * const hibernation_modes[] = { * supports it (as determined by having hibernation_ops). */ -static ssize_t disk_show(struct kset *kset, char *buf) +static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) { int i; char *start = buf; @@ -597,7 +598,8 @@ static ssize_t disk_show(struct kset *kset, char *buf) } -static ssize_t disk_store(struct kset *kset, const char *buf, size_t n) +static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) { int error = 0; int i; @@ -642,13 +644,15 @@ static ssize_t disk_store(struct kset *kset, const char *buf, size_t n) power_attr(disk); -static ssize_t resume_show(struct kset *kset, char *buf) +static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) { return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); } -static ssize_t resume_store(struct kset *kset, const char *buf, size_t n) +static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) { unsigned int maj, min; dev_t res; @@ -674,12 +678,14 @@ static ssize_t resume_store(struct kset *kset, const char *buf, size_t n) power_attr(resume); -static ssize_t image_size_show(struct kset *kset, char *buf) +static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) { return sprintf(buf, "%lu\n", image_size); } -static ssize_t image_size_store(struct kset *kset, const char *buf, size_t n) +static ssize_t image_size_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) { unsigned long size; diff --git a/kernel/power/main.c b/kernel/power/main.c index dce2d76d66de..b8139493b856 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -289,7 +289,8 @@ struct kset *power_kset; * proper enumerated value, and initiates a suspend transition. */ -static ssize_t state_show(struct kset *kset, char *buf) +static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) { char *s = buf; #ifdef CONFIG_SUSPEND @@ -310,7 +311,8 @@ static ssize_t state_show(struct kset *kset, char *buf) return (s - buf); } -static ssize_t state_store(struct kset *kset, const char *buf, size_t n) +static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) { #ifdef CONFIG_SUSPEND suspend_state_t state = PM_SUSPEND_STANDBY; @@ -347,13 +349,15 @@ power_attr(state); #ifdef CONFIG_PM_TRACE int pm_trace_enabled; -static ssize_t pm_trace_show(struct kset *kset, char *buf) +static ssize_t pm_trace_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", pm_trace_enabled); } static ssize_t -pm_trace_store(struct kset *kset, const char *buf, size_t n) +pm_trace_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) { int val; diff --git a/kernel/power/power.h b/kernel/power/power.h index 1083e6b188ab..2093c3a9a994 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -54,7 +54,7 @@ extern int pfn_is_nosave(unsigned long); extern struct mutex pm_mutex; #define power_attr(_name) \ -static struct subsys_attribute _name##_attr = { \ +static struct kobj_attribute _name##_attr = { \ .attr = { \ .name = __stringify(_name), \ .mode = 0644, \ -- cgit v1.2.3 From eb41d9465cdafee45e0cb30f3b7338646221908e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 2 Nov 2007 13:47:53 +0100 Subject: fix struct user_info export's sysfs interaction Clean up the use of ksets and kobjects. Kobjects are instances of objects (like struct user_info), ksets are collections of objects of a similar type (like the uids directory containing the user_info directories). So, use kobjects for the user_info directories, and a kset for the "uids" directory. On object cleanup, the final kobject_put() was missing. Cc: Dhaval Giani Cc: Srivatsa Vaddagiri Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/ksysfs.c | 7 ++-- kernel/user.c | 104 +++++++++++++++++++++++++++----------------------------- 2 files changed, 53 insertions(+), 58 deletions(-) (limited to 'kernel') diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index dd0f9e7f3414..45e646585605 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -141,11 +141,8 @@ static int __init ksysfs_init(void) goto group_exit; } - /* - * Create "/sys/kernel/uids" directory and corresponding root user's - * directory under it. - */ - error = uids_kobject_init(); + /* create the /sys/kernel/uids/ directory */ + error = uids_sysfs_init(); if (error) goto notes_exit; diff --git a/kernel/user.c b/kernel/user.c index 80f1116b8fcd..5a106f3fdf05 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -115,7 +115,7 @@ static void sched_switch_user(struct task_struct *p) { } #if defined(CONFIG_FAIR_USER_SCHED) && defined(CONFIG_SYSFS) -static struct kobject uids_kobject; /* represents /sys/kernel/uids directory */ +static struct kset *uids_kset; /* represents the /sys/kernel/uids/ directory */ static DEFINE_MUTEX(uids_mutex); static inline void uids_mutex_lock(void) @@ -128,86 +128,84 @@ static inline void uids_mutex_unlock(void) mutex_unlock(&uids_mutex); } -/* return cpu shares held by the user */ -static ssize_t cpu_shares_show(struct kset *kset, char *buffer) +/* uid directory attributes */ +static ssize_t cpu_shares_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) { - struct user_struct *up = container_of(kset, struct user_struct, kset); + struct user_struct *up = container_of(kobj, struct user_struct, kobj); - return sprintf(buffer, "%lu\n", sched_group_shares(up->tg)); + return sprintf(buf, "%lu\n", sched_group_shares(up->tg)); } -/* modify cpu shares held by the user */ -static ssize_t cpu_shares_store(struct kset *kset, const char *buffer, - size_t size) +static ssize_t cpu_shares_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t size) { - struct user_struct *up = container_of(kset, struct user_struct, kset); + struct user_struct *up = container_of(kobj, struct user_struct, kobj); unsigned long shares; int rc; - sscanf(buffer, "%lu", &shares); + sscanf(buf, "%lu", &shares); rc = sched_group_set_shares(up->tg, shares); return (rc ? rc : size); } -static void user_attr_init(struct subsys_attribute *sa, char *name, int mode) +static struct kobj_attribute cpu_share_attr = + __ATTR(cpu_share, 0644, cpu_shares_show, cpu_shares_store); + +/* default attributes per uid directory */ +static struct attribute *uids_attributes[] = { + &cpu_share_attr.attr, + NULL +}; + +/* the lifetime of user_struct is not managed by the core (now) */ +static void uids_release(struct kobject *kobj) { - sa->attr.name = name; - sa->attr.mode = mode; - sa->show = cpu_shares_show; - sa->store = cpu_shares_store; + return; } -/* Create "/sys/kernel/uids/" directory and - * "/sys/kernel/uids//cpu_share" file for this user. - */ -static int user_kobject_create(struct user_struct *up) +static struct kobj_type uids_ktype = { + .sysfs_ops = &kobj_sysfs_ops, + .default_attrs = uids_attributes, + .release = uids_release, +}; + +/* create /sys/kernel/uids//cpu_share file for this user */ +static int uids_user_create(struct user_struct *up) { - struct kset *kset = &up->kset; - struct kobject *kobj = &kset->kobj; + struct kobject *kobj = &up->kobj; int error; - memset(kset, 0, sizeof(struct kset)); - kobj->parent = &uids_kobject; /* create under /sys/kernel/uids dir */ - kobject_set_name(kobj, "%d", up->uid); - kset_init(kset); - user_attr_init(&up->user_attr, "cpu_share", 0644); - + memset(kobj, 0, sizeof(struct kobject)); + kobj->ktype = &uids_ktype; + kobj->kset = uids_kset; + kobject_init(kobj); + kobject_set_name(&up->kobj, "%d", up->uid); error = kobject_add(kobj); if (error) goto done; - error = sysfs_create_file(kobj, &up->user_attr.attr); - if (error) - kobject_del(kobj); - kobject_uevent(kobj, KOBJ_ADD); - done: return error; } -/* create these in sysfs filesystem: +/* create these entries in sysfs: * "/sys/kernel/uids" directory * "/sys/kernel/uids/0" directory (for root user) * "/sys/kernel/uids/0/cpu_share" file (for root user) */ -int __init uids_kobject_init(void) +int __init uids_sysfs_init(void) { - int error; + uids_kset = kset_create_and_add("uids", NULL, &kernel_kset->kobj); + if (!uids_kset) + return -ENOMEM; - /* create under /sys/kernel dir */ - uids_kobject.parent = &kernel_kset->kobj; - uids_kobject.kset = kernel_kset; - kobject_set_name(&uids_kobject, "uids"); - kobject_init(&uids_kobject); - - error = kobject_add(&uids_kobject); - if (!error) - error = user_kobject_create(&root_user); - - return error; + return uids_user_create(&root_user); } /* work function to remove sysfs directory for a user and free up @@ -216,7 +214,6 @@ int __init uids_kobject_init(void) static void remove_user_sysfs_dir(struct work_struct *w) { struct user_struct *up = container_of(w, struct user_struct, work); - struct kobject *kobj = &up->kset.kobj; unsigned long flags; int remove_user = 0; @@ -238,9 +235,9 @@ static void remove_user_sysfs_dir(struct work_struct *w) if (!remove_user) goto done; - sysfs_remove_file(kobj, &up->user_attr.attr); - kobject_uevent(kobj, KOBJ_REMOVE); - kobject_del(kobj); + kobject_uevent(&up->kobj, KOBJ_REMOVE); + kobject_del(&up->kobj); + kobject_put(&up->kobj); sched_destroy_user(up); key_put(up->uid_keyring); @@ -267,7 +264,8 @@ static inline void free_user(struct user_struct *up, unsigned long flags) #else /* CONFIG_FAIR_USER_SCHED && CONFIG_SYSFS */ -static inline int user_kobject_create(struct user_struct *up) { return 0; } +int uids_sysfs_init(void) { return 0; } +static inline int uids_user_create(struct user_struct *up) { return 0; } static inline void uids_mutex_lock(void) { } static inline void uids_mutex_unlock(void) { } @@ -324,7 +322,7 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) struct hlist_head *hashent = uidhashentry(ns, uid); struct user_struct *up; - /* Make uid_hash_find() + user_kobject_create() + uid_hash_insert() + /* Make uid_hash_find() + uids_user_create() + uid_hash_insert() * atomic. */ uids_mutex_lock(); @@ -370,7 +368,7 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) return NULL; } - if (user_kobject_create(new)) { + if (uids_user_create(new)) { sched_destroy_user(new); key_put(new->uid_keyring); key_put(new->session_keyring); -- cgit v1.2.3 From 0ff21e46630abce11fdaaffabd72bbd4eed5ac2c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Nov 2007 10:36:58 -0800 Subject: kobject: convert kernel_kset to be a kobject kernel_kset does not need to be a kset, but a much simpler kobject now that we have kobj_attributes. We also rename kernel_kset to kernel_kobj to catch all users of this symbol with a build error instead of an easy-to-ignore build warning. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/ksysfs.c | 18 +++++++++--------- kernel/user.c | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'kernel') diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 45e646585605..1081aff5fb9e 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -101,8 +101,8 @@ static struct bin_attribute notes_attr = { .read = ¬es_read, }; -struct kset *kernel_kset; -EXPORT_SYMBOL_GPL(kernel_kset); +struct kobject *kernel_kobj; +EXPORT_SYMBOL_GPL(kernel_kobj); static struct attribute * kernel_attrs[] = { #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) @@ -125,18 +125,18 @@ static int __init ksysfs_init(void) { int error; - kernel_kset = kset_create_and_add("kernel", NULL, NULL); - if (!kernel_kset) { + kernel_kobj = kobject_create_and_add("kernel", NULL); + if (!kernel_kobj) { error = -ENOMEM; goto exit; } - error = sysfs_create_group(&kernel_kset->kobj, &kernel_attr_group); + error = sysfs_create_group(kernel_kobj, &kernel_attr_group); if (error) goto kset_exit; if (notes_size > 0) { notes_attr.size = notes_size; - error = sysfs_create_bin_file(&kernel_kset->kobj, ¬es_attr); + error = sysfs_create_bin_file(kernel_kobj, ¬es_attr); if (error) goto group_exit; } @@ -150,11 +150,11 @@ static int __init ksysfs_init(void) notes_exit: if (notes_size > 0) - sysfs_remove_bin_file(&kernel_kset->kobj, ¬es_attr); + sysfs_remove_bin_file(kernel_kobj, ¬es_attr); group_exit: - sysfs_remove_group(&kernel_kset->kobj, &kernel_attr_group); + sysfs_remove_group(kernel_kobj, &kernel_attr_group); kset_exit: - kset_unregister(kernel_kset); + kobject_unregister(kernel_kobj); exit: return error; } diff --git a/kernel/user.c b/kernel/user.c index 5a106f3fdf05..7f17e6e8fd65 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -201,7 +201,7 @@ done: */ int __init uids_sysfs_init(void) { - uids_kset = kset_create_and_add("uids", NULL, &kernel_kset->kobj); + uids_kset = kset_create_and_add("uids", NULL, kernel_kobj); if (!uids_kset) return -ENOMEM; -- cgit v1.2.3 From d76e15fb20eeb7632ef38876a884fe3508b2c01d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 27 Nov 2007 11:28:26 -0800 Subject: driver core: make /sys/power a kobject /sys/power should not be a kset, that's overkill. This patch renames it to power_kset and fixes up all usages of it in the tree. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/power/disk.c | 2 +- kernel/power/main.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'kernel') diff --git a/kernel/power/disk.c b/kernel/power/disk.c index ef5aa2ca0ab0..b138b431e271 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -714,7 +714,7 @@ static struct attribute_group attr_group = { static int __init pm_disk_init(void) { - return sysfs_create_group(&power_kset->kobj, &attr_group); + return sysfs_create_group(power_kobj, &attr_group); } core_initcall(pm_disk_init); diff --git a/kernel/power/main.c b/kernel/power/main.c index b8139493b856..efc08360e627 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -276,7 +276,7 @@ EXPORT_SYMBOL(pm_suspend); #endif /* CONFIG_SUSPEND */ -struct kset *power_kset; +struct kobject *power_kobj; /** * state - control system power state. @@ -389,10 +389,10 @@ static struct attribute_group attr_group = { static int __init pm_init(void) { - power_kset = kset_create_and_add("power", NULL, NULL); - if (!power_kset) + power_kobj = kobject_create_and_add("power", NULL); + if (!power_kobj) return -ENOMEM; - return sysfs_create_group(&power_kset->kobj, &attr_group); + return sysfs_create_group(power_kobj, &attr_group); } core_initcall(pm_init); -- cgit v1.2.3 From e43b9192c59402685bd1f809068dd13aa5931570 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Dec 2007 23:05:35 -0700 Subject: Kobject: convert kernel/params.c to use kobject_init/add_ng() This converts the code to use the new kobject functions, cleaning up the logic in doing so. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/params.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'kernel') diff --git a/kernel/params.c b/kernel/params.c index 97e092312155..1078b148ca80 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -561,11 +561,9 @@ static void __init kernel_param_sysfs_setup(const char *name, mk->mod = THIS_MODULE; mk->kobj.kset = module_kset; - mk->kobj.ktype = &module_ktype; - kobject_set_name(&mk->kobj, name); - kobject_init(&mk->kobj); - ret = kobject_add(&mk->kobj); + ret = kobject_init_and_add(&mk->kobj, &module_ktype, NULL, "%s", name); if (ret) { + kobject_put(&mk->kobj); printk(KERN_ERR "Module '%s' failed to be added to sysfs, " "error number %d\n", name, ret); printk(KERN_ERR "The system will be unstable now.\n"); -- cgit v1.2.3 From cf15126b3d4511e06e5299781ab74922590900be Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Dec 2007 23:05:35 -0700 Subject: Kobject: convert kernel/user.c to use kobject_init/add_ng() This converts the code to use the new kobject functions, cleaning up the logic in doing so. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/user.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'kernel') diff --git a/kernel/user.c b/kernel/user.c index 7f17e6e8fd65..ab4fd706993b 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -181,13 +181,12 @@ static int uids_user_create(struct user_struct *up) int error; memset(kobj, 0, sizeof(struct kobject)); - kobj->ktype = &uids_ktype; kobj->kset = uids_kset; - kobject_init(kobj); - kobject_set_name(&up->kobj, "%d", up->uid); - error = kobject_add(kobj); - if (error) + error = kobject_init_and_add(kobj, &uids_ktype, NULL, "%d", up->uid); + if (error) { + kobject_put(kobj); goto done; + } kobject_uevent(kobj, KOBJ_ADD); done: -- cgit v1.2.3 From c63469a3985a9771c18a916b8d42845d044ea0b1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 28 Nov 2007 12:23:18 -0800 Subject: Driver core: move the driver specific module code into the driver core The module driver specific code should belong in the driver core, not in the kernel/ directory. So move this code. This is done in preparation for some struct device_driver rework that should be confined to the driver core code only. This also lets us keep from exporting these functions, as no external code should ever be calling it. Thanks to Andrew Morton for the !CONFIG_MODULES fix. Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 87 --------------------------------------------------------- 1 file changed, 87 deletions(-) (limited to 'kernel') diff --git a/kernel/module.c b/kernel/module.c index d03fcd9d652c..dc4d3f5ce820 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2501,93 +2501,6 @@ void print_modules(void) printk("\n"); } -#ifdef CONFIG_SYSFS -static char *make_driver_name(struct device_driver *drv) -{ - char *driver_name; - - driver_name = kmalloc(strlen(drv->name) + strlen(drv->bus->name) + 2, - GFP_KERNEL); - if (!driver_name) - return NULL; - - sprintf(driver_name, "%s:%s", drv->bus->name, drv->name); - return driver_name; -} - -static void module_create_drivers_dir(struct module_kobject *mk) -{ - if (!mk || mk->drivers_dir) - return; - - mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj); -} - -void module_add_driver(struct module *mod, struct device_driver *drv) -{ - char *driver_name; - int no_warn; - struct module_kobject *mk = NULL; - - if (!drv) - return; - - if (mod) - mk = &mod->mkobj; - else if (drv->mod_name) { - struct kobject *mkobj; - - /* Lookup built-in module entry in /sys/modules */ - mkobj = kset_find_obj(module_kset, drv->mod_name); - if (mkobj) { - mk = container_of(mkobj, struct module_kobject, kobj); - /* remember our module structure */ - drv->mkobj = mk; - /* kset_find_obj took a reference */ - kobject_put(mkobj); - } - } - - if (!mk) - return; - - /* Don't check return codes; these calls are idempotent */ - no_warn = sysfs_create_link(&drv->kobj, &mk->kobj, "module"); - driver_name = make_driver_name(drv); - if (driver_name) { - module_create_drivers_dir(mk); - no_warn = sysfs_create_link(mk->drivers_dir, &drv->kobj, - driver_name); - kfree(driver_name); - } -} -EXPORT_SYMBOL(module_add_driver); - -void module_remove_driver(struct device_driver *drv) -{ - struct module_kobject *mk = NULL; - char *driver_name; - - if (!drv) - return; - - sysfs_remove_link(&drv->kobj, "module"); - - if (drv->owner) - mk = &drv->owner->mkobj; - else if (drv->mkobj) - mk = drv->mkobj; - if (mk && mk->drivers_dir) { - driver_name = make_driver_name(drv); - if (driver_name) { - sysfs_remove_link(mk->drivers_dir, driver_name); - kfree(driver_name); - } - } -} -EXPORT_SYMBOL(module_remove_driver); -#endif - #ifdef CONFIG_MODVERSIONS /* Generate the signature for struct module here, too, for modversions. */ void struct_module(struct module *mod) { return; } -- cgit v1.2.3 From 97c146ef075dc40ae34407c03d3860fc3850b8e8 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 29 Nov 2007 23:46:11 +0100 Subject: sysfs: fix /sys/module/*/holders after sysfs logic change Sysfs symlinks now require fully registered kobjects as a target, otherwise the call to create a symlink will fail. Here we register the kobject before we request the symlink in the holders directory. Signed-off-by: Kay Sievers Cc: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'kernel') diff --git a/kernel/module.c b/kernel/module.c index dc4d3f5ce820..0ae811785c59 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1227,6 +1227,8 @@ int mod_sysfs_init(struct module *mod) kobject_init(&mod->mkobj.kobj); + /* delay uevent until full sysfs population */ + err = kobject_add(&mod->mkobj.kobj); out: return err; } @@ -1237,11 +1239,6 @@ int mod_sysfs_setup(struct module *mod, { int err; - /* delay uevent until full sysfs population */ - err = kobject_add(&mod->mkobj.kobj); - if (err) - goto out; - mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj); if (!mod->holders_dir) { err = -ENOMEM; @@ -1266,7 +1263,6 @@ out_unreg_holders: out_unreg: kobject_del(&mod->mkobj.kobj); kobject_put(&mod->mkobj.kobj); -out: return err; } #endif @@ -1883,10 +1879,10 @@ static struct module *load_module(void __user *umod, /* Now we've moved module, initialize linked lists, etc. */ module_unload_init(mod); - /* Initialize kobject, so we can reference it. */ + /* add kobject, so we can reference it. */ err = mod_sysfs_init(mod); if (err) - goto cleanup; + goto free_unload; /* Set up license info based on the info section */ set_license(mod, get_modinfo(sechdrs, infoindex, "license")); @@ -2056,6 +2052,9 @@ static struct module *load_module(void __user *umod, arch_cleanup: module_arch_cleanup(mod); cleanup: + kobject_del(&mod->mkobj.kobj); + kobject_put(&mod->mkobj.kobj); + free_unload: module_unload_free(mod); module_free(mod, mod->module_init); free_core: -- cgit v1.2.3 From ac3c8141f62f357169980ec21b7be6d29964a394 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Dec 2007 23:05:35 -0700 Subject: Kobject: convert kernel/module.c to use kobject_init/add_ng() This converts the code to use the new kobject functions, cleaning up the logic in doing so. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'kernel') diff --git a/kernel/module.c b/kernel/module.c index 0ae811785c59..89cd4c7361d8 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1217,18 +1217,16 @@ int mod_sysfs_init(struct module *mod) err = -EINVAL; goto out; } - memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); - err = kobject_set_name(&mod->mkobj.kobj, "%s", mod->name); - if (err) - goto out; - mod->mkobj.kobj.kset = module_kset; - mod->mkobj.kobj.ktype = &module_ktype; mod->mkobj.mod = mod; - kobject_init(&mod->mkobj.kobj); + memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); + mod->mkobj.kobj.kset = module_kset; + err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL, + "%s", mod->name); + if (err) + kobject_put(&mod->mkobj.kobj); /* delay uevent until full sysfs population */ - err = kobject_add(&mod->mkobj.kobj); out: return err; } -- cgit v1.2.3 From 7a6a41615bfb2f03ce797bc24104c50b42c935e5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 22 Dec 2007 21:18:25 -0800 Subject: Modules: remove unneeded release function Now that kobjects properly clean up their name structures, no matter if they have a release function or not, we can drop this empty module kobject release function too (it was needed prior to this because of the way we handled static kobject names, we based the fact that if a release function was present, then we could safely free the name string, now we are more smart about things and only free names we have previously set.) Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/params.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'kernel') diff --git a/kernel/params.c b/kernel/params.c index 1078b148ca80..b4da9505f4d2 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -694,18 +694,8 @@ static struct kset_uevent_ops module_uevent_ops = { struct kset *module_kset; int module_sysfs_initialized; -static void module_release(struct kobject *kobj) -{ - /* - * Stupid empty release function to allow the memory for the kobject to - * be properly cleaned up. This will not need to be present for 2.6.25 - * with the upcoming kobject core rework. - */ -} - struct kobj_type module_ktype = { .sysfs_ops = &module_sysfs_ops, - .release = module_release, }; /* -- cgit v1.2.3 From 78a2d906b40fe530ea800c1e873bfe8f02326f1e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 20 Dec 2007 08:13:05 -0800 Subject: Kobject: convert remaining kobject_unregister() to kobject_put() There is no need for kobject_unregister() anymore, thanks to Kay's kobject cleanup changes, so replace all instances of it with kobject_put(). Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/ksysfs.c | 2 +- kernel/module.c | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'kernel') diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 1081aff5fb9e..e53bc30e9ba5 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -154,7 +154,7 @@ notes_exit: group_exit: sysfs_remove_group(kernel_kobj, &kernel_attr_group); kset_exit: - kobject_unregister(kernel_kobj); + kobject_put(kernel_kobj); exit: return error; } diff --git a/kernel/module.c b/kernel/module.c index 89cd4c7361d8..dcb8a2cbf75e 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1257,9 +1257,8 @@ int mod_sysfs_setup(struct module *mod, out_unreg_param: module_param_sysfs_remove(mod); out_unreg_holders: - kobject_unregister(mod->holders_dir); + kobject_put(mod->holders_dir); out_unreg: - kobject_del(&mod->mkobj.kobj); kobject_put(&mod->mkobj.kobj); return err; } @@ -1269,9 +1268,9 @@ static void mod_kobject_remove(struct module *mod) { module_remove_modinfo_attrs(mod); module_param_sysfs_remove(mod); - kobject_unregister(mod->mkobj.drivers_dir); - kobject_unregister(mod->holders_dir); - kobject_unregister(&mod->mkobj.kobj); + kobject_put(mod->mkobj.drivers_dir); + kobject_put(mod->holders_dir); + kobject_put(&mod->mkobj.kobj); } /* -- cgit v1.2.3 From af5ca3f4ec5cc4432a42a73b050dd8898ce8fd00 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 20 Dec 2007 02:09:39 +0100 Subject: Driver core: change sysdev classes to use dynamic kobject names All kobjects require a dynamically allocated name now. We no longer need to keep track if the name is statically assigned, we can just unconditionally free() all kobject names on cleanup. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/rtmutex-tester.c | 2 +- kernel/time/clocksource.c | 2 +- kernel/time/timekeeping.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'kernel') diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c index e3055ba69159..092e4c620af9 100644 --- a/kernel/rtmutex-tester.c +++ b/kernel/rtmutex-tester.c @@ -394,7 +394,7 @@ static SYSDEV_ATTR(status, 0600, sysfs_test_status, NULL); static SYSDEV_ATTR(command, 0600, NULL, sysfs_test_command); static struct sysdev_class rttest_sysclass = { - set_kset_name("rttest"), + .name = "rttest", }; static int init_test_thread(int id) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index c8a9d13874df..8d6125ad2cf0 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -441,7 +441,7 @@ static SYSDEV_ATTR(available_clocksource, 0600, sysfs_show_available_clocksources, NULL); static struct sysdev_class clocksource_sysclass = { - set_kset_name("clocksource"), + .name = "clocksource", }; static struct sys_device device_clocksource = { diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index e5e466b27598..ab46ae8c062b 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -335,9 +335,9 @@ static int timekeeping_suspend(struct sys_device *dev, pm_message_t state) /* sysfs resume/suspend bits for timekeeping */ static struct sysdev_class timekeeping_sysclass = { + .name = "timekeeping", .resume = timekeeping_resume, .suspend = timekeeping_suspend, - set_kset_name("timekeeping"), }; static struct sys_device device_timer = { -- cgit v1.2.3 From 6ea6dd93c9454cc9521134f907bc970d09f460e4 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 27 Nov 2007 13:02:40 +0100 Subject: ptrace: Call arch_ptrace_attach() when request=PTRACE_TRACEME arch_ptrace_attach() is a hook that allows the architecture to do book-keeping after a ptrace attach. This patch adds a call to this hook when handling a PTRACE_TRACEME request as well. Currently only one architecture, m32r, implements this hook. When called, it initializes a number of debug trap slots in the ptraced task's thread struct, and it looks to me like this is the right thing to do after a PTRACE_TRACEME request as well, not only after PTRACE_ATTACH. Please correct me if I'm wrong. I want to use this hook on AVR32 to turn the debugging hardware on when a process is actually being debugged and keep it off otherwise. To be able to do this, I need to intercept PTRACE_TRACEME and PTRACE_ATTACH, as well as PTRACE_DETACH and thread exit. The latter two can be handled by existing hooks. Signed-off-by: Haavard Skinnemoen --- kernel/ptrace.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'kernel') diff --git a/kernel/ptrace.c b/kernel/ptrace.c index c25db863081d..c719bb9d79ab 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -470,6 +470,8 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) lock_kernel(); if (request == PTRACE_TRACEME) { ret = ptrace_traceme(); + if (!ret) + arch_ptrace_attach(current); goto out; } -- cgit v1.2.3 From 32a76006683f7b28ae3cc491da37716e002f198e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 25 Jan 2008 21:07:58 +0100 Subject: printk: make printk more robust by not allowing recursion make printk more robust by allowing recursion only if there's a crash going on. Also add recursion detection. I've tested it with an artificially injected printk recursion - instead of a lockup or spontaneous reboot or other crash, the output was a well controlled: [ 41.057335] SysRq : <2>BUG: recent printk recursion! [ 41.057335] loglevel0-8 reBoot Crashdump show-all-locks(D) tErm Full kIll saK showMem Nice powerOff showPc show-all-timers(Q) unRaw Sync showTasks Unmount shoW-blocked-tasks also do all this printk-debug logic with irqs disabled. Signed-off-by: Ingo Molnar Reviewed-by: Nick Piggin --- kernel/printk.c | 48 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) (limited to 'kernel') diff --git a/kernel/printk.c b/kernel/printk.c index 89011bf8c106..e6c1f36d8c3a 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -628,30 +628,57 @@ asmlinkage int printk(const char *fmt, ...) /* cpu currently holding logbuf_lock */ static volatile unsigned int printk_cpu = UINT_MAX; +const char printk_recursion_bug_msg [] = + KERN_CRIT "BUG: recent printk recursion!\n"; +static int printk_recursion_bug; + asmlinkage int vprintk(const char *fmt, va_list args) { + static int log_level_unknown = 1; + static char printk_buf[1024]; + unsigned long flags; - int printed_len; + int printed_len = 0; + int this_cpu; char *p; - static char printk_buf[1024]; - static int log_level_unknown = 1; boot_delay_msec(); preempt_disable(); - if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id()) - /* If a crash is occurring during printk() on this CPU, - * make sure we can't deadlock */ - zap_locks(); - /* This stops the holder of console_sem just where we want him */ raw_local_irq_save(flags); + this_cpu = smp_processor_id(); + + /* + * Ouch, printk recursed into itself! + */ + if (unlikely(printk_cpu == this_cpu)) { + /* + * If a crash is occurring during printk() on this CPU, + * then try to get the crash message out but make sure + * we can't deadlock. Otherwise just return to avoid the + * recursion and return - but flag the recursion so that + * it can be printed at the next appropriate moment: + */ + if (!oops_in_progress) { + printk_recursion_bug = 1; + goto out_restore_irqs; + } + zap_locks(); + } + lockdep_off(); spin_lock(&logbuf_lock); - printk_cpu = smp_processor_id(); + printk_cpu = this_cpu; + if (printk_recursion_bug) { + printk_recursion_bug = 0; + strcpy(printk_buf, printk_recursion_bug_msg); + printed_len = sizeof(printk_recursion_bug_msg); + } /* Emit the output into the temporary buffer */ - printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args); + printed_len += vscnprintf(printk_buf + printed_len, + sizeof(printk_buf), fmt, args); /* * Copy the output into log_buf. If the caller didn't provide @@ -744,6 +771,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) printk_cpu = UINT_MAX; spin_unlock(&logbuf_lock); lockdep_on(); +out_restore_irqs: raw_local_irq_restore(flags); } -- cgit v1.2.3 From d713f519332e029d43eca8462629314eee1ded86 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 25 Jan 2008 21:07:58 +0100 Subject: sched: fix CONFIG_PRINT_TIME's reliance on sched_clock() Stefano Brivio reported weird printk timestamp behavior during CPU frequency changes: http://bugzilla.kernel.org/show_bug.cgi?id=9475 fix CONFIG_PRINT_TIME's reliance on sched_clock() and use cpu_clock() instead. Reported-and-bisected-by: Stefano Brivio Signed-off-by: Ingo Molnar --- kernel/printk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/printk.c b/kernel/printk.c index e6c1f36d8c3a..5f9d053699f9 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -707,7 +707,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) loglev_char = default_message_loglevel + '0'; } - t = printk_clock(); + t = cpu_clock(printk_cpu); nanosec_rem = do_div(t, 1000000000); tlen = sprintf(tbuf, "<%c>[%5lu.%06lu] ", -- cgit v1.2.3 From b842271fbb9c8b5fd0e1c3e1895a3b67ba5bcc54 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 25 Jan 2008 21:07:59 +0100 Subject: sched: remove printk_clock() printk_clock() is obsolete - it has been replaced with cpu_clock(). Signed-off-by: Ingo Molnar --- kernel/printk.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'kernel') diff --git a/kernel/printk.c b/kernel/printk.c index 5f9d053699f9..3b7c968d0ef9 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -573,11 +573,6 @@ static int __init printk_time_setup(char *str) __setup("time", printk_time_setup); -__attribute__((weak)) unsigned long long printk_clock(void) -{ - return sched_clock(); -} - /* Check if we have any console registered that can be called early in boot. */ static int have_callable_console(void) { -- cgit v1.2.3 From 93f992ccc008dd4030381caeebb252e85e66684b Mon Sep 17 00:00:00 2001 From: Srivatsa Vaddagiri Date: Fri, 25 Jan 2008 21:07:59 +0100 Subject: sched: group scheduling code cleanup Minor cleanups: - Fix coding style - remove obsolete comment Signed-off-by: Srivatsa Vaddagiri Signed-off-by: Ingo Molnar --- kernel/sched.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'kernel') diff --git a/kernel/sched.c b/kernel/sched.c index e76b11ca6df3..7f827b70ae02 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -191,12 +191,12 @@ struct task_group init_task_group = { }; #ifdef CONFIG_FAIR_USER_SCHED -# define INIT_TASK_GRP_LOAD 2*NICE_0_LOAD +# define INIT_TASK_GROUP_LOAD 2*NICE_0_LOAD #else -# define INIT_TASK_GRP_LOAD NICE_0_LOAD +# define INIT_TASK_GROUP_LOAD NICE_0_LOAD #endif -static int init_task_group_load = INIT_TASK_GRP_LOAD; +static int init_task_group_load = INIT_TASK_GROUP_LOAD; /* return group to which a task belongs */ static inline struct task_group *task_group(struct task_struct *p) @@ -881,21 +881,6 @@ static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {} #define sched_class_highest (&rt_sched_class) -/* - * Update delta_exec, delta_fair fields for rq. - * - * delta_fair clock advances at a rate inversely proportional to - * total load (rq->load.weight) on the runqueue, while - * delta_exec advances at the same rate as wall-clock (provided - * cpu is not idle). - * - * delta_exec / delta_fair is a measure of the (smoothened) load on this - * runqueue over any given interval. This (smoothened) load is used - * during load balance. - * - * This function is called /before/ updating rq->load - * and when switching tasks. - */ static inline void inc_load(struct rq *rq, const struct task_struct *p) { update_load_add(&rq->load, p->se.load.weight); -- cgit v1.2.3 From ec2c507fe8c8fa3c04fc6cb99a382a965c477379 Mon Sep 17 00:00:00 2001 From: Srivatsa Vaddagiri Date: Fri, 25 Jan 2008 21:07:59 +0100 Subject: sched: group scheduling, minor fixes Minor bug fixes for the group scheduler: - Use a mutex to serialize add/remove of task groups and also when changing shares of a task group. Use the same mutex when printing cfs_rq debugging stats for various task groups. - Use list_for_each_entry_rcu in for_each_leaf_cfs_rq macro (when walking task group list) Signed-off-by: Srivatsa Vaddagiri Signed-off-by: Ingo Molnar --- kernel/sched.c | 33 +++++++++++++++++++++++++-------- kernel/sched_fair.c | 4 +++- 2 files changed, 28 insertions(+), 9 deletions(-) (limited to 'kernel') diff --git a/kernel/sched.c b/kernel/sched.c index 7f827b70ae02..cfa695819252 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -169,8 +169,6 @@ struct task_group { /* runqueue "owned" by this group on each cpu */ struct cfs_rq **cfs_rq; unsigned long shares; - /* spinlock to serialize modification to shares */ - spinlock_t lock; struct rcu_head rcu; }; @@ -182,6 +180,11 @@ static DEFINE_PER_CPU(struct cfs_rq, init_cfs_rq) ____cacheline_aligned_in_smp; static struct sched_entity *init_sched_entity_p[NR_CPUS]; static struct cfs_rq *init_cfs_rq_p[NR_CPUS]; +/* task_group_mutex serializes add/remove of task groups and also changes to + * a task group's cpu shares. + */ +static DEFINE_MUTEX(task_group_mutex); + /* Default task group. * Every task in system belong to this group at bootup. */ @@ -221,9 +224,21 @@ static inline void set_task_cfs_rq(struct task_struct *p, unsigned int cpu) p->se.parent = task_group(p)->se[cpu]; } +static inline void lock_task_group_list(void) +{ + mutex_lock(&task_group_mutex); +} + +static inline void unlock_task_group_list(void) +{ + mutex_unlock(&task_group_mutex); +} + #else static inline void set_task_cfs_rq(struct task_struct *p, unsigned int cpu) { } +static inline void lock_task_group_list(void) { } +static inline void unlock_task_group_list(void) { } #endif /* CONFIG_FAIR_GROUP_SCHED */ @@ -6768,7 +6783,6 @@ void __init sched_init(void) se->parent = NULL; } init_task_group.shares = init_task_group_load; - spin_lock_init(&init_task_group.lock); #endif for (j = 0; j < CPU_LOAD_IDX_MAX; j++) @@ -7008,14 +7022,15 @@ struct task_group *sched_create_group(void) se->parent = NULL; } + tg->shares = NICE_0_LOAD; + + lock_task_group_list(); for_each_possible_cpu(i) { rq = cpu_rq(i); cfs_rq = tg->cfs_rq[i]; list_add_rcu(&cfs_rq->leaf_cfs_rq_list, &rq->leaf_cfs_rq_list); } - - tg->shares = NICE_0_LOAD; - spin_lock_init(&tg->lock); + unlock_task_group_list(); return tg; @@ -7061,10 +7076,12 @@ void sched_destroy_group(struct task_group *tg) struct cfs_rq *cfs_rq = NULL; int i; + lock_task_group_list(); for_each_possible_cpu(i) { cfs_rq = tg->cfs_rq[i]; list_del_rcu(&cfs_rq->leaf_cfs_rq_list); } + unlock_task_group_list(); BUG_ON(!cfs_rq); @@ -7146,7 +7163,7 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares) if (shares < 2) shares = 2; - spin_lock(&tg->lock); + lock_task_group_list(); if (tg->shares == shares) goto done; @@ -7155,7 +7172,7 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares) set_se_shares(tg->se[i], shares); done: - spin_unlock(&tg->lock); + unlock_task_group_list(); return 0; } diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index da7c061e7206..0c5fdce67228 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -690,7 +690,7 @@ static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu) /* Iterate thr' all leaf cfs_rq's on a runqueue */ #define for_each_leaf_cfs_rq(rq, cfs_rq) \ - list_for_each_entry(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list) + list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list) /* Do the two (enqueued) entities belong to the same group ? */ static inline int @@ -1132,7 +1132,9 @@ static void print_cfs_stats(struct seq_file *m, int cpu) #ifdef CONFIG_FAIR_GROUP_SCHED print_cfs_rq(m, cpu, &cpu_rq(cpu)->cfs); #endif + lock_task_group_list(); for_each_leaf_cfs_rq(cpu_rq(cpu), cfs_rq) print_cfs_rq(m, cpu, cfs_rq); + unlock_task_group_list(); } #endif -- cgit v1.2.3 From 58e2d4ca581167c2a079f4ee02be2f0bc52e8729 Mon Sep 17 00:00:00 2001 From: Srivatsa Vaddagiri Date: Fri, 25 Jan 2008 21:08:00 +0100 Subject: sched: group scheduling, change how cpu load is calculated This patch changes how the cpu load exerted by fair_sched_class tasks is calculated. Load exerted by fair_sched_class tasks on a cpu is now a summation of the group weights, rather than summation of task weights. Weight exerted by a group on a cpu is dependent on the shares allocated to it. This version of patch has a minor impact on code size, but should have no runtime/functional impact for !CONFIG_FAIR_GROUP_SCHED. Signed-off-by: Srivatsa Vaddagiri Signed-off-by: Ingo Molnar --- kernel/sched.c | 27 +++++++++++---------------- kernel/sched_fair.c | 31 +++++++++++++++++++++++++++---- kernel/sched_rt.c | 2 ++ 3 files changed, 40 insertions(+), 20 deletions(-) (limited to 'kernel') diff --git a/kernel/sched.c b/kernel/sched.c index cfa695819252..c915f3e6e593 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -886,6 +886,16 @@ static void cpuacct_charge(struct task_struct *tsk, u64 cputime); static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {} #endif +static inline void inc_cpu_load(struct rq *rq, unsigned long load) +{ + update_load_add(&rq->load, load); +} + +static inline void dec_cpu_load(struct rq *rq, unsigned long load) +{ + update_load_sub(&rq->load, load); +} + #include "sched_stats.h" #include "sched_idletask.c" #include "sched_fair.c" @@ -896,26 +906,14 @@ static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {} #define sched_cla