diff options
-rw-r--r-- | Documentation/feature-removal-schedule.txt | 15 | ||||
-rw-r--r-- | include/linux/sched.h | 14 | ||||
-rw-r--r-- | init/Kconfig | 81 | ||||
-rw-r--r-- | kernel/ksysfs.c | 8 | ||||
-rw-r--r-- | kernel/sched.c | 114 | ||||
-rw-r--r-- | kernel/sys.c | 5 | ||||
-rw-r--r-- | kernel/user.c | 305 |
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 | ||
9 | What: USER_SCHED | ||
10 | When: 2.6.34 | ||
11 | |||
12 | Why: 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 | |||
20 | Who: Dhaval Giani <dhaval@linux.vnet.ibm.com> | ||
21 | |||
22 | --------------------------- | ||
23 | |||
24 | What: PRISM54 | 9 | What: PRISM54 |
25 | When: 2.6.34 | 10 | When: 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 | ||
2503 | extern void normalize_rt_tasks(void); | 2495 | extern void normalize_rt_tasks(void); |
2504 | 2496 | ||
2505 | #ifdef CONFIG_GROUP_SCHED | 2497 | #ifdef CONFIG_CGROUP_SCHED |
2506 | 2498 | ||
2507 | extern struct task_group init_task_group; | 2499 | extern struct task_group init_task_group; |
2508 | #ifdef CONFIG_USER_SCHED | ||
2509 | extern struct task_group root_task_group; | ||
2510 | extern void set_tg_uid(struct user_struct *user); | ||
2511 | #endif | ||
2512 | 2500 | ||
2513 | extern struct task_group *sched_create_group(struct task_group *parent); | 2501 | extern struct task_group *sched_create_group(struct task_group *parent); |
2514 | extern void sched_destroy_group(struct task_group *tg); | 2502 | extern 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 | |||
435 | config HAVE_UNSTABLE_SCHED_CLOCK | 435 | config HAVE_UNSTABLE_SCHED_CLOCK |
436 | bool | 436 | bool |
437 | 437 | ||
438 | config 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 | |||
448 | config FAIR_GROUP_SCHED | ||
449 | bool "Group scheduling for SCHED_OTHER" | ||
450 | depends on GROUP_SCHED | ||
451 | default GROUP_SCHED | ||
452 | |||
453 | config 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 | |||
466 | choice | ||
467 | depends on GROUP_SCHED | ||
468 | prompt "Basis for grouping tasks" | ||
469 | default USER_SCHED | ||
470 | |||
471 | config 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 | |||
477 | config 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 | |||
487 | endchoice | ||
488 | |||
489 | menuconfig CGROUPS | 438 | menuconfig 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 | ||
558 | menuconfig 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 | |||
567 | if CGROUP_SCHED | ||
568 | config FAIR_GROUP_SCHED | ||
569 | bool "Group scheduling for SCHED_OTHER" | ||
570 | depends on CGROUP_SCHED | ||
571 | default CGROUP_SCHED | ||
572 | |||
573 | config 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 | |||
586 | endif #CGROUP_SCHED | ||
587 | |||
609 | endif # CGROUPS | 588 | endif # CGROUPS |
610 | 589 | ||
611 | config MM_OWNER | 590 | config 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 | ||
207 | notes_exit: | ||
208 | if (notes_size > 0) | ||
209 | sysfs_remove_bin_file(kernel_kobj, ¬es_attr); | ||
210 | group_exit: | 202 | group_exit: |
211 | sysfs_remove_group(kernel_kobj, &kernel_attr_group); | 203 | sysfs_remove_group(kernel_kobj, &kernel_attr_group); |
212 | kset_exit: | 204 | kset_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 | */ |
234 | static DEFINE_MUTEX(sched_domains_mutex); | 234 | static 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 */ |
245 | struct task_group { | 245 | struct 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() */ | ||
280 | void 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 | */ | ||
290 | struct task_group root_task_group; | ||
291 | |||
292 | #ifdef CONFIG_FAIR_GROUP_SCHED | ||
293 | /* Default task group's sched entity on each cpu */ | ||
294 | static DEFINE_PER_CPU(struct sched_entity, init_sched_entity); | ||
295 | /* Default task group's cfs_rq on each cpu */ | ||
296 | static 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 | ||
300 | static DEFINE_PER_CPU(struct sched_rt_entity, init_sched_rt_entity); | ||
301 | static 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 */ |
389 | struct cfs_rq { | 347 | struct 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 |
8222 | static void free_sched_group(struct task_group *tg) | 8129 | static 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 |
8333 | static void __set_se_shares(struct sched_entity *se, unsigned long shares) | 8240 | static 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 | |||
80 | static void sched_destroy_user(struct user_struct *up) | ||
81 | { | ||
82 | sched_destroy_group(up->tg); | ||
83 | } | ||
84 | |||
85 | static 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 | |||
100 | static void sched_destroy_user(struct user_struct *up) { } | ||
101 | static 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 | |||
107 | static 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 | |||
124 | static struct kset *uids_kset; /* represents the /sys/kernel/uids/ directory */ | ||
125 | static DEFINE_MUTEX(uids_mutex); | ||
126 | |||
127 | static inline void uids_mutex_lock(void) | ||
128 | { | ||
129 | mutex_lock(&uids_mutex); | ||
130 | } | ||
131 | |||
132 | static inline void uids_mutex_unlock(void) | ||
133 | { | ||
134 | mutex_unlock(&uids_mutex); | ||
135 | } | ||
136 | |||
137 | /* uid directory attributes */ | ||
138 | #ifdef CONFIG_FAIR_GROUP_SCHED | ||
139 | static 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 | |||
148 | static 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 | |||
163 | static 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 | ||
168 | static 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 | |||
177 | static 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 | |||
192 | static struct kobj_attribute cpu_rt_runtime_attr = | ||
193 | __ATTR(cpu_rt_runtime, 0644, cpu_rt_runtime_show, cpu_rt_runtime_store); | ||
194 | |||
195 | static 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 | |||
204 | static 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 | |||
219 | static 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 */ | ||
224 | static 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) */ | ||
236 | static void uids_release(struct kobject *kobj) | ||
237 | { | ||
238 | return; | ||
239 | } | ||
240 | |||
241 | static 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 | */ | ||
254 | static 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); | ||
270 | done: | ||
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 | */ | ||
279 | int __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 | */ | ||
291 | static 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 | |||
323 | done: | ||
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 | */ | ||
331 | static 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 | |||
340 | static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) | 75 | static 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 | ||
355 | int uids_sysfs_init(void) { return 0; } | ||
356 | static inline int uids_user_create(struct user_struct *up) { return 0; } | ||
357 | static inline void uids_mutex_lock(void) { } | ||
358 | static 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 | */ | ||
381 | int 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 | ||
388 | int 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 | ||
482 | out_destoy_sched: | ||
483 | sched_destroy_user(new); | ||
484 | put_user_ns(new->user_ns); | 181 | put_user_ns(new->user_ns); |
485 | out_free_user: | ||
486 | kmem_cache_free(uid_cachep, new); | 182 | kmem_cache_free(uid_cachep, new); |
487 | out_unlock: | 183 | out_unlock: |
488 | uids_mutex_unlock(); | ||
489 | return NULL; | 184 | return NULL; |
490 | } | 185 | } |
491 | 186 | ||