aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDhaval Giani <dhaval.giani@gmail.com>2010-01-20 07:26:18 -0500
committerIngo Molnar <mingo@elte.hu>2010-01-21 07:40:18 -0500
commit7c9414385ebfdd87cc542d4e7e3bb0dbb2d3ce25 (patch)
treebeb51d7d0d543d72e2754cff807df5c399f2d376
parent871e35bc9733f273eaf5ceb69bbd0423b58e5285 (diff)
sched: Remove USER_SCHED
Remove the USER_SCHED feature. It has been scheduled to be removed in 2.6.34 as per http://marc.info/?l=linux-kernel&m=125728479022976&w=2 Signed-off-by: Dhaval Giani <dhaval.giani@gmail.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <1263990378.24844.3.camel@localhost> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--Documentation/feature-removal-schedule.txt15
-rw-r--r--include/linux/sched.h14
-rw-r--r--init/Kconfig81
-rw-r--r--kernel/ksysfs.c8
-rw-r--r--kernel/sched.c114
-rw-r--r--kernel/sys.c5
-rw-r--r--kernel/user.c305
7 files changed, 38 insertions, 504 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 870d190fe617..04a3fc3d139b 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -6,21 +6,6 @@ be removed from this file.
6 6
7--------------------------- 7---------------------------
8 8
9What: USER_SCHED
10When: 2.6.34
11
12Why: USER_SCHED was implemented as a proof of concept for group scheduling.
13 The effect of USER_SCHED can already be achieved from userspace with
14 the help of libcgroup. The removal of USER_SCHED will also simplify
15 the scheduler code with the removal of one major ifdef. There are also
16 issues USER_SCHED has with USER_NS. A decision was taken not to fix
17 those and instead remove USER_SCHED. Also new group scheduling
18 features will not be implemented for USER_SCHED.
19
20Who: Dhaval Giani <dhaval@linux.vnet.ibm.com>
21
22---------------------------
23
24What: PRISM54 9What: PRISM54
25When: 2.6.34 10When: 2.6.34
26 11
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 50d685cde70e..8b079735ae5f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -731,14 +731,6 @@ struct user_struct {
731 uid_t uid; 731 uid_t uid;
732 struct user_namespace *user_ns; 732 struct user_namespace *user_ns;
733 733
734#ifdef CONFIG_USER_SCHED
735 struct task_group *tg;
736#ifdef CONFIG_SYSFS
737 struct kobject kobj;
738 struct delayed_work work;
739#endif
740#endif
741
742#ifdef CONFIG_PERF_EVENTS 734#ifdef CONFIG_PERF_EVENTS
743 atomic_long_t locked_vm; 735 atomic_long_t locked_vm;
744#endif 736#endif
@@ -2502,13 +2494,9 @@ extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
2502 2494
2503extern void normalize_rt_tasks(void); 2495extern void normalize_rt_tasks(void);
2504 2496
2505#ifdef CONFIG_GROUP_SCHED 2497#ifdef CONFIG_CGROUP_SCHED
2506 2498
2507extern struct task_group init_task_group; 2499extern struct task_group init_task_group;
2508#ifdef CONFIG_USER_SCHED
2509extern struct task_group root_task_group;
2510extern void set_tg_uid(struct user_struct *user);
2511#endif
2512 2500
2513extern struct task_group *sched_create_group(struct task_group *parent); 2501extern struct task_group *sched_create_group(struct task_group *parent);
2514extern void sched_destroy_group(struct task_group *tg); 2502extern void sched_destroy_group(struct task_group *tg);
diff --git a/init/Kconfig b/init/Kconfig
index a23da9f01803..e9fa3007a6fc 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -435,57 +435,6 @@ config LOG_BUF_SHIFT
435config HAVE_UNSTABLE_SCHED_CLOCK 435config HAVE_UNSTABLE_SCHED_CLOCK
436 bool 436 bool
437 437
438config GROUP_SCHED
439 bool "Group CPU scheduler"
440 depends on EXPERIMENTAL
441 default n
442 help
443 This feature lets CPU scheduler recognize task groups and control CPU
444 bandwidth allocation to such task groups.
445 In order to create a group from arbitrary set of processes, use
446 CONFIG_CGROUPS. (See Control Group support.)
447
448config FAIR_GROUP_SCHED
449 bool "Group scheduling for SCHED_OTHER"
450 depends on GROUP_SCHED
451 default GROUP_SCHED
452
453config RT_GROUP_SCHED
454 bool "Group scheduling for SCHED_RR/FIFO"
455 depends on EXPERIMENTAL
456 depends on GROUP_SCHED
457 default n
458 help
459 This feature lets you explicitly allocate real CPU bandwidth
460 to users or control groups (depending on the "Basis for grouping tasks"
461 setting below. If enabled, it will also make it impossible to
462 schedule realtime tasks for non-root users until you allocate
463 realtime bandwidth for them.
464 See Documentation/scheduler/sched-rt-group.txt for more information.
465
466choice
467 depends on GROUP_SCHED
468 prompt "Basis for grouping tasks"
469 default USER_SCHED
470
471config USER_SCHED
472 bool "user id"
473 help
474 This option will choose userid as the basis for grouping
475 tasks, thus providing equal CPU bandwidth to each user.
476
477config CGROUP_SCHED
478 bool "Control groups"
479 depends on CGROUPS
480 help
481 This option allows you to create arbitrary task groups
482 using the "cgroup" pseudo filesystem and control
483 the cpu bandwidth allocated to each such task group.
484 Refer to Documentation/cgroups/cgroups.txt for more
485 information on "cgroup" pseudo filesystem.
486
487endchoice
488
489menuconfig CGROUPS 438menuconfig CGROUPS
490 boolean "Control Group support" 439 boolean "Control Group support"
491 help 440 help
@@ -606,6 +555,36 @@ config CGROUP_MEM_RES_CTLR_SWAP
606 Now, memory usage of swap_cgroup is 2 bytes per entry. If swap page 555 Now, memory usage of swap_cgroup is 2 bytes per entry. If swap page
607 size is 4096bytes, 512k per 1Gbytes of swap. 556 size is 4096bytes, 512k per 1Gbytes of swap.
608 557
558menuconfig CGROUP_SCHED
559 bool "Group CPU scheduler"
560 depends on EXPERIMENTAL && CGROUPS
561 default n
562 help
563 This feature lets CPU scheduler recognize task groups and control CPU
564 bandwidth allocation to such task groups. It uses cgroups to group
565 tasks.
566
567if CGROUP_SCHED
568config FAIR_GROUP_SCHED
569 bool "Group scheduling for SCHED_OTHER"
570 depends on CGROUP_SCHED
571 default CGROUP_SCHED
572
573config RT_GROUP_SCHED
574 bool "Group scheduling for SCHED_RR/FIFO"
575 depends on EXPERIMENTAL
576 depends on CGROUP_SCHED
577 default n
578 help
579 This feature lets you explicitly allocate real CPU bandwidth
580 to users or control groups (depending on the "Basis for grouping tasks"
581 setting below. If enabled, it will also make it impossible to
582 schedule realtime tasks for non-root users until you allocate
583 realtime bandwidth for them.
584 See Documentation/scheduler/sched-rt-group.txt for more information.
585
586endif #CGROUP_SCHED
587
609endif # CGROUPS 588endif # CGROUPS
610 589
611config MM_OWNER 590config MM_OWNER
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 3feaf5a74514..6b1ccc3f0205 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -197,16 +197,8 @@ static int __init ksysfs_init(void)
197 goto group_exit; 197 goto group_exit;
198 } 198 }
199 199
200 /* create the /sys/kernel/uids/ directory */
201 error = uids_sysfs_init();
202 if (error)
203 goto notes_exit;
204
205 return 0; 200 return 0;
206 201
207notes_exit:
208 if (notes_size > 0)
209 sysfs_remove_bin_file(kernel_kobj, &notes_attr);
210group_exit: 202group_exit:
211 sysfs_remove_group(kernel_kobj, &kernel_attr_group); 203 sysfs_remove_group(kernel_kobj, &kernel_attr_group);
212kset_exit: 204kset_exit:
diff --git a/kernel/sched.c b/kernel/sched.c
index c0be07932a8d..41e76d325648 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -233,7 +233,7 @@ static void destroy_rt_bandwidth(struct rt_bandwidth *rt_b)
233 */ 233 */
234static DEFINE_MUTEX(sched_domains_mutex); 234static DEFINE_MUTEX(sched_domains_mutex);
235 235
236#ifdef CONFIG_GROUP_SCHED 236#ifdef CONFIG_CGROUP_SCHED
237 237
238#include <linux/cgroup.h> 238#include <linux/cgroup.h>
239 239
@@ -243,13 +243,7 @@ static LIST_HEAD(task_groups);
243 243
244/* task group related information */ 244/* task group related information */
245struct task_group { 245struct task_group {
246#ifdef CONFIG_CGROUP_SCHED
247 struct cgroup_subsys_state css; 246 struct cgroup_subsys_state css;
248#endif
249
250#ifdef CONFIG_USER_SCHED
251 uid_t uid;
252#endif
253 247
254#ifdef CONFIG_FAIR_GROUP_SCHED 248#ifdef CONFIG_FAIR_GROUP_SCHED
255 /* schedulable entities of this group on each cpu */ 249 /* schedulable entities of this group on each cpu */
@@ -274,35 +268,7 @@ struct task_group {
274 struct list_head children; 268 struct list_head children;
275}; 269};
276 270
277#ifdef CONFIG_USER_SCHED
278
279/* Helper function to pass uid information to create_sched_user() */
280void set_tg_uid(struct user_struct *user)
281{
282 user->tg->uid = user->uid;
283}
284
285/*
286 * Root task group.
287 * Every UID task group (including init_task_group aka UID-0) will
288 * be a child to this group.
289 */
290struct task_group root_task_group;
291
292#ifdef CONFIG_FAIR_GROUP_SCHED
293/* Default task group's sched entity on each cpu */
294static DEFINE_PER_CPU(struct sched_entity, init_sched_entity);
295/* Default task group's cfs_rq on each cpu */
296static DEFINE_PER_CPU_SHARED_ALIGNED(struct cfs_rq, init_tg_cfs_rq);
297#endif /* CONFIG_FAIR_GROUP_SCHED */
298
299#ifdef CONFIG_RT_GROUP_SCHED
300static DEFINE_PER_CPU(struct sched_rt_entity, init_sched_rt_entity);
301static DEFINE_PER_CPU_SHARED_ALIGNED(struct rt_rq, init_rt_rq_var);
302#endif /* CONFIG_RT_GROUP_SCHED */
303#else /* !CONFIG_USER_SCHED */
304#define root_task_group init_task_group 271#define root_task_group init_task_group
305#endif /* CONFIG_USER_SCHED */
306 272
307/* task_group_lock serializes add/remove of task groups and also changes to 273/* task_group_lock serializes add/remove of task groups and also changes to
308 * a task group's cpu shares. 274 * a task group's cpu shares.
@@ -318,11 +284,7 @@ static int root_task_group_empty(void)
318} 284}
319#endif 285#endif
320 286
321#ifdef CONFIG_USER_SCHED
322# define INIT_TASK_GROUP_LOAD (2*NICE_0_LOAD)
323#else /* !CONFIG_USER_SCHED */
324# define INIT_TASK_GROUP_LOAD NICE_0_LOAD 287# define INIT_TASK_GROUP_LOAD NICE_0_LOAD
325#endif /* CONFIG_USER_SCHED */
326 288
327/* 289/*
328 * A weight of 0 or 1 can cause arithmetics problems. 290 * A weight of 0 or 1 can cause arithmetics problems.
@@ -348,11 +310,7 @@ static inline struct task_group *task_group(struct task_struct *p)
348{ 310{
349 struct task_group *tg; 311 struct task_group *tg;
350 312
351#ifdef CONFIG_USER_SCHED 313#ifdef CONFIG_CGROUP_SCHED
352 rcu_read_lock();
353 tg = __task_cred(p)->user->tg;
354 rcu_read_unlock();
355#elif defined(CONFIG_CGROUP_SCHED)
356 tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id), 314 tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id),
357 struct task_group, css); 315 struct task_group, css);
358#else 316#else
@@ -383,7 +341,7 @@ static inline struct task_group *task_group(struct task_struct *p)
383 return NULL; 341 return NULL;
384} 342}
385 343
386#endif /* CONFIG_GROUP_SCHED */ 344#endif /* CONFIG_CGROUP_SCHED */
387 345
388/* CFS-related fields in a runqueue */ 346/* CFS-related fields in a runqueue */
389struct cfs_rq { 347struct cfs_rq {
@@ -7678,9 +7636,6 @@ void __init sched_init(void)
7678#ifdef CONFIG_RT_GROUP_SCHED 7636#ifdef CONFIG_RT_GROUP_SCHED
7679 alloc_size += 2 * nr_cpu_ids * sizeof(void **); 7637 alloc_size += 2 * nr_cpu_ids * sizeof(void **);
7680#endif 7638#endif
7681#ifdef CONFIG_USER_SCHED
7682 alloc_size *= 2;
7683#endif
7684#ifdef CONFIG_CPUMASK_OFFSTACK 7639#ifdef CONFIG_CPUMASK_OFFSTACK
7685 alloc_size += num_possible_cpus() * cpumask_size(); 7640 alloc_size += num_possible_cpus() * cpumask_size();
7686#endif 7641#endif
@@ -7694,13 +7649,6 @@ void __init sched_init(void)
7694 init_task_group.cfs_rq = (struct cfs_rq **)ptr; 7649 init_task_group.cfs_rq = (struct cfs_rq **)ptr;
7695 ptr += nr_cpu_ids * sizeof(void **); 7650 ptr += nr_cpu_ids * sizeof(void **);
7696 7651
7697#ifdef CONFIG_USER_SCHED
7698 root_task_group.se = (struct sched_entity **)ptr;
7699 ptr += nr_cpu_ids * sizeof(void **);
7700
7701 root_task_group.cfs_rq = (struct cfs_rq **)ptr;
7702 ptr += nr_cpu_ids * sizeof(void **);
7703#endif /* CONFIG_USER_SCHED */
7704#endif /* CONFIG_FAIR_GROUP_SCHED */ 7652#endif /* CONFIG_FAIR_GROUP_SCHED */
7705#ifdef CONFIG_RT_GROUP_SCHED 7653#ifdef CONFIG_RT_GROUP_SCHED
7706 init_task_group.rt_se = (struct sched_rt_entity **)ptr; 7654 init_task_group.rt_se = (struct sched_rt_entity **)ptr;
@@ -7709,13 +7657,6 @@ void __init sched_init(void)
7709 init_task_group.rt_rq = (struct rt_rq **)ptr; 7657 init_task_group.rt_rq = (struct rt_rq **)ptr;
7710 ptr += nr_cpu_ids * sizeof(void **); 7658 ptr += nr_cpu_ids * sizeof(void **);
7711 7659
7712#ifdef CONFIG_USER_SCHED
7713 root_task_group.rt_se = (struct sched_rt_entity **)ptr;
7714 ptr += nr_cpu_ids * sizeof(void **);
7715
7716 root_task_group.rt_rq = (struct rt_rq **)ptr;
7717 ptr += nr_cpu_ids * sizeof(void **);
7718#endif /* CONFIG_USER_SCHED */
7719#endif /* CONFIG_RT_GROUP_SCHED */ 7660#endif /* CONFIG_RT_GROUP_SCHED */
7720#ifdef CONFIG_CPUMASK_OFFSTACK 7661#ifdef CONFIG_CPUMASK_OFFSTACK
7721 for_each_possible_cpu(i) { 7662 for_each_possible_cpu(i) {
@@ -7735,22 +7676,13 @@ void __init sched_init(void)
7735#ifdef CONFIG_RT_GROUP_SCHED 7676#ifdef CONFIG_RT_GROUP_SCHED
7736 init_rt_bandwidth(&init_task_group.rt_bandwidth, 7677 init_rt_bandwidth(&init_task_group.rt_bandwidth,
7737 global_rt_period(), global_rt_runtime()); 7678 global_rt_period(), global_rt_runtime());
7738#ifdef CONFIG_USER_SCHED
7739 init_rt_bandwidth(&root_task_group.rt_bandwidth,
7740 global_rt_period(), RUNTIME_INF);
7741#endif /* CONFIG_USER_SCHED */
7742#endif /* CONFIG_RT_GROUP_SCHED */ 7679#endif /* CONFIG_RT_GROUP_SCHED */
7743 7680
7744#ifdef CONFIG_GROUP_SCHED 7681#ifdef CONFIG_CGROUP_SCHED
7745 list_add(&init_task_group.list, &task_groups); 7682 list_add(&init_task_group.list, &task_groups);
7746 INIT_LIST_HEAD(&init_task_group.children); 7683 INIT_LIST_HEAD(&init_task_group.children);
7747 7684
7748#ifdef CONFIG_USER_SCHED 7685#endif /* CONFIG_CGROUP_SCHED */
7749 INIT_LIST_HEAD(&root_task_group.children);
7750 init_task_group.parent = &root_task_group;
7751 list_add(&init_task_group.siblings, &root_task_group.children);
7752#endif /* CONFIG_USER_SCHED */
7753#endif /* CONFIG_GROUP_SCHED */
7754 7686
7755#if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP 7687#if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP
7756 update_shares_data = __alloc_percpu(nr_cpu_ids * sizeof(unsigned long), 7688 update_shares_data = __alloc_percpu(nr_cpu_ids * sizeof(unsigned long),
@@ -7790,25 +7722,6 @@ void __init sched_init(void)
7790 * directly in rq->cfs (i.e init_task_group->se[] = NULL). 7722 * directly in rq->cfs (i.e init_task_group->se[] = NULL).
7791 */ 7723 */
7792 init_tg_cfs_entry(&init_task_group, &rq->cfs, NULL, i, 1, NULL); 7724 init_tg_cfs_entry(&init_task_group, &rq->cfs, NULL, i, 1, NULL);
7793#elif defined CONFIG_USER_SCHED
7794 root_task_group.shares = NICE_0_LOAD;
7795 init_tg_cfs_entry(&root_task_group, &rq->cfs, NULL, i, 0, NULL);
7796 /*
7797 * In case of task-groups formed thr' the user id of tasks,
7798 * init_task_group represents tasks belonging to root user.
7799 * Hence it forms a sibling of all subsequent groups formed.
7800 * In this case, init_task_group gets only a fraction of overall
7801 * system cpu resource, based on the weight assigned to root
7802 * user's cpu share (INIT_TASK_GROUP_LOAD). This is accomplished
7803 * by letting tasks of init_task_group sit in a separate cfs_rq
7804 * (init_tg_cfs_rq) and having one entity represent this group of
7805 * tasks in rq->cfs (i.e init_task_group->se[] != NULL).
7806 */
7807 init_tg_cfs_entry(&init_task_group,
7808 &per_cpu(init_tg_cfs_rq, i),
7809 &per_cpu(init_sched_entity, i), i, 1,
7810 root_task_group.se[i]);
7811
7812#endif 7725#endif
7813#endif /* CONFIG_FAIR_GROUP_SCHED */ 7726#endif /* CONFIG_FAIR_GROUP_SCHED */
7814 7727
@@ -7817,12 +7730,6 @@ void __init sched_init(void)
7817 INIT_LIST_HEAD(&rq->leaf_rt_rq_list); 7730 INIT_LIST_HEAD(&rq->leaf_rt_rq_list);
7818#ifdef CONFIG_CGROUP_SCHED 7731#ifdef CONFIG_CGROUP_SCHED
7819 init_tg_rt_entry(&init_task_group, &rq->rt, NULL, i, 1, NULL); 7732 init_tg_rt_entry(&init_task_group, &rq->rt, NULL, i, 1, NULL);
7820#elif defined CONFIG_USER_SCHED
7821 init_tg_rt_entry(&root_task_group, &rq->rt, NULL, i, 0, NULL);
7822 init_tg_rt_entry(&init_task_group,
7823 &per_cpu(init_rt_rq_var, i),
7824 &per_cpu(init_sched_rt_entity, i), i, 1,
7825 root_task_group.rt_se[i]);
7826#endif 7733#endif
7827#endif 7734#endif
7828 7735
@@ -8218,7 +8125,7 @@ static inline void unregister_rt_sched_group(struct task_group *tg, int cpu)
8218} 8125}
8219#endif /* CONFIG_RT_GROUP_SCHED */ 8126#endif /* CONFIG_RT_GROUP_SCHED */
8220 8127
8221#ifdef CONFIG_GROUP_SCHED 8128#ifdef CONFIG_CGROUP_SCHED
8222static void free_sched_group(struct task_group *tg) 8129static void free_sched_group(struct task_group *tg)
8223{ 8130{
8224 free_fair_sched_group(tg); 8131 free_fair_sched_group(tg);
@@ -8327,7 +8234,7 @@ void sched_move_task(struct task_struct *tsk)
8327 8234
8328 task_rq_unlock(rq, &flags); 8235 task_rq_unlock(rq, &flags);
8329} 8236}
8330#endif /* CONFIG_GROUP_SCHED */ 8237#endif /* CONFIG_CGROUP_SCHED */
8331 8238
8332#ifdef CONFIG_FAIR_GROUP_SCHED 8239#ifdef CONFIG_FAIR_GROUP_SCHED
8333static void __set_se_shares(struct sched_entity *se, unsigned long shares) 8240static void __set_se_shares(struct sched_entity *se, unsigned long shares)
@@ -8469,13 +8376,6 @@ static int tg_schedulable(struct task_group *tg, void *data)
8469 runtime = d->rt_runtime; 8376 runtime = d->rt_runtime;
8470 } 8377 }
8471 8378
8472#ifdef CONFIG_USER_SCHED
8473 if (tg == &root_task_group) {
8474 period = global_rt_period();
8475 runtime = global_rt_runtime();
8476 }
8477#endif
8478
8479 /* 8379 /*
8480 * Cannot have more runtime than the period. 8380 * Cannot have more runtime than the period.
8481 */ 8381 */
diff --git a/kernel/sys.c b/kernel/sys.c
index 26a6b73a6b85..f75bf0936f47 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -569,11 +569,6 @@ static int set_user(struct cred *new)
569 if (!new_user) 569 if (!new_user)
570 return -EAGAIN; 570 return -EAGAIN;
571 571
572 if (!task_can_switch_user(new_user, current)) {
573 free_uid(new_user);
574 return -EINVAL;
575 }
576
577 if (atomic_read(&new_user->processes) >= 572 if (atomic_read(&new_user->processes) >=
578 current->signal->rlim[RLIMIT_NPROC].rlim_cur && 573 current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
579 new_user != INIT_USER) { 574 new_user != INIT_USER) {
diff --git a/kernel/user.c b/kernel/user.c
index 46d0165ca70c..766467b3bcb7 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -56,9 +56,6 @@ struct user_struct root_user = {
56 .sigpending = ATOMIC_INIT(0), 56 .sigpending = ATOMIC_INIT(0),
57 .locked_shm = 0, 57 .locked_shm = 0,
58 .user_ns = &init_user_ns, 58 .user_ns = &init_user_ns,
59#ifdef CONFIG_USER_SCHED
60 .tg = &init_task_group,
61#endif
62}; 59};
63 60
64/* 61/*
@@ -75,268 +72,6 @@ static void uid_hash_remove(struct user_struct *up)
75 put_user_ns(up->user_ns); 72 put_user_ns(up->user_ns);
76} 73}
77 74
78#ifdef CONFIG_USER_SCHED
79
80static void sched_destroy_user(struct user_struct *up)
81{
82 sched_destroy_group(up->tg);
83}
84
85static int sched_create_user(struct user_struct *up)
86{
87 int rc = 0;
88
89 up->tg = sched_create_group(&root_task_group);
90 if (IS_ERR(up->tg))
91 rc = -ENOMEM;
92
93 set_tg_uid(up);
94
95 return rc;
96}
97
98#else /* CONFIG_USER_SCHED */
99
100static void sched_destroy_user(struct user_struct *up) { }
101static int sched_create_user(struct user_struct *up) { return 0; }
102
103#endif /* CONFIG_USER_SCHED */
104
105#if defined(CONFIG_USER_SCHED) && defined(CONFIG_SYSFS)
106
107static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent)
108{
109 struct user_struct *user;
110 struct hlist_node *h;
111
112 hlist_for_each_entry(user, h, hashent, uidhash_node) {
113 if (user->uid == uid) {
114 /* possibly resurrect an "almost deleted" object */
115 if (atomic_inc_return(&user->__count) == 1)
116 cancel_delayed_work(&user->work);
117 return user;
118 }
119 }
120
121 return NULL;
122}
123
124static struct kset *uids_kset; /* represents the /sys/kernel/uids/ directory */
125static DEFINE_MUTEX(uids_mutex);
126
127static inline void uids_mutex_lock(void)
128{
129 mutex_lock(&uids_mutex);
130}
131
132static inline void uids_mutex_unlock(void)
133{
134 mutex_unlock(&uids_mutex);
135}
136
137/* uid directory attributes */
138#ifdef CONFIG_FAIR_GROUP_SCHED
139static ssize_t cpu_shares_show(struct kobject *kobj,
140 struct kobj_attribute *attr,
141 char *buf)
142{
143 struct user_struct *up = container_of(kobj, struct user_struct, kobj);
144
145 return sprintf(buf, "%lu\n", sched_group_shares(up->tg));
146}
147
148static ssize_t cpu_shares_store(struct kobject *kobj,
149 struct kobj_attribute *attr,
150 const char *buf, size_t size)
151{
152 struct user_struct *up = container_of(kobj, struct user_struct, kobj);
153 unsigned long shares;
154 int rc;
155
156 sscanf(buf, "%lu", &shares);
157
158 rc = sched_group_set_shares(up->tg, shares);
159
160 return (rc ? rc : size);
161}
162
163static struct kobj_attribute cpu_share_attr =
164 __ATTR(cpu_share, 0644, cpu_shares_show, cpu_shares_store);
165#endif
166
167#ifdef CONFIG_RT_GROUP_SCHED
168static ssize_t cpu_rt_runtime_show(struct kobject *kobj,
169 struct kobj_attribute *attr,
170 char *buf)
171{
172 struct user_struct *up = container_of(kobj, struct user_struct, kobj);
173
174 return sprintf(buf, "%ld\n", sched_group_rt_runtime(up->tg));
175}
176
177static ssize_t cpu_rt_runtime_store(struct kobject *kobj,
178 struct kobj_attribute *attr,
179 const char *buf, size_t size)
180{
181 struct user_struct *up = container_of(kobj, struct user_struct, kobj);
182 unsigned long rt_runtime;
183 int rc;
184
185 sscanf(buf, "%ld", &rt_runtime);
186
187 rc = sched_group_set_rt_runtime(up->tg, rt_runtime);
188
189 return (rc ? rc : size);
190}
191
192static struct kobj_attribute cpu_rt_runtime_attr =
193 __ATTR(cpu_rt_runtime, 0644, cpu_rt_runtime_show, cpu_rt_runtime_store);
194
195static ssize_t cpu_rt_period_show(struct kobject *kobj,
196 struct kobj_attribute *attr,
197 char *buf)
198{
199 struct user_struct *up = container_of(kobj, struct user_struct, kobj);
200
201 return sprintf(buf, "%lu\n", sched_group_rt_period(up->tg));
202}
203
204static ssize_t cpu_rt_period_store(struct kobject *kobj,
205 struct kobj_attribute *attr,
206 const char *buf, size_t size)
207{
208 struct user_struct *up = container_of(kobj, struct user_struct, kobj);
209 unsigned long rt_period;
210 int rc;
211
212 sscanf(buf, "%lu", &rt_period);
213
214 rc = sched_group_set_rt_period(up->tg, rt_period);
215
216 return (rc ? rc : size);
217}
218
219static struct kobj_attribute cpu_rt_period_attr =
220 __ATTR(cpu_rt_period, 0644, cpu_rt_period_show, cpu_rt_period_store);
221#endif
222
223/* default attributes per uid directory */
224static struct attribute *uids_attributes[] = {
225#ifdef CONFIG_FAIR_GROUP_SCHED
226 &cpu_share_attr.attr,
227#endif
228#ifdef CONFIG_RT_GROUP_SCHED
229 &cpu_rt_runtime_attr.attr,
230 &cpu_rt_period_attr.attr,
231#endif
232 NULL
233};
234
235/* the lifetime of user_struct is not managed by the core (now) */
236static void uids_release(struct kobject *kobj)
237{
238 return;
239}
240
241static struct kobj_type uids_ktype = {
242 .sysfs_ops = &kobj_sysfs_ops,
243 .default_attrs = uids_attributes,
244 .release = uids_release,
245};
246
247/*
248 * Create /sys/kernel/uids/<uid>/cpu_share file for this user
249 * We do not create this file for users in a user namespace (until
250 * sysfs tagging is implemented).
251 *
252 * See Documentation/scheduler/sched-design-CFS.txt for ramifications.
253 */
254static int uids_user_create(struct user_struct *up)
255{
256 struct kobject *kobj = &up->kobj;
257 int error;
258
259 memset(kobj, 0, sizeof(struct kobject));
260 if (up->user_ns != &init_user_ns)
261 return 0;
262 kobj->kset = uids_kset;
263 error = kobject_init_and_add(kobj, &uids_ktype, NULL, "%d", up->uid);
264 if (error) {
265 kobject_put(kobj);
266 goto done;
267 }
268
269 kobject_uevent(kobj, KOBJ_ADD);
270done:
271 return error;
272}
273
274/* create these entries in sysfs:
275 * "/sys/kernel/uids" directory
276 * "/sys/kernel/uids/0" directory (for root user)
277 * "/sys/kernel/uids/0/cpu_share" file (for root user)
278 */
279int __init uids_sysfs_init(void)
280{
281 uids_kset = kset_create_and_add("uids", NULL, kernel_kobj);
282 if (!uids_kset)
283 return -ENOMEM;
284
285 return uids_user_create(&root_user);
286}
287
288/* delayed work function to remove sysfs directory for a user and free up
289 * corresponding structures.
290 */
291static void cleanup_user_struct(struct work_struct *w)
292{
293 struct user_struct *up = container_of(w, struct user_struct, work.work);
294 unsigned long flags;
295 int remove_user = 0;
296
297 /* Make uid_hash_remove() + sysfs_remove_file() + kobject_del()
298 * atomic.
299 */
300 uids_mutex_lock();
301
302 spin_lock_irqsave(&uidhash_lock, flags);
303 if (atomic_read(&up->__count) == 0) {
304 uid_hash_remove(up);
305 remove_user = 1;
306 }
307 spin_unlock_irqrestore(&uidhash_lock, flags);
308
309 if (!remove_user)
310 goto done;
311
312 if (up->user_ns == &init_user_ns) {
313 kobject_uevent(&up->kobj, KOBJ_REMOVE);
314 kobject_del(&up->kobj);
315 kobject_put(&up->kobj);
316 }
317
318 sched_destroy_user(up);
319 key_put(up->uid_keyring);
320 key_put(up->session_keyring);
321 kmem_cache_free(uid_cachep, up);
322
323done:
324 uids_mutex_unlock();
325}
326
327/* IRQs are disabled and uidhash_lock is held upon function entry.
328 * IRQ state (as stored in flags) is restored and uidhash_lock released
329 * upon function exit.
330 */
331static void free_user(struct user_struct *up, unsigned long flags)
332{
333 INIT_DELAYED_WORK(&up->work, cleanup_user_struct);
334 schedule_delayed_work(&up->work, msecs_to_jiffies(1000));
335 spin_unlock_irqrestore(&uidhash_lock, flags);
336}
337
338#else /* CONFIG_USER_SCHED && CONFIG_SYSFS */
339
340static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) 75static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent)
341{ 76{
342 struct user_struct *user; 77 struct user_struct *user;
@@ -352,11 +87,6 @@ static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent)
352 return NULL; 87 return NULL;
353} 88}
354 89
355int uids_sysfs_init(void) { return 0; }
356static inline int uids_user_create(struct user_struct *up) { return 0; }
357static inline void uids_mutex_lock(void) { }
358static inline void uids_mutex_unlock(void) { }
359
360/* IRQs are disabled and uidhash_lock is held upon function entry. 90/* IRQs are disabled and uidhash_lock is held upon function entry.
361 * IRQ state (as stored in flags) is restored and uidhash_lock released 91 * IRQ state (as stored in flags) is restored and uidhash_lock released
362 * upon function exit. 92 * upon function exit.
@@ -365,32 +95,11 @@ static void free_user(struct user_struct *up, unsigned long flags)
365{ 95{
366 uid_hash_remove(up); 96 uid_hash_remove(up);
367 spin_unlock_irqrestore(&uidhash_lock, flags); 97 spin_unlock_irqrestore(&uidhash_lock, flags);
368 sched_destroy_user(up);
369 key_put(up->uid_keyring); 98 key_put(up->uid_keyring);
370 key_put(up->session_keyring); 99 key_put(up->session_keyring);
371 kmem_cache_free(uid_cachep, up); 100 kmem_cache_free(uid_cachep, up);
372} 101}
373 102
374#endif
375
376#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED)
377/*
378 * We need to check if a setuid can take place. This function should be called
379 * before successfully completing the setuid.
380 */
381int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
382{
383
384 return sched_rt_can_attach(up->tg, tsk);
385
386}
387#else
388int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
389{
390 return 1;
391}
392#endif
393
394/* 103/*
395 * Locate the user_struct for the passed UID. If found, take a ref on it. The 104 * Locate the user_struct for the passed UID. If found, take a ref on it. The
396 * caller must undo that ref with free_uid(). 105 * caller must undo that ref with free_uid().
@@ -431,8 +140,6 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)
431 /* Make uid_hash_find() + uids_user_create() + uid_hash_insert() 140 /* Make uid_hash_find() + uids_user_create() + uid_hash_insert()
432 * atomic. 141 * atomic.
433 */ 142 */
434 uids_mutex_lock();
435
436 spin_lock_irq(&uidhash_lock); 143 spin_lock_irq(&uidhash_lock);
437 up = uid_hash_find(uid, hashent); 144 up = uid_hash_find(uid, hashent);
438 spin_unlock_irq(&uidhash_lock); 145 spin_unlock_irq(&uidhash_lock);
@@ -445,14 +152,8 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)
445 new->uid = uid; 152 new->uid = uid;
446 atomic_set(&new->__count, 1); 153 atomic_set(&new->__count, 1);
447 154
448 if (sched_create_user(new) < 0)
449 goto out_free_user;
450
451 new->user_ns = get_user_ns(ns); 155 new->user_ns = get_user_ns(ns);
452 156
453 if (uids_user_create(new))
454 goto out_destoy_sched;
455
456 /* 157 /*
457 * Before adding this, check whether we raced 158 * Before adding this, check whether we raced
458 * on adding the same user already.. 159 * on adding the same user already..
@@ -475,17 +176,11 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)
475 spin_unlock_irq(&uidhash_lock); 176 spin_unlock_irq(&uidhash_lock);
476 } 177 }
477 178
478 uids_mutex_unlock();
479
480 return up; 179 return up;
481 180
482out_destoy_sched:
483 sched_destroy_user(new);
484 put_user_ns(new->user_ns); 181 put_user_ns(new->user_ns);
485out_free_user:
486 kmem_cache_free(uid_cachep, new); 182 kmem_cache_free(uid_cachep, new);
487out_unlock: 183out_unlock:
488 uids_mutex_unlock();
489 return NULL; 184 return NULL;
490} 185}
491 186