diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2007-11-02 08:47:53 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-01-24 23:40:18 -0500 |
commit | eb41d9465cdafee45e0cb30f3b7338646221908e (patch) | |
tree | a2e5d62c8b1bd48d5b20515b541096709fe184e0 /kernel/user.c | |
parent | 386f275f5d097758f867bc99ddeaeb7a03b6b190 (diff) |
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 <dhaval@linux.vnet.ibm.com>
Cc: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'kernel/user.c')
-rw-r--r-- | kernel/user.c | 104 |
1 files changed, 51 insertions, 53 deletions
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) { } | |||
115 | 115 | ||
116 | #if defined(CONFIG_FAIR_USER_SCHED) && defined(CONFIG_SYSFS) | 116 | #if defined(CONFIG_FAIR_USER_SCHED) && defined(CONFIG_SYSFS) |
117 | 117 | ||
118 | static struct kobject uids_kobject; /* represents /sys/kernel/uids directory */ | 118 | static struct kset *uids_kset; /* represents the /sys/kernel/uids/ directory */ |
119 | static DEFINE_MUTEX(uids_mutex); | 119 | static DEFINE_MUTEX(uids_mutex); |
120 | 120 | ||
121 | static inline void uids_mutex_lock(void) | 121 | static inline void uids_mutex_lock(void) |
@@ -128,86 +128,84 @@ static inline void uids_mutex_unlock(void) | |||
128 | mutex_unlock(&uids_mutex); | 128 | mutex_unlock(&uids_mutex); |
129 | } | 129 | } |
130 | 130 | ||
131 | /* return cpu shares held by the user */ | 131 | /* uid directory attributes */ |
132 | static ssize_t cpu_shares_show(struct kset *kset, char *buffer) | 132 | static ssize_t cpu_shares_show(struct kobject *kobj, |
133 | struct kobj_attribute *attr, | ||
134 | char *buf) | ||
133 | { | 135 | { |
134 | struct user_struct *up = container_of(kset, struct user_struct, kset); | 136 | struct user_struct *up = container_of(kobj, struct user_struct, kobj); |
135 | 137 | ||
136 | return sprintf(buffer, "%lu\n", sched_group_shares(up->tg)); | 138 | return sprintf(buf, "%lu\n", sched_group_shares(up->tg)); |
137 | } | 139 | } |
138 | 140 | ||
139 | /* modify cpu shares held by the user */ | 141 | static ssize_t cpu_shares_store(struct kobject *kobj, |
140 | static ssize_t cpu_shares_store(struct kset *kset, const char *buffer, | 142 | struct kobj_attribute *attr, |
141 | size_t size) | 143 | const char *buf, size_t size) |
142 | { | 144 | { |
143 | struct user_struct *up = container_of(kset, struct user_struct, kset); | 145 | struct user_struct *up = container_of(kobj, struct user_struct, kobj); |
144 | unsigned long shares; | 146 | unsigned long shares; |
145 | int rc; | 147 | int rc; |
146 | 148 | ||
147 | sscanf(buffer, "%lu", &shares); | 149 | sscanf(buf, "%lu", &shares); |
148 | 150 | ||
149 | rc = sched_group_set_shares(up->tg, shares); | 151 | rc = sched_group_set_shares(up->tg, shares); |
150 | 152 | ||
151 | return (rc ? rc : size); | 153 | return (rc ? rc : size); |
152 | } | 154 | } |
153 | 155 | ||
154 | static void user_attr_init(struct subsys_attribute *sa, char *name, int mode) | 156 | static struct kobj_attribute cpu_share_attr = |
157 | __ATTR(cpu_share, 0644, cpu_shares_show, cpu_shares_store); | ||
158 | |||
159 | /* default attributes per uid directory */ | ||
160 | static struct attribute *uids_attributes[] = { | ||
161 | &cpu_share_attr.attr, | ||
162 | NULL | ||
163 | }; | ||
164 | |||
165 | /* the lifetime of user_struct is not managed by the core (now) */ | ||
166 | static void uids_release(struct kobject *kobj) | ||
155 | { | 167 | { |
156 | sa->attr.name = name; | 168 | return; |
157 | sa->attr.mode = mode; | ||
158 | sa->show = cpu_shares_show; | ||
159 | sa->store = cpu_shares_store; | ||
160 | } | 169 | } |
161 | 170 | ||
162 | /* Create "/sys/kernel/uids/<uid>" directory and | 171 | static struct kobj_type uids_ktype = { |
163 | * "/sys/kernel/uids/<uid>/cpu_share" file for this user. | 172 | .sysfs_ops = &kobj_sysfs_ops, |
164 | */ | 173 | .default_attrs = uids_attributes, |
165 | static int user_kobject_create(struct user_struct *up) | 174 | .release = uids_release, |
175 | }; | ||
176 | |||
177 | /* create /sys/kernel/uids/<uid>/cpu_share file for this user */ | ||
178 | static int uids_user_create(struct user_struct *up) | ||
166 | { | 179 | { |
167 | struct kset *kset = &up->kset; | 180 | struct kobject *kobj = &up->kobj; |
168 | struct kobject *kobj = &kset->kobj; | ||
169 | int error; | 181 | int error; |
170 | 182 | ||
171 | memset(kset, 0, sizeof(struct kset)); | 183 | memset(kobj, 0, sizeof(struct kobject)); |
172 | kobj->parent = &uids_kobject; /* create under /sys/kernel/uids dir */ | 184 | kobj->ktype = &uids_ktype; |
173 | kobject_set_name(kobj, "%d", up->uid); | 185 | kobj->kset = uids_kset; |
174 | kset_init(kset); | 186 | kobject_init(kobj); |
175 | user_attr_init(&up->user_attr, "cpu_share", 0644); | 187 | kobject_set_name(&up->kobj, "%d", up->uid); |
176 | |||
177 | error = kobject_add(kobj); | 188 | error = kobject_add(kobj); |
178 | if (error) | 189 | if (error) |
179 | goto done; | 190 | goto done; |
180 | 191 | ||
181 | error = sysfs_create_file(kobj, &up->user_attr.attr); | ||
182 | if (error) | ||
183 | kobject_del(kobj); | ||
184 | |||
185 | kobject_uevent(kobj, KOBJ_ADD); | 192 | kobject_uevent(kobj, KOBJ_ADD); |
186 | |||
187 | done: | 193 | done: |
188 | return error; | 194 | return error; |
189 | } | 195 | } |
190 | 196 | ||
191 | /* create these in sysfs filesystem: | 197 | /* create these entries in sysfs: |
192 | * "/sys/kernel/uids" directory | 198 | * "/sys/kernel/uids" directory |
193 | * "/sys/kernel/uids/0" directory (for root user) | 199 | * "/sys/kernel/uids/0" directory (for root user) |
194 | * "/sys/kernel/uids/0/cpu_share" file (for root user) | 200 | * "/sys/kernel/uids/0/cpu_share" file (for root user) |
195 | */ | 201 | */ |
196 | int __init uids_kobject_init(void) | 202 | int __init uids_sysfs_init(void) |
197 | { | 203 | { |
198 | int error; | 204 | uids_kset = kset_create_and_add("uids", NULL, &kernel_kset->kobj); |
205 | if (!uids_kset) | ||
206 | return -ENOMEM; | ||
199 | 207 | ||
200 | /* create under /sys/kernel dir */ | 208 | return uids_user_create(&root_user); |
201 | uids_kobject.parent = &kernel_kset->kobj; | ||
202 | uids_kobject.kset = kernel_kset; | ||
203 | kobject_set_name(&uids_kobject, "uids"); | ||
204 | kobject_init(&uids_kobject); | ||
205 | |||
206 | error = kobject_add(&uids_kobject); | ||
207 | if (!error) | ||
208 | error = user_kobject_create(&root_user); | ||
209 | |||
210 | return error; | ||
211 | } | 209 | } |
212 | 210 | ||
213 | /* work function to remove sysfs directory for a user and free up | 211 | /* work function to remove sysfs directory for a user and free up |
@@ -216,7 +214,6 @@ int __init uids_kobject_init(void) | |||
216 | static void remove_user_sysfs_dir(struct work_struct *w) | 214 | static void remove_user_sysfs_dir(struct work_struct *w) |
217 | { | 215 | { |
218 | struct user_struct *up = container_of(w, struct user_struct, work); | 216 | struct user_struct *up = container_of(w, struct user_struct, work); |
219 | struct kobject *kobj = &up->kset.kobj; | ||
220 | unsigned long flags; | 217 | unsigned long flags; |
221 | int remove_user = 0; | 218 | int remove_user = 0; |
222 | 219 | ||
@@ -238,9 +235,9 @@ static void remove_user_sysfs_dir(struct work_struct *w) | |||
238 | if (!remove_user) | 235 | if (!remove_user) |
239 | goto done; | 236 | goto done; |
240 | 237 | ||
241 | sysfs_remove_file(kobj, &up->user_attr.attr); | 238 | kobject_uevent(&up->kobj, KOBJ_REMOVE); |
242 | kobject_uevent(kobj, KOBJ_REMOVE); | 239 | kobject_del(&up->kobj); |
243 | kobject_del(kobj); | 240 | kobject_put(&up->kobj); |
244 | 241 | ||
245 | sched_destroy_user(up); | 242 | sched_destroy_user(up); |
246 | key_put(up->uid_keyring); | 243 | key_put(up->uid_keyring); |
@@ -267,7 +264,8 @@ static inline void free_user(struct user_struct *up, unsigned long flags) | |||
267 | 264 | ||
268 | #else /* CONFIG_FAIR_USER_SCHED && CONFIG_SYSFS */ | 265 | #else /* CONFIG_FAIR_USER_SCHED && CONFIG_SYSFS */ |
269 | 266 | ||
270 | static inline int user_kobject_create(struct user_struct *up) { return 0; } | 267 | int uids_sysfs_init(void) { return 0; } |
268 | static inline int uids_user_create(struct user_struct *up) { return 0; } | ||
271 | static inline void uids_mutex_lock(void) { } | 269 | static inline void uids_mutex_lock(void) { } |
272 | static inline void uids_mutex_unlock(void) { } | 270 | static inline void uids_mutex_unlock(void) { } |
273 | 271 | ||
@@ -324,7 +322,7 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) | |||
324 | struct hlist_head *hashent = uidhashentry(ns, uid); | 322 | struct hlist_head *hashent = uidhashentry(ns, uid); |
325 | struct user_struct *up; | 323 | struct user_struct *up; |
326 | 324 | ||
327 | /* Make uid_hash_find() + user_kobject_create() + uid_hash_insert() | 325 | /* Make uid_hash_find() + uids_user_create() + uid_hash_insert() |
328 | * atomic. | 326 | * atomic. |
329 | */ | 327 | */ |
330 | uids_mutex_lock(); | 328 | uids_mutex_lock(); |
@@ -370,7 +368,7 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) | |||
370 | return NULL; | 368 | return NULL; |
371 | } | 369 | } |
372 | 370 | ||
373 | if (user_kobject_create(new)) { | 371 | if (uids_user_create(new)) { |
374 | sched_destroy_user(new); | 372 | sched_destroy_user(new); |
375 | key_put(new->uid_keyring); | 373 | key_put(new->uid_keyring); |
376 | key_put(new->session_keyring); | 374 | key_put(new->session_keyring); |