diff -uprN linux-2.6.22.14-CFS-v24/include/linux/sched.h linux-2.6.22.14-CFS-v24-fix/include/linux/sched.h --- linux-2.6.22.14-CFS-v24/include/linux/sched.h 2007-12-11 16:59:41.000000000 +0000 +++ linux-2.6.22.14-CFS-v24-fix/include/linux/sched.h 2007-12-11 16:55:27.000000000 +0000 @@ -586,18 +586,13 @@ struct user_struct { #ifdef CONFIG_FAIR_USER_SCHED struct task_group *tg; #ifdef CONFIG_SYSFS - struct kset kset; - struct subsys_attribute user_attr; + struct kobject kobj; struct work_struct work; #endif #endif }; -#ifdef CONFIG_FAIR_USER_SCHED -extern int uids_kobject_init(void); -#else -static inline int uids_kobject_init(void) { return 0; } -#endif +extern int uids_sysfs_init(void); extern struct user_struct *find_user(uid_t); diff -uprN linux-2.6.22.14-CFS-v24/kernel/ksysfs.c linux-2.6.22.14-CFS-v24-fix/kernel/ksysfs.c --- linux-2.6.22.14-CFS-v24/kernel/ksysfs.c 2007-12-11 16:59:41.000000000 +0000 +++ linux-2.6.22.14-CFS-v24-fix/kernel/ksysfs.c 2007-12-11 16:55:27.000000000 +0000 @@ -89,12 +89,9 @@ static int __init ksysfs_init(void) error = sysfs_create_group(&kernel_subsys.kobj, &kernel_attr_group); - /* - * Create "/sys/kernel/uids" directory and corresponding root user's - * directory under it. - */ + /* create the /sys/kernel/uids/ directory */ if (!error) - error = uids_kobject_init(); + error = uids_sysfs_init(); return error; } diff -uprN linux-2.6.22.14-CFS-v24/kernel/user.c linux-2.6.22.14-CFS-v24-fix/kernel/user.c --- linux-2.6.22.14-CFS-v24/kernel/user.c 2007-12-11 16:59:41.000000000 +0000 +++ linux-2.6.22.14-CFS-v24-fix/kernel/user.c 2007-12-11 16:57:02.000000000 +0000 @@ -87,7 +87,6 @@ static inline struct user_struct *uid_ha #ifdef CONFIG_FAIR_USER_SCHED -static struct kobject uids_kobject; /* represents /sys/kernel/uids directory */ static DEFINE_MUTEX(uids_mutex); static void sched_destroy_user(struct user_struct *up) @@ -121,83 +120,104 @@ static inline void uids_mutex_unlock(voi mutex_unlock(&uids_mutex); } -/* return cpu shares held by the user */ -ssize_t cpu_shares_show(struct kset *kset, char *buffer) +/* uid directory attributes */ +static ssize_t cpu_shares_show(struct kobject *kobj, + struct 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 */ -ssize_t cpu_shares_store(struct kset *kset, const char *buffer, size_t size) +static ssize_t cpu_shares_store(struct kobject *kobj, + struct 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) -{ - sa->attr.name = name; - sa->attr.mode = mode; - sa->show = cpu_shares_show; - sa->store = cpu_shares_store; -} - -/* Create "/sys/kernel/uids/" directory and - * "/sys/kernel/uids//cpu_share" file for this user. - */ -static int user_kobject_create(struct user_struct *up) -{ - struct kset *kset = &up->kset; - struct kobject *kobj = &kset->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); - +static struct attribute cpu_share_attr = { + .name = "cpu_share", + .mode = 0644 + }; + +/* default attributes per uid directory */ +static struct attribute *uids_attributes[] = { + &cpu_share_attr, + NULL +}; + +/* the lifetime of user_struct is not managed by the core (now) */ +static void uids_release(struct kobject *kobj) +{ + return; +} + +static struct sysfs_ops uids_attributes_ops = { + .show = cpu_shares_show, + .store = cpu_shares_store, +}; + +static struct kobj_type uids_ktype = { + .sysfs_ops = &uids_attributes_ops, + .release = uids_release, +}; + +/* represents the /sys/kernel/uids/ directory */ +static struct kset uids_kset = { + .kobj = {.ktype = &uids_ktype}, +}; + +/* create /sys/kernel/uids//cpu_share file for this user */ +static int uids_user_create(struct user_struct *up) +{ + struct kobject *kobj = &up->kobj; + int error, i = 0; + + memset(kobj, 0, sizeof(struct kobject)); + kobject_init(kobj); + kobj->ktype = &uids_ktype; + kobj->kset = &uids_kset; + 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); + while (uids_attributes[i]) { + error = sysfs_create_file(kobj, uids_attributes[i++]); + if (error) + goto done; + } 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; - /* create under /sys/kernel dir */ - uids_kobject.parent = &kernel_subsys.kobj; - uids_kobject.kset = &kernel_subsys; - kobject_set_name(&uids_kobject, "uids"); - kobject_init(&uids_kobject); + kobject_set_name(&uids_kset.kobj, "uids"); + kobj_set_kset_s(&uids_kset, kernel_subsys); - error = kobject_add(&uids_kobject); + error = kset_register(&uids_kset); if (!error) - error = user_kobject_create(&root_user); + error = uids_user_create(&root_user); return error; } @@ -208,9 +228,8 @@ 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; + int remove_user = 0, i = 0; /* Make uid_hash_remove() + sysfs_remove_file() + kobject_del() * atomic. @@ -230,9 +249,12 @@ static void remove_user_sysfs_dir(struct if (!remove_user) goto done; - sysfs_remove_file(kobj, &up->user_attr.attr); - kobject_uevent(kobj, KOBJ_REMOVE); - kobject_del(kobj); + while (uids_attributes[i]) + sysfs_remove_file(&up->kobj, uids_attributes[i++]); + + kobject_uevent(&up->kobj, KOBJ_REMOVE); + kobject_del(&up->kobj); + kobject_put(&up->kobj); sched_destroy_user(up); key_put(up->uid_keyring); @@ -262,7 +284,8 @@ static inline void free_user(struct user static void sched_destroy_user(struct user_struct *up) { } static int sched_create_user(struct user_struct *up) { return 0; } static void sched_switch_user(struct task_struct *p) { } -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) { } @@ -319,7 +342,7 @@ struct user_struct * alloc_uid(struct us 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(); @@ -359,7 +382,7 @@ struct user_struct * alloc_uid(struct us 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);