aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h9
-rw-r--r--kernel/ksysfs.c7
-rw-r--r--kernel/user.c104
3 files changed, 55 insertions, 65 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index cc14656f8682..d6eacda765ca 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -552,18 +552,13 @@ struct user_struct {
552#ifdef CONFIG_FAIR_USER_SCHED 552#ifdef CONFIG_FAIR_USER_SCHED
553 struct task_group *tg; 553 struct task_group *tg;
554#ifdef CONFIG_SYSFS 554#ifdef CONFIG_SYSFS
555 struct kset kset; 555 struct kobject kobj;
556 struct subsys_attribute user_attr;
557 struct work_struct work; 556 struct work_struct work;
558#endif 557#endif
559#endif 558#endif
560}; 559};
561 560
562#ifdef CONFIG_FAIR_USER_SCHED 561extern int uids_sysfs_init(void);
563extern int uids_kobject_init(void);
564#else
565static inline int uids_kobject_init(void) { return 0; }
566#endif
567 562
568extern struct user_struct *find_user(uid_t); 563extern struct user_struct *find_user(uid_t);
569 564
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)
141 goto group_exit; 141 goto group_exit;
142 } 142 }
143 143
144 /* 144 /* create the /sys/kernel/uids/ directory */
145 * Create "/sys/kernel/uids" directory and corresponding root user's 145 error = uids_sysfs_init();
146 * directory under it.
147 */
148 error = uids_kobject_init();
149 if (error) 146 if (error)
150 goto notes_exit; 147 goto notes_exit;
151 148
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
118static struct kobject uids_kobject; /* represents /sys/kernel/uids directory */ 118static struct kset *uids_kset; /* represents the /sys/kernel/uids/ directory */
119static DEFINE_MUTEX(uids_mutex); 119static DEFINE_MUTEX(uids_mutex);
120 120
121static inline void uids_mutex_lock(void) 121static 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 */
132static ssize_t cpu_shares_show(struct kset *kset, char *buffer) 132static 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 */ 141static ssize_t cpu_shares_store(struct kobject *kobj,
140static 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
154static void user_attr_init(struct subsys_attribute *sa, char *name, int mode) 156static struct kobj_attribute cpu_share_attr =
157 __ATTR(cpu_share, 0644, cpu_shares_show, cpu_shares_store);
158
159/* default attributes per uid directory */
160static 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) */
166static 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 171static 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,
165static 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 */
178static 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
187done: 193done:
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 */
196int __init uids_kobject_init(void) 202int __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)
216static void remove_user_sysfs_dir(struct work_struct *w) 214static 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
270static inline int user_kobject_create(struct user_struct *up) { return 0; } 267int uids_sysfs_init(void) { return 0; }
268static inline int uids_user_create(struct user_struct *up) { return 0; }
271static inline void uids_mutex_lock(void) { } 269static inline void uids_mutex_lock(void) { }
272static inline void uids_mutex_unlock(void) { } 270static 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);