diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 15:59:24 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 15:59:24 -0500 |
| commit | db0c2bf69aa095d4a6de7b1145f29fe9a7c0f6a3 (patch) | |
| tree | 8f38957c01b18edddd44d49ecc3beeac08a20b4e /include | |
| parent | ac69e0928054ff29a5049902fb477f9c7605c773 (diff) | |
| parent | 0d19ea866562e46989412a0676412fa0983c9ce7 (diff) | |
Merge branch 'for-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
* 'for-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: (21 commits)
cgroup: fix to allow mounting a hierarchy by name
cgroup: move assignement out of condition in cgroup_attach_proc()
cgroup: Remove task_lock() from cgroup_post_fork()
cgroup: add sparse annotation to cgroup_iter_start() and cgroup_iter_end()
cgroup: mark cgroup_rmdir_waitq and cgroup_attach_proc() as static
cgroup: only need to check oldcgrp==newgrp once
cgroup: remove redundant get/put of task struct
cgroup: remove redundant get/put of old css_set from migrate
cgroup: Remove unnecessary task_lock before fetching css_set on migration
cgroup: Drop task_lock(parent) on cgroup_fork()
cgroups: remove redundant get/put of css_set from css_set_check_fetched()
resource cgroups: remove bogus cast
cgroup: kill subsys->can_attach_task(), pre_attach() and attach_task()
cgroup, cpuset: don't use ss->pre_attach()
cgroup: don't use subsys->can_attach_task() or ->attach_task()
cgroup: introduce cgroup_taskset and use it in subsys->can_attach(), cancel_attach() and attach()
cgroup: improve old cgroup handling in cgroup_attach_proc()
cgroup: always lock threadgroup during migration
threadgroup: extend threadgroup_lock() to cover exit and exec
threadgroup: rename signal->threadgroup_fork_lock to ->group_rwsem
...
Fix up conflict in kernel/cgroup.c due to commit e0197aae59e5: "cgroups:
fix a css_set not found bug in cgroup_attach_proc" that already
mentioned that the bug is fixed (differently) in Tejun's cgroup
patchset. This one, in other words.
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/cgroup.h | 31 | ||||
| -rw-r--r-- | include/linux/init_task.h | 9 | ||||
| -rw-r--r-- | include/linux/sched.h | 73 |
3 files changed, 83 insertions, 30 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index a17becc36ca1..e9b602151caf 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
| @@ -457,6 +457,28 @@ void cgroup_exclude_rmdir(struct cgroup_subsys_state *css); | |||
| 457 | void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css); | 457 | void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css); |
| 458 | 458 | ||
| 459 | /* | 459 | /* |
| 460 | * Control Group taskset, used to pass around set of tasks to cgroup_subsys | ||
| 461 | * methods. | ||
| 462 | */ | ||
| 463 | struct cgroup_taskset; | ||
| 464 | struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset); | ||
| 465 | struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset); | ||
| 466 | struct cgroup *cgroup_taskset_cur_cgroup(struct cgroup_taskset *tset); | ||
| 467 | int cgroup_taskset_size(struct cgroup_taskset *tset); | ||
| 468 | |||
| 469 | /** | ||
| 470 | * cgroup_taskset_for_each - iterate cgroup_taskset | ||
| 471 | * @task: the loop cursor | ||
| 472 | * @skip_cgrp: skip if task's cgroup matches this, %NULL to iterate through all | ||
| 473 | * @tset: taskset to iterate | ||
| 474 | */ | ||
| 475 | #define cgroup_taskset_for_each(task, skip_cgrp, tset) \ | ||
| 476 | for ((task) = cgroup_taskset_first((tset)); (task); \ | ||
| 477 | (task) = cgroup_taskset_next((tset))) \ | ||
| 478 | if (!(skip_cgrp) || \ | ||
| 479 | cgroup_taskset_cur_cgroup((tset)) != (skip_cgrp)) | ||
| 480 | |||
| 481 | /* | ||
| 460 | * Control Group subsystem type. | 482 | * Control Group subsystem type. |
| 461 | * See Documentation/cgroups/cgroups.txt for details | 483 | * See Documentation/cgroups/cgroups.txt for details |
| 462 | */ | 484 | */ |
| @@ -467,14 +489,11 @@ struct cgroup_subsys { | |||
| 467 | int (*pre_destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); | 489 | int (*pre_destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); |
| 468 | void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); | 490 | void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); |
| 469 | int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, | 491 | int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, |
| 470 | struct task_struct *tsk); | 492 | struct cgroup_taskset *tset); |
| 471 | int (*can_attach_task)(struct cgroup *cgrp, struct task_struct *tsk); | ||
| 472 | void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, | 493 | void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, |
| 473 | struct task_struct *tsk); | 494 | struct cgroup_taskset *tset); |
| 474 | void (*pre_attach)(struct cgroup *cgrp); | ||
| 475 | void (*attach_task)(struct cgroup *cgrp, struct task_struct *tsk); | ||
| 476 | void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, | 495 | void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, |
| 477 | struct cgroup *old_cgrp, struct task_struct *tsk); | 496 | struct cgroup_taskset *tset); |
| 478 | void (*fork)(struct cgroup_subsys *ss, struct task_struct *task); | 497 | void (*fork)(struct cgroup_subsys *ss, struct task_struct *task); |
| 479 | void (*exit)(struct cgroup_subsys *ss, struct cgroup *cgrp, | 498 | void (*exit)(struct cgroup_subsys *ss, struct cgroup *cgrp, |
| 480 | struct cgroup *old_cgrp, struct task_struct *task); | 499 | struct cgroup *old_cgrp, struct task_struct *task); |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 32574eef9394..9c66b1ada9d7 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
| @@ -23,11 +23,10 @@ extern struct files_struct init_files; | |||
| 23 | extern struct fs_struct init_fs; | 23 | extern struct fs_struct init_fs; |
| 24 | 24 | ||
| 25 | #ifdef CONFIG_CGROUPS | 25 | #ifdef CONFIG_CGROUPS |
| 26 | #define INIT_THREADGROUP_FORK_LOCK(sig) \ | 26 | #define INIT_GROUP_RWSEM(sig) \ |
| 27 | .threadgroup_fork_lock = \ | 27 | .group_rwsem = __RWSEM_INITIALIZER(sig.group_rwsem), |
| 28 | __RWSEM_INITIALIZER(sig.threadgroup_fork_lock), | ||
| 29 | #else | 28 | #else |
| 30 | #define INIT_THREADGROUP_FORK_LOCK(sig) | 29 | #define INIT_GROUP_RWSEM(sig) |
| 31 | #endif | 30 | #endif |
| 32 | 31 | ||
| 33 | #define INIT_SIGNALS(sig) { \ | 32 | #define INIT_SIGNALS(sig) { \ |
| @@ -46,7 +45,7 @@ extern struct fs_struct init_fs; | |||
| 46 | }, \ | 45 | }, \ |
| 47 | .cred_guard_mutex = \ | 46 | .cred_guard_mutex = \ |
| 48 | __MUTEX_INITIALIZER(sig.cred_guard_mutex), \ | 47 | __MUTEX_INITIALIZER(sig.cred_guard_mutex), \ |
| 49 | INIT_THREADGROUP_FORK_LOCK(sig) \ | 48 | INIT_GROUP_RWSEM(sig) \ |
| 50 | } | 49 | } |
| 51 | 50 | ||
| 52 | extern struct nsproxy init_nsproxy; | 51 | extern struct nsproxy init_nsproxy; |
diff --git a/include/linux/sched.h b/include/linux/sched.h index ad93e1ec8c65..f044f66018f2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -637,13 +637,15 @@ struct signal_struct { | |||
| 637 | #endif | 637 | #endif |
| 638 | #ifdef CONFIG_CGROUPS | 638 | #ifdef CONFIG_CGROUPS |
| 639 | /* | 639 | /* |
| 640 | * The threadgroup_fork_lock prevents threads from forking with | 640 | * group_rwsem prevents new tasks from entering the threadgroup and |
| 641 | * CLONE_THREAD while held for writing. Use this for fork-sensitive | 641 | * member tasks from exiting,a more specifically, setting of |
| 642 | * threadgroup-wide operations. It's taken for reading in fork.c in | 642 | * PF_EXITING. fork and exit paths are protected with this rwsem |
| 643 | * copy_process(). | 643 | * using threadgroup_change_begin/end(). Users which require |
| 644 | * Currently only needed write-side by cgroups. | 644 | * threadgroup to remain stable should use threadgroup_[un]lock() |
| 645 | * which also takes care of exec path. Currently, cgroup is the | ||
| 646 | * only user. | ||
| 645 | */ | 647 | */ |
| 646 | struct rw_semaphore threadgroup_fork_lock; | 648 | struct rw_semaphore group_rwsem; |
| 647 | #endif | 649 | #endif |
| 648 | 650 | ||
| 649 | int oom_adj; /* OOM kill score adjustment (bit shift) */ | 651 | int oom_adj; /* OOM kill score adjustment (bit shift) */ |
| @@ -2394,29 +2396,62 @@ static inline void unlock_task_sighand(struct task_struct *tsk, | |||
| 2394 | spin_unlock_irqrestore(&tsk->sighand->siglock, *flags); | 2396 | spin_unlock_irqrestore(&tsk->sighand->siglock, *flags); |
| 2395 | } | 2397 | } |
| 2396 | 2398 | ||
| 2397 | /* See the declaration of threadgroup_fork_lock in signal_struct. */ | ||
| 2398 | #ifdef CONFIG_CGROUPS | 2399 | #ifdef CONFIG_CGROUPS |
| 2399 | static inline void threadgroup_fork_read_lock(struct task_struct *tsk) | 2400 | static inline void threadgroup_change_begin(struct task_struct *tsk) |
| 2400 | { | 2401 | { |
| 2401 | down_read(&tsk->signal->threadgroup_fork_lock); | 2402 | down_read(&tsk->signal->group_rwsem); |
| 2402 | } | 2403 | } |
| 2403 | static inline void threadgroup_fork_read_unlock(struct task_struct *tsk) | 2404 | static inline void threadgroup_change_end(struct task_struct *tsk) |
| 2404 | { | 2405 | { |
| 2405 | up_read(&tsk->signal->threadgroup_fork_lock); | 2406 | up_read(&tsk->signal->group_rwsem); |
| 2406 | } | 2407 | } |
| 2407 | static inline void threadgroup_fork_write_lock(struct task_struct *tsk) | 2408 | |
| 2409 | /** | ||
| 2410 | * threadgroup_lock - lock threadgroup | ||
| 2411 | * @tsk: member task of the threadgroup to lock | ||
| 2412 | * | ||
| 2413 | * Lock the threadgroup @tsk belongs to. No new task is allowed to enter | ||
| 2414 | * and member tasks aren't allowed to exit (as indicated by PF_EXITING) or | ||
| 2415 | * perform exec. This is useful for cases where the threadgroup needs to | ||
| 2416 | * stay stable across blockable operations. | ||
| 2417 | * | ||
| 2418 | * fork and exit paths explicitly call threadgroup_change_{begin|end}() for | ||
| 2419 | * synchronization. While held, no new task will be added to threadgroup | ||
| 2420 | * and no existing live task will have its PF_EXITING set. | ||
| 2421 | * | ||
| 2422 | * During exec, a task goes and puts its thread group through unusual | ||
| 2423 | * changes. After de-threading, exclusive access is assumed to resources | ||
| 2424 | * which are usually shared by tasks in the same group - e.g. sighand may | ||
| 2425 | * be replaced with a new one. Also, the exec'ing task takes over group | ||
| 2426 | * leader role including its pid. Exclude these changes while locked by | ||
| 2427 | * grabbing cred_guard_mutex which is used to synchronize exec path. | ||
| 2428 | */ | ||
| 2429 | static inline void threadgroup_lock(struct task_struct *tsk) | ||
| 2408 | { | 2430 | { |
| 2409 | down_write(&tsk->signal->threadgroup_fork_lock); | 2431 | /* |
| 2432 | * exec uses exit for de-threading nesting group_rwsem inside | ||
| 2433 | * cred_guard_mutex. Grab cred_guard_mutex first. | ||
| 2434 | */ | ||
| 2435 | mutex_lock(&tsk->signal->cred_guard_mutex); | ||
| 2436 | down_write(&tsk->signal->group_rwsem); | ||
| 2410 | } | 2437 | } |
| 2411 | static inline void threadgroup_fork_write_unlock(struct task_struct *tsk) | 2438 | |
| 2439 | /** | ||
| 2440 | * threadgroup_unlock - unlock threadgroup | ||
| 2441 | * @tsk: member task of the threadgroup to unlock | ||
| 2442 | * | ||
| 2443 | * Reverse threadgroup_lock(). | ||
| 2444 | */ | ||
| 2445 | static inline void threadgroup_unlock(struct task_struct *tsk) | ||
| 2412 | { | 2446 | { |
| 2413 | up_write(&tsk->signal->threadgroup_fork_lock); | 2447 | up_write(&tsk->signal->group_rwsem); |
| 2448 | mutex_unlock(&tsk->signal->cred_guard_mutex); | ||
| 2414 | } | 2449 | } |
| 2415 | #else | 2450 | #else |
| 2416 | static inline void threadgroup_fork_read_lock(struct task_struct *tsk) {} | 2451 | static inline void threadgroup_change_begin(struct task_struct *tsk) {} |
| 2417 | static inline void threadgroup_fork_read_unlock(struct task_struct *tsk) {} | 2452 | static inline void threadgroup_change_end(struct task_struct *tsk) {} |
| 2418 | static inline void threadgroup_fork_write_lock(struct task_struct *tsk) {} | 2453 | static inline void threadgroup_lock(struct task_struct *tsk) {} |
| 2419 | static inline void threadgroup_fork_write_unlock(struct task_struct *tsk) {} | 2454 | static inline void threadgroup_unlock(struct task_struct *tsk) {} |
| 2420 | #endif | 2455 | #endif |
| 2421 | 2456 | ||
| 2422 | #ifndef __HAVE_THREAD_FUNCTIONS | 2457 | #ifndef __HAVE_THREAD_FUNCTIONS |
