mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 22:40:54 -04:00
Merge branch 'for-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup updates from Tejun Heo:
"A lot updates for cgroup:
- The biggest one is cgroup's conversion to kernfs. cgroup took
after the long abandoned vfs-entangled sysfs implementation and
made it even more convoluted over time. cgroup's internal objects
were fused with vfs objects which also brought in vfs locking and
object lifetime rules. Naturally, there are places where vfs rules
don't fit and nasty hacks, such as credential switching or lock
dance interleaving inode mutex and cgroup_mutex with object serial
number comparison thrown in to decide whether the operation is
actually necessary, needed to be employed.
After conversion to kernfs, internal object lifetime and locking
rules are mostly isolated from vfs interactions allowing shedding
of several nasty hacks and overall simplification. This will also
allow implmentation of operations which may affect multiple cgroups
which weren't possible before as it would have required nesting
i_mutexes.
- Various simplifications including dropping of module support,
easier cgroup name/path handling, simplified cgroup file type
handling and task_cg_lists optimization.
- Prepatory changes for the planned unified hierarchy, which is still
a patchset away from being actually operational. The dummy
hierarchy is updated to serve as the default unified hierarchy.
Controllers which aren't claimed by other hierarchies are
associated with it, which BTW was what the dummy hierarchy was for
anyway.
- Various fixes from Li and others. This pull request includes some
patches to add missing slab.h to various subsystems. This was
triggered xattr.h include removal from cgroup.h. cgroup.h
indirectly got included a lot of files which brought in xattr.h
which brought in slab.h.
There are several merge commits - one to pull in kernfs updates
necessary for converting cgroup (already in upstream through
driver-core), others for interfering changes in the fixes branch"
* 'for-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: (74 commits)
cgroup: remove useless argument from cgroup_exit()
cgroup: fix spurious lockdep warning in cgroup_exit()
cgroup: Use RCU_INIT_POINTER(x, NULL) in cgroup.c
cgroup: break kernfs active_ref protection in cgroup directory operations
cgroup: fix cgroup_taskset walking order
cgroup: implement CFTYPE_ONLY_ON_DFL
cgroup: make cgrp_dfl_root mountable
cgroup: drop const from @buffer of cftype->write_string()
cgroup: rename cgroup_dummy_root and related names
cgroup: move ->subsys_mask from cgroupfs_root to cgroup
cgroup: treat cgroup_dummy_root as an equivalent hierarchy during rebinding
cgroup: remove NULL checks from [pr_cont_]cgroup_{name|path}()
cgroup: use cgroup_setup_root() to initialize cgroup_dummy_root
cgroup: reorganize cgroup bootstrapping
cgroup: relocate setting of CGRP_DEAD
cpuset: use rcu_read_lock() to protect task_cs()
cgroup_freezer: document freezer_fork() subtleties
cgroup: update cgroup_transfer_tasks() to either succeed or fail
cgroup: drop task_lock() protection around task->cgroups
cgroup: update how a newly forked task gets associated with css_set
...
This commit is contained in:
commit
32d01dc7be
32 changed files with 1913 additions and 2739 deletions
3749
kernel/cgroup.c
3749
kernel/cgroup.c
File diff suppressed because it is too large
Load diff
|
|
@ -52,7 +52,7 @@ static inline struct freezer *css_freezer(struct cgroup_subsys_state *css)
|
|||
|
||||
static inline struct freezer *task_freezer(struct task_struct *task)
|
||||
{
|
||||
return css_freezer(task_css(task, freezer_subsys_id));
|
||||
return css_freezer(task_css(task, freezer_cgrp_id));
|
||||
}
|
||||
|
||||
static struct freezer *parent_freezer(struct freezer *freezer)
|
||||
|
|
@ -84,8 +84,6 @@ static const char *freezer_state_strs(unsigned int state)
|
|||
return "THAWED";
|
||||
};
|
||||
|
||||
struct cgroup_subsys freezer_subsys;
|
||||
|
||||
static struct cgroup_subsys_state *
|
||||
freezer_css_alloc(struct cgroup_subsys_state *parent_css)
|
||||
{
|
||||
|
|
@ -189,7 +187,7 @@ static void freezer_attach(struct cgroup_subsys_state *new_css,
|
|||
* current state before executing the following - !frozen tasks may
|
||||
* be visible in a FROZEN cgroup and frozen tasks in a THAWED one.
|
||||
*/
|
||||
cgroup_taskset_for_each(task, new_css, tset) {
|
||||
cgroup_taskset_for_each(task, tset) {
|
||||
if (!(freezer->state & CGROUP_FREEZING)) {
|
||||
__thaw_task(task);
|
||||
} else {
|
||||
|
|
@ -216,6 +214,16 @@ static void freezer_attach(struct cgroup_subsys_state *new_css,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* freezer_fork - cgroup post fork callback
|
||||
* @task: a task which has just been forked
|
||||
*
|
||||
* @task has just been created and should conform to the current state of
|
||||
* the cgroup_freezer it belongs to. This function may race against
|
||||
* freezer_attach(). Losing to freezer_attach() means that we don't have
|
||||
* to do anything as freezer_attach() will put @task into the appropriate
|
||||
* state.
|
||||
*/
|
||||
static void freezer_fork(struct task_struct *task)
|
||||
{
|
||||
struct freezer *freezer;
|
||||
|
|
@ -224,14 +232,26 @@ static void freezer_fork(struct task_struct *task)
|
|||
freezer = task_freezer(task);
|
||||
|
||||
/*
|
||||
* The root cgroup is non-freezable, so we can skip the
|
||||
* following check.
|
||||
* The root cgroup is non-freezable, so we can skip locking the
|
||||
* freezer. This is safe regardless of race with task migration.
|
||||
* If we didn't race or won, skipping is obviously the right thing
|
||||
* to do. If we lost and root is the new cgroup, noop is still the
|
||||
* right thing to do.
|
||||
*/
|
||||
if (!parent_freezer(freezer))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Grab @freezer->lock and freeze @task after verifying @task still
|
||||
* belongs to @freezer and it's freezing. The former is for the
|
||||
* case where we have raced against task migration and lost and
|
||||
* @task is already in a different cgroup which may not be frozen.
|
||||
* This isn't strictly necessary as freeze_task() is allowed to be
|
||||
* called spuriously but let's do it anyway for, if nothing else,
|
||||
* documentation.
|
||||
*/
|
||||
spin_lock_irq(&freezer->lock);
|
||||
if (freezer->state & CGROUP_FREEZING)
|
||||
if (freezer == task_freezer(task) && (freezer->state & CGROUP_FREEZING))
|
||||
freeze_task(task);
|
||||
spin_unlock_irq(&freezer->lock);
|
||||
out:
|
||||
|
|
@ -422,7 +442,7 @@ static void freezer_change_state(struct freezer *freezer, bool freeze)
|
|||
}
|
||||
|
||||
static int freezer_write(struct cgroup_subsys_state *css, struct cftype *cft,
|
||||
const char *buffer)
|
||||
char *buffer)
|
||||
{
|
||||
bool freeze;
|
||||
|
||||
|
|
@ -473,13 +493,11 @@ static struct cftype files[] = {
|
|||
{ } /* terminate */
|
||||
};
|
||||
|
||||
struct cgroup_subsys freezer_subsys = {
|
||||
.name = "freezer",
|
||||
struct cgroup_subsys freezer_cgrp_subsys = {
|
||||
.css_alloc = freezer_css_alloc,
|
||||
.css_online = freezer_css_online,
|
||||
.css_offline = freezer_css_offline,
|
||||
.css_free = freezer_css_free,
|
||||
.subsys_id = freezer_subsys_id,
|
||||
.attach = freezer_attach,
|
||||
.fork = freezer_fork,
|
||||
.base_cftypes = files,
|
||||
|
|
|
|||
262
kernel/cpuset.c
262
kernel/cpuset.c
|
|
@ -119,7 +119,7 @@ static inline struct cpuset *css_cs(struct cgroup_subsys_state *css)
|
|||
/* Retrieve the cpuset for a task */
|
||||
static inline struct cpuset *task_cs(struct task_struct *task)
|
||||
{
|
||||
return css_cs(task_css(task, cpuset_subsys_id));
|
||||
return css_cs(task_css(task, cpuset_cgrp_id));
|
||||
}
|
||||
|
||||
static inline struct cpuset *parent_cs(struct cpuset *cs)
|
||||
|
|
@ -467,7 +467,7 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
|
|||
* be changed to have empty cpus_allowed or mems_allowed.
|
||||
*/
|
||||
ret = -ENOSPC;
|
||||
if ((cgroup_task_count(cur->css.cgroup) || cur->attach_in_progress)) {
|
||||
if ((cgroup_has_tasks(cur->css.cgroup) || cur->attach_in_progress)) {
|
||||
if (!cpumask_empty(cur->cpus_allowed) &&
|
||||
cpumask_empty(trial->cpus_allowed))
|
||||
goto out;
|
||||
|
|
@ -828,56 +828,37 @@ static struct cpuset *effective_nodemask_cpuset(struct cpuset *cs)
|
|||
return cs;
|
||||
}
|
||||
|
||||
/**
|
||||
* cpuset_change_cpumask - make a task's cpus_allowed the same as its cpuset's
|
||||
* @tsk: task to test
|
||||
* @data: cpuset to @tsk belongs to
|
||||
*
|
||||
* Called by css_scan_tasks() for each task in a cgroup whose cpus_allowed
|
||||
* mask needs to be changed.
|
||||
*
|
||||
* We don't need to re-check for the cgroup/cpuset membership, since we're
|
||||
* holding cpuset_mutex at this point.
|
||||
*/
|
||||
static void cpuset_change_cpumask(struct task_struct *tsk, void *data)
|
||||
{
|
||||
struct cpuset *cs = data;
|
||||
struct cpuset *cpus_cs = effective_cpumask_cpuset(cs);
|
||||
|
||||
set_cpus_allowed_ptr(tsk, cpus_cs->cpus_allowed);
|
||||
}
|
||||
|
||||
/**
|
||||
* update_tasks_cpumask - Update the cpumasks of tasks in the cpuset.
|
||||
* @cs: the cpuset in which each task's cpus_allowed mask needs to be changed
|
||||
* @heap: if NULL, defer allocating heap memory to css_scan_tasks()
|
||||
*
|
||||
* Called with cpuset_mutex held
|
||||
*
|
||||
* The css_scan_tasks() function will scan all the tasks in a cgroup,
|
||||
* calling callback functions for each.
|
||||
*
|
||||
* No return value. It's guaranteed that css_scan_tasks() always returns 0
|
||||
* if @heap != NULL.
|
||||
* Iterate through each task of @cs updating its cpus_allowed to the
|
||||
* effective cpuset's. As this function is called with cpuset_mutex held,
|
||||
* cpuset membership stays stable.
|
||||
*/
|
||||
static void update_tasks_cpumask(struct cpuset *cs, struct ptr_heap *heap)
|
||||
static void update_tasks_cpumask(struct cpuset *cs)
|
||||
{
|
||||
css_scan_tasks(&cs->css, NULL, cpuset_change_cpumask, cs, heap);
|
||||
struct cpuset *cpus_cs = effective_cpumask_cpuset(cs);
|
||||
struct css_task_iter it;
|
||||
struct task_struct *task;
|
||||
|
||||
css_task_iter_start(&cs->css, &it);
|
||||
while ((task = css_task_iter_next(&it)))
|
||||
set_cpus_allowed_ptr(task, cpus_cs->cpus_allowed);
|
||||
css_task_iter_end(&it);
|
||||
}
|
||||
|
||||
/*
|
||||
* update_tasks_cpumask_hier - Update the cpumasks of tasks in the hierarchy.
|
||||
* @root_cs: the root cpuset of the hierarchy
|
||||
* @update_root: update root cpuset or not?
|
||||
* @heap: the heap used by css_scan_tasks()
|
||||
*
|
||||
* This will update cpumasks of tasks in @root_cs and all other empty cpusets
|
||||
* which take on cpumask of @root_cs.
|
||||
*
|
||||
* Called with cpuset_mutex held
|
||||
*/
|
||||
static void update_tasks_cpumask_hier(struct cpuset *root_cs,
|
||||
bool update_root, struct ptr_heap *heap)
|
||||
static void update_tasks_cpumask_hier(struct cpuset *root_cs, bool update_root)
|
||||
{
|
||||
struct cpuset *cp;
|
||||
struct cgroup_subsys_state *pos_css;
|
||||
|
|
@ -898,7 +879,7 @@ static void update_tasks_cpumask_hier(struct cpuset *root_cs,
|
|||
continue;
|
||||
rcu_read_unlock();
|
||||
|
||||
update_tasks_cpumask(cp, heap);
|
||||
update_tasks_cpumask(cp);
|
||||
|
||||
rcu_read_lock();
|
||||
css_put(&cp->css);
|
||||
|
|
@ -914,7 +895,6 @@ static void update_tasks_cpumask_hier(struct cpuset *root_cs,
|
|||
static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
|
||||
const char *buf)
|
||||
{
|
||||
struct ptr_heap heap;
|
||||
int retval;
|
||||
int is_load_balanced;
|
||||
|
||||
|
|
@ -947,19 +927,13 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
|
|||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
is_load_balanced = is_sched_load_balance(trialcs);
|
||||
|
||||
mutex_lock(&callback_mutex);
|
||||
cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed);
|
||||
mutex_unlock(&callback_mutex);
|
||||
|
||||
update_tasks_cpumask_hier(cs, true, &heap);
|
||||
|
||||
heap_free(&heap);
|
||||
update_tasks_cpumask_hier(cs, true);
|
||||
|
||||
if (is_load_balanced)
|
||||
rebuild_sched_domains_locked();
|
||||
|
|
@ -1048,53 +1022,22 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk,
|
|||
task_unlock(tsk);
|
||||
}
|
||||
|
||||
struct cpuset_change_nodemask_arg {
|
||||
struct cpuset *cs;
|
||||
nodemask_t *newmems;
|
||||
};
|
||||
|
||||
/*
|
||||
* Update task's mems_allowed and rebind its mempolicy and vmas' mempolicy
|
||||
* of it to cpuset's new mems_allowed, and migrate pages to new nodes if
|
||||
* memory_migrate flag is set. Called with cpuset_mutex held.
|
||||
*/
|
||||
static void cpuset_change_nodemask(struct task_struct *p, void *data)
|
||||
{
|
||||
struct cpuset_change_nodemask_arg *arg = data;
|
||||
struct cpuset *cs = arg->cs;
|
||||
struct mm_struct *mm;
|
||||
int migrate;
|
||||
|
||||
cpuset_change_task_nodemask(p, arg->newmems);
|
||||
|
||||
mm = get_task_mm(p);
|
||||
if (!mm)
|
||||
return;
|
||||
|
||||
migrate = is_memory_migrate(cs);
|
||||
|
||||
mpol_rebind_mm(mm, &cs->mems_allowed);
|
||||
if (migrate)
|
||||
cpuset_migrate_mm(mm, &cs->old_mems_allowed, arg->newmems);
|
||||
mmput(mm);
|
||||
}
|
||||
|
||||
static void *cpuset_being_rebound;
|
||||
|
||||
/**
|
||||
* update_tasks_nodemask - Update the nodemasks of tasks in the cpuset.
|
||||
* @cs: the cpuset in which each task's mems_allowed mask needs to be changed
|
||||
* @heap: if NULL, defer allocating heap memory to css_scan_tasks()
|
||||
*
|
||||
* Called with cpuset_mutex held. No return value. It's guaranteed that
|
||||
* css_scan_tasks() always returns 0 if @heap != NULL.
|
||||
* Iterate through each task of @cs updating its mems_allowed to the
|
||||
* effective cpuset's. As this function is called with cpuset_mutex held,
|
||||
* cpuset membership stays stable.
|
||||
*/
|
||||
static void update_tasks_nodemask(struct cpuset *cs, struct ptr_heap *heap)
|
||||
static void update_tasks_nodemask(struct cpuset *cs)
|
||||
{
|
||||
static nodemask_t newmems; /* protected by cpuset_mutex */
|
||||
struct cpuset *mems_cs = effective_nodemask_cpuset(cs);
|
||||
struct cpuset_change_nodemask_arg arg = { .cs = cs,
|
||||
.newmems = &newmems };
|
||||
struct css_task_iter it;
|
||||
struct task_struct *task;
|
||||
|
||||
cpuset_being_rebound = cs; /* causes mpol_dup() rebind */
|
||||
|
||||
|
|
@ -1110,7 +1053,25 @@ static void update_tasks_nodemask(struct cpuset *cs, struct ptr_heap *heap)
|
|||
* It's ok if we rebind the same mm twice; mpol_rebind_mm()
|
||||
* is idempotent. Also migrate pages in each mm to new nodes.
|
||||
*/
|
||||
css_scan_tasks(&cs->css, NULL, cpuset_change_nodemask, &arg, heap);
|
||||
css_task_iter_start(&cs->css, &it);
|
||||
while ((task = css_task_iter_next(&it))) {
|
||||
struct mm_struct *mm;
|
||||
bool migrate;
|
||||
|
||||
cpuset_change_task_nodemask(task, &newmems);
|
||||
|
||||
mm = get_task_mm(task);
|
||||
if (!mm)
|
||||
continue;
|
||||
|
||||
migrate = is_memory_migrate(cs);
|
||||
|
||||
mpol_rebind_mm(mm, &cs->mems_allowed);
|
||||
if (migrate)
|
||||
cpuset_migrate_mm(mm, &cs->old_mems_allowed, &newmems);
|
||||
mmput(mm);
|
||||
}
|
||||
css_task_iter_end(&it);
|
||||
|
||||
/*
|
||||
* All the tasks' nodemasks have been updated, update
|
||||
|
|
@ -1126,15 +1087,13 @@ static void update_tasks_nodemask(struct cpuset *cs, struct ptr_heap *heap)
|
|||
* update_tasks_nodemask_hier - Update the nodemasks of tasks in the hierarchy.
|
||||
* @cs: the root cpuset of the hierarchy
|
||||
* @update_root: update the root cpuset or not?
|
||||
* @heap: the heap used by css_scan_tasks()
|
||||
*
|
||||
* This will update nodemasks of tasks in @root_cs and all other empty cpusets
|
||||
* which take on nodemask of @root_cs.
|
||||
*
|
||||
* Called with cpuset_mutex held
|
||||
*/
|
||||
static void update_tasks_nodemask_hier(struct cpuset *root_cs,
|
||||
bool update_root, struct ptr_heap *heap)
|
||||
static void update_tasks_nodemask_hier(struct cpuset *root_cs, bool update_root)
|
||||
{
|
||||
struct cpuset *cp;
|
||||
struct cgroup_subsys_state *pos_css;
|
||||
|
|
@ -1155,7 +1114,7 @@ static void update_tasks_nodemask_hier(struct cpuset *root_cs,
|
|||
continue;
|
||||
rcu_read_unlock();
|
||||
|
||||
update_tasks_nodemask(cp, heap);
|
||||
update_tasks_nodemask(cp);
|
||||
|
||||
rcu_read_lock();
|
||||
css_put(&cp->css);
|
||||
|
|
@ -1180,7 +1139,6 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
|
|||
const char *buf)
|
||||
{
|
||||
int retval;
|
||||
struct ptr_heap heap;
|
||||
|
||||
/*
|
||||
* top_cpuset.mems_allowed tracks node_stats[N_MEMORY];
|
||||
|
|
@ -1219,17 +1177,11 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
|
|||
if (retval < 0)
|
||||
goto done;
|
||||
|
||||
retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL);
|
||||
if (retval < 0)
|
||||
goto done;
|
||||
|
||||
mutex_lock(&callback_mutex);
|
||||
cs->mems_allowed = trialcs->mems_allowed;
|
||||
mutex_unlock(&callback_mutex);
|
||||
|
||||
update_tasks_nodemask_hier(cs, true, &heap);
|
||||
|
||||
heap_free(&heap);
|
||||
update_tasks_nodemask_hier(cs, true);
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -1256,39 +1208,23 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cpuset_change_flag - make a task's spread flags the same as its cpuset's
|
||||
* @tsk: task to be updated
|
||||
* @data: cpuset to @tsk belongs to
|
||||
*
|
||||
* Called by css_scan_tasks() for each task in a cgroup.
|
||||
*
|
||||
* We don't need to re-check for the cgroup/cpuset membership, since we're
|
||||
* holding cpuset_mutex at this point.
|
||||
*/
|
||||
static void cpuset_change_flag(struct task_struct *tsk, void *data)
|
||||
{
|
||||
struct cpuset *cs = data;
|
||||
|
||||
cpuset_update_task_spread_flag(cs, tsk);
|
||||
}
|
||||
|
||||
/**
|
||||
* update_tasks_flags - update the spread flags of tasks in the cpuset.
|
||||
* @cs: the cpuset in which each task's spread flags needs to be changed
|
||||
* @heap: if NULL, defer allocating heap memory to css_scan_tasks()
|
||||
*
|
||||
* Called with cpuset_mutex held
|
||||
*
|
||||
* The css_scan_tasks() function will scan all the tasks in a cgroup,
|
||||
* calling callback functions for each.
|
||||
*
|
||||
* No return value. It's guaranteed that css_scan_tasks() always returns 0
|
||||
* if @heap != NULL.
|
||||
* Iterate through each task of @cs updating its spread flags. As this
|
||||
* function is called with cpuset_mutex held, cpuset membership stays
|
||||
* stable.
|
||||
*/
|
||||
static void update_tasks_flags(struct cpuset *cs, struct ptr_heap *heap)
|
||||
static void update_tasks_flags(struct cpuset *cs)
|
||||
{
|
||||
css_scan_tasks(&cs->css, NULL, cpuset_change_flag, cs, heap);
|
||||
struct css_task_iter it;
|
||||
struct task_struct *task;
|
||||
|
||||
css_task_iter_start(&cs->css, &it);
|
||||
while ((task = css_task_iter_next(&it)))
|
||||
cpuset_update_task_spread_flag(cs, task);
|
||||
css_task_iter_end(&it);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1306,7 +1242,6 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
|
|||
struct cpuset *trialcs;
|
||||
int balance_flag_changed;
|
||||
int spread_flag_changed;
|
||||
struct ptr_heap heap;
|
||||
int err;
|
||||
|
||||
trialcs = alloc_trial_cpuset(cs);
|
||||
|
|
@ -1322,10 +1257,6 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
|
|||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
balance_flag_changed = (is_sched_load_balance(cs) !=
|
||||
is_sched_load_balance(trialcs));
|
||||
|
||||
|
|
@ -1340,8 +1271,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
|
|||
rebuild_sched_domains_locked();
|
||||
|
||||
if (spread_flag_changed)
|
||||
update_tasks_flags(cs, &heap);
|
||||
heap_free(&heap);
|
||||
update_tasks_flags(cs);
|
||||
out:
|
||||
free_trial_cpuset(trialcs);
|
||||
return err;
|
||||
|
|
@ -1445,6 +1375,8 @@ static int fmeter_getrate(struct fmeter *fmp)
|
|||
return val;
|
||||
}
|
||||
|
||||
static struct cpuset *cpuset_attach_old_cs;
|
||||
|
||||
/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
|
||||
static int cpuset_can_attach(struct cgroup_subsys_state *css,
|
||||
struct cgroup_taskset *tset)
|
||||
|
|
@ -1453,6 +1385,9 @@ static int cpuset_can_attach(struct cgroup_subsys_state *css,
|
|||
struct task_struct *task;
|
||||
int ret;
|
||||
|
||||
/* used later by cpuset_attach() */
|
||||
cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset));
|
||||
|
||||
mutex_lock(&cpuset_mutex);
|
||||
|
||||
/*
|
||||
|
|
@ -1464,7 +1399,7 @@ static int cpuset_can_attach(struct cgroup_subsys_state *css,
|
|||
(cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)))
|
||||
goto out_unlock;
|
||||
|
||||
cgroup_taskset_for_each(task, css, tset) {
|
||||
cgroup_taskset_for_each(task, tset) {
|
||||
/*
|
||||
* Kthreads which disallow setaffinity shouldn't be moved
|
||||
* to a new cpuset; we don't want to change their cpu
|
||||
|
|
@ -1516,10 +1451,8 @@ static void cpuset_attach(struct cgroup_subsys_state *css,
|
|||
struct mm_struct *mm;
|
||||
struct task_struct *task;
|
||||
struct task_struct *leader = cgroup_taskset_first(tset);
|
||||
struct cgroup_subsys_state *oldcss = cgroup_taskset_cur_css(tset,
|
||||
cpuset_subsys_id);
|
||||
struct cpuset *cs = css_cs(css);
|
||||
struct cpuset *oldcs = css_cs(oldcss);
|
||||
struct cpuset *oldcs = cpuset_attach_old_cs;
|
||||
struct cpuset *cpus_cs = effective_cpumask_cpuset(cs);
|
||||
struct cpuset *mems_cs = effective_nodemask_cpuset(cs);
|
||||
|
||||
|
|
@ -1533,7 +1466,7 @@ static void cpuset_attach(struct cgroup_subsys_state *css,
|
|||
|
||||
guarantee_online_mems(mems_cs, &cpuset_attach_nodemask_to);
|
||||
|
||||
cgroup_taskset_for_each(task, css, tset) {
|
||||
cgroup_taskset_for_each(task, tset) {
|
||||
/*
|
||||
* can_attach beforehand should guarantee that this doesn't
|
||||
* fail. TODO: have a better way to handle failure here
|
||||
|
|
@ -1673,7 +1606,7 @@ out_unlock:
|
|||
* Common handling for a write to a "cpus" or "mems" file.
|
||||
*/
|
||||
static int cpuset_write_resmask(struct cgroup_subsys_state *css,
|
||||
struct cftype *cft, const char *buf)
|
||||
struct cftype *cft, char *buf)
|
||||
{
|
||||
struct cpuset *cs = css_cs(css);
|
||||
struct cpuset *trialcs;
|
||||
|
|
@ -2020,8 +1953,7 @@ static void cpuset_css_free(struct cgroup_subsys_state *css)
|
|||
kfree(cs);
|
||||
}
|
||||
|
||||
struct cgroup_subsys cpuset_subsys = {
|
||||
.name = "cpuset",
|
||||
struct cgroup_subsys cpuset_cgrp_subsys = {
|
||||
.css_alloc = cpuset_css_alloc,
|
||||
.css_online = cpuset_css_online,
|
||||
.css_offline = cpuset_css_offline,
|
||||
|
|
@ -2029,7 +1961,6 @@ struct cgroup_subsys cpuset_subsys = {
|
|||
.can_attach = cpuset_can_attach,
|
||||
.cancel_attach = cpuset_cancel_attach,
|
||||
.attach = cpuset_attach,
|
||||
.subsys_id = cpuset_subsys_id,
|
||||
.base_cftypes = files,
|
||||
.early_init = 1,
|
||||
};
|
||||
|
|
@ -2086,10 +2017,9 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs)
|
|||
parent = parent_cs(parent);
|
||||
|
||||
if (cgroup_transfer_tasks(parent->css.cgroup, cs->css.cgroup)) {
|
||||
rcu_read_lock();
|
||||
printk(KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset %s\n",
|
||||
cgroup_name(cs->css.cgroup));
|
||||
rcu_read_unlock();
|
||||
printk(KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset ");
|
||||
pr_cont_cgroup_name(cs->css.cgroup);
|
||||
pr_cont("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2137,7 +2067,7 @@ retry:
|
|||
*/
|
||||
if ((sane && cpumask_empty(cs->cpus_allowed)) ||
|
||||
(!cpumask_empty(&off_cpus) && !cpumask_empty(cs->cpus_allowed)))
|
||||
update_tasks_cpumask(cs, NULL);
|
||||
update_tasks_cpumask(cs);
|
||||
|
||||
mutex_lock(&callback_mutex);
|
||||
nodes_andnot(cs->mems_allowed, cs->mems_allowed, off_mems);
|
||||
|
|
@ -2151,7 +2081,7 @@ retry:
|
|||
*/
|
||||
if ((sane && nodes_empty(cs->mems_allowed)) ||
|
||||
(!nodes_empty(off_mems) && !nodes_empty(cs->mems_allowed)))
|
||||
update_tasks_nodemask(cs, NULL);
|
||||
update_tasks_nodemask(cs);
|
||||
|
||||
is_empty = cpumask_empty(cs->cpus_allowed) ||
|
||||
nodes_empty(cs->mems_allowed);
|
||||
|
|
@ -2213,7 +2143,7 @@ static void cpuset_hotplug_workfn(struct work_struct *work)
|
|||
mutex_lock(&callback_mutex);
|
||||
top_cpuset.mems_allowed = new_mems;
|
||||
mutex_unlock(&callback_mutex);
|
||||
update_tasks_nodemask(&top_cpuset, NULL);
|
||||
update_tasks_nodemask(&top_cpuset);
|
||||
}
|
||||
|
||||
mutex_unlock(&cpuset_mutex);
|
||||
|
|
@ -2305,10 +2235,10 @@ void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask)
|
|||
struct cpuset *cpus_cs;
|
||||
|
||||
mutex_lock(&callback_mutex);
|
||||
task_lock(tsk);
|
||||
rcu_read_lock();
|
||||
cpus_cs = effective_cpumask_cpuset(task_cs(tsk));
|
||||
guarantee_online_cpus(cpus_cs, pmask);
|
||||
task_unlock(tsk);
|
||||
rcu_read_unlock();
|
||||
mutex_unlock(&callback_mutex);
|
||||
}
|
||||
|
||||
|
|
@ -2361,10 +2291,10 @@ nodemask_t cpuset_mems_allowed(struct task_struct *tsk)
|
|||
nodemask_t mask;
|
||||
|
||||
mutex_lock(&callback_mutex);
|
||||
task_lock(tsk);
|
||||
rcu_read_lock();
|
||||
mems_cs = effective_nodemask_cpuset(task_cs(tsk));
|
||||
guarantee_online_mems(mems_cs, &mask);
|
||||
task_unlock(tsk);
|
||||
rcu_read_unlock();
|
||||
mutex_unlock(&callback_mutex);
|
||||
|
||||
return mask;
|
||||
|
|
@ -2480,10 +2410,10 @@ int __cpuset_node_allowed_softwall(int node, gfp_t gfp_mask)
|
|||
/* Not hardwall and node outside mems_allowed: scan up cpusets */
|
||||
mutex_lock(&callback_mutex);
|
||||
|
||||
task_lock(current);
|
||||
rcu_read_lock();
|
||||
cs = nearest_hardwall_ancestor(task_cs(current));
|
||||
allowed = node_isset(node, cs->mems_allowed);
|
||||
task_unlock(current);
|
||||
rcu_read_unlock();
|
||||
|
||||
mutex_unlock(&callback_mutex);
|
||||
return allowed;
|
||||
|
|
@ -2609,27 +2539,27 @@ int cpuset_mems_allowed_intersects(const struct task_struct *tsk1,
|
|||
* @task: pointer to task_struct of some task.
|
||||
*
|
||||
* Description: Prints @task's name, cpuset name, and cached copy of its
|
||||
* mems_allowed to the kernel log. Must hold task_lock(task) to allow
|
||||
* dereferencing task_cs(task).
|
||||
* mems_allowed to the kernel log.
|
||||
*/
|
||||
void cpuset_print_task_mems_allowed(struct task_struct *tsk)
|
||||
{
|
||||
/* Statically allocated to prevent using excess stack. */
|
||||
static char cpuset_nodelist[CPUSET_NODELIST_LEN];
|
||||
static DEFINE_SPINLOCK(cpuset_buffer_lock);
|
||||
struct cgroup *cgrp;
|
||||
|
||||
struct cgroup *cgrp = task_cs(tsk)->css.cgroup;
|
||||
|
||||
rcu_read_lock();
|
||||
spin_lock(&cpuset_buffer_lock);
|
||||
rcu_read_lock();
|
||||
|
||||
cgrp = task_cs(tsk)->css.cgroup;
|
||||
nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN,
|
||||
tsk->mems_allowed);
|
||||
printk(KERN_INFO "%s cpuset=%s mems_allowed=%s\n",
|
||||
tsk->comm, cgroup_name(cgrp), cpuset_nodelist);
|
||||
printk(KERN_INFO "%s cpuset=", tsk->comm);
|
||||
pr_cont_cgroup_name(cgrp);
|
||||
pr_cont(" mems_allowed=%s\n", cpuset_nodelist);
|
||||
|
||||
spin_unlock(&cpuset_buffer_lock);
|
||||
rcu_read_unlock();
|
||||
spin_unlock(&cpuset_buffer_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2660,9 +2590,9 @@ int cpuset_memory_pressure_enabled __read_mostly;
|
|||
|
||||
void __cpuset_memory_pressure_bump(void)
|
||||
{
|
||||
task_lock(current);
|
||||
rcu_read_lock();
|
||||
fmeter_markevent(&task_cs(current)->fmeter);
|
||||
task_unlock(current);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_PID_CPUSET
|
||||
|
|
@ -2679,12 +2609,12 @@ int proc_cpuset_show(struct seq_file *m, void *unused_v)
|
|||
{
|
||||
struct pid *pid;
|
||||
struct task_struct *tsk;
|
||||
char *buf;
|
||||
char *buf, *p;
|
||||
struct cgroup_subsys_state *css;
|
||||
int retval;
|
||||
|
||||
retval = -ENOMEM;
|
||||
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
buf = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (!buf)
|
||||
goto out;
|
||||
|
||||
|
|
@ -2694,14 +2624,16 @@ int proc_cpuset_show(struct seq_file *m, void *unused_v)
|
|||
if (!tsk)
|
||||
goto out_free;
|
||||
|
||||
retval = -ENAMETOOLONG;
|
||||
rcu_read_lock();
|
||||
css = task_css(tsk, cpuset_subsys_id);
|
||||
retval = cgroup_path(css->cgroup, buf, PAGE_SIZE);
|
||||
css = task_css(tsk, cpuset_cgrp_id);
|
||||
p = cgroup_path(css->cgroup, buf, PATH_MAX);
|
||||
rcu_read_unlock();
|
||||
if (retval < 0)
|
||||
if (!p)
|
||||
goto out_put_task;
|
||||
seq_puts(m, buf);
|
||||
seq_puts(m, p);
|
||||
seq_putc(m, '\n');
|
||||
retval = 0;
|
||||
out_put_task:
|
||||
put_task_struct(tsk);
|
||||
out_free:
|
||||
|
|
|
|||
|
|
@ -361,7 +361,7 @@ struct perf_cgroup {
|
|||
static inline struct perf_cgroup *
|
||||
perf_cgroup_from_task(struct task_struct *task)
|
||||
{
|
||||
return container_of(task_css(task, perf_subsys_id),
|
||||
return container_of(task_css(task, perf_event_cgrp_id),
|
||||
struct perf_cgroup, css);
|
||||
}
|
||||
|
||||
|
|
@ -389,11 +389,6 @@ perf_cgroup_match(struct perf_event *event)
|
|||
event->cgrp->css.cgroup);
|
||||
}
|
||||
|
||||
static inline bool perf_tryget_cgroup(struct perf_event *event)
|
||||
{
|
||||
return css_tryget(&event->cgrp->css);
|
||||
}
|
||||
|
||||
static inline void perf_put_cgroup(struct perf_event *event)
|
||||
{
|
||||
css_put(&event->cgrp->css);
|
||||
|
|
@ -612,9 +607,7 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
|
|||
if (!f.file)
|
||||
return -EBADF;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
css = css_from_dir(f.file->f_dentry, &perf_subsys);
|
||||
css = css_tryget_from_dir(f.file->f_dentry, &perf_event_cgrp_subsys);
|
||||
if (IS_ERR(css)) {
|
||||
ret = PTR_ERR(css);
|
||||
goto out;
|
||||
|
|
@ -623,13 +616,6 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
|
|||
cgrp = container_of(css, struct perf_cgroup, css);
|
||||
event->cgrp = cgrp;
|
||||
|
||||
/* must be done before we fput() the file */
|
||||
if (!perf_tryget_cgroup(event)) {
|
||||
event->cgrp = NULL;
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* all events in a group must monitor
|
||||
* the same cgroup because a task belongs
|
||||
|
|
@ -640,7 +626,6 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
|
|||
ret = -EINVAL;
|
||||
}
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
fdput(f);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -8053,7 +8038,7 @@ static void perf_cgroup_attach(struct cgroup_subsys_state *css,
|
|||
{
|
||||
struct task_struct *task;
|
||||
|
||||
cgroup_taskset_for_each(task, css, tset)
|
||||
cgroup_taskset_for_each(task, tset)
|
||||
task_function_call(task, __perf_cgroup_move, task);
|
||||
}
|
||||
|
||||
|
|
@ -8072,9 +8057,7 @@ static void perf_cgroup_exit(struct cgroup_subsys_state *css,
|
|||
task_function_call(task, __perf_cgroup_move, task);
|
||||
}
|
||||
|
||||
struct cgroup_subsys perf_subsys = {
|
||||
.name = "perf_event",
|
||||
.subsys_id = perf_subsys_id,
|
||||
struct cgroup_subsys perf_event_cgrp_subsys = {
|
||||
.css_alloc = perf_cgroup_css_alloc,
|
||||
.css_free = perf_cgroup_css_free,
|
||||
.exit = perf_cgroup_exit,
|
||||
|
|
|
|||
|
|
@ -797,7 +797,7 @@ void do_exit(long code)
|
|||
*/
|
||||
perf_event_exit_task(tsk);
|
||||
|
||||
cgroup_exit(tsk, 1);
|
||||
cgroup_exit(tsk);
|
||||
|
||||
if (group_dead)
|
||||
disassociate_ctty(1);
|
||||
|
|
|
|||
|
|
@ -1272,7 +1272,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|||
if (IS_ERR(p->mempolicy)) {
|
||||
retval = PTR_ERR(p->mempolicy);
|
||||
p->mempolicy = NULL;
|
||||
goto bad_fork_cleanup_cgroup;
|
||||
goto bad_fork_cleanup_threadgroup_lock;
|
||||
}
|
||||
mpol_fix_fork_child_flag(p);
|
||||
#endif
|
||||
|
|
@ -1525,11 +1525,10 @@ bad_fork_cleanup_policy:
|
|||
perf_event_free_task(p);
|
||||
#ifdef CONFIG_NUMA
|
||||
mpol_put(p->mempolicy);
|
||||
bad_fork_cleanup_cgroup:
|
||||
bad_fork_cleanup_threadgroup_lock:
|
||||
#endif
|
||||
if (clone_flags & CLONE_THREAD)
|
||||
threadgroup_change_end(current);
|
||||
cgroup_exit(p, 0);
|
||||
delayacct_tsk_free(p);
|
||||
module_put(task_thread_info(p)->exec_domain->module);
|
||||
bad_fork_cleanup_count:
|
||||
|
|
|
|||
|
|
@ -7230,7 +7230,7 @@ void sched_move_task(struct task_struct *tsk)
|
|||
if (unlikely(running))
|
||||
tsk->sched_class->put_prev_task(rq, tsk);
|
||||
|
||||
tg = container_of(task_css_check(tsk, cpu_cgroup_subsys_id,
|
||||
tg = container_of(task_css_check(tsk, cpu_cgrp_id,
|
||||
lockdep_is_held(&tsk->sighand->siglock)),
|
||||
struct task_group, css);
|
||||
tg = autogroup_task_group(tsk, tg);
|
||||
|
|
@ -7657,7 +7657,7 @@ static int cpu_cgroup_can_attach(struct cgroup_subsys_state *css,
|
|||
{
|
||||
struct task_struct *task;
|
||||
|
||||
cgroup_taskset_for_each(task, css, tset) {
|
||||
cgroup_taskset_for_each(task, tset) {
|
||||
#ifdef CONFIG_RT_GROUP_SCHED
|
||||
if (!sched_rt_can_attach(css_tg(css), task))
|
||||
return -EINVAL;
|
||||
|
|
@ -7675,7 +7675,7 @@ static void cpu_cgroup_attach(struct cgroup_subsys_state *css,
|
|||
{
|
||||
struct task_struct *task;
|
||||
|
||||
cgroup_taskset_for_each(task, css, tset)
|
||||
cgroup_taskset_for_each(task, tset)
|
||||
sched_move_task(task);
|
||||
}
|
||||
|
||||
|
|
@ -8014,8 +8014,7 @@ static struct cftype cpu_files[] = {
|
|||
{ } /* terminate */
|
||||
};
|
||||
|
||||
struct cgroup_subsys cpu_cgroup_subsys = {
|
||||
.name = "cpu",
|
||||
struct cgroup_subsys cpu_cgrp_subsys = {
|
||||
.css_alloc = cpu_cgroup_css_alloc,
|
||||
.css_free = cpu_cgroup_css_free,
|
||||
.css_online = cpu_cgroup_css_online,
|
||||
|
|
@ -8023,7 +8022,6 @@ struct cgroup_subsys cpu_cgroup_subsys = {
|
|||
.can_attach = cpu_cgroup_can_attach,
|
||||
.attach = cpu_cgroup_attach,
|
||||
.exit = cpu_cgroup_exit,
|
||||
.subsys_id = cpu_cgroup_subsys_id,
|
||||
.base_cftypes = cpu_files,
|
||||
.early_init = 1,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ static inline struct cpuacct *css_ca(struct cgroup_subsys_state *css)
|
|||
/* return cpu accounting group to which this task belongs */
|
||||
static inline struct cpuacct *task_ca(struct task_struct *tsk)
|
||||
{
|
||||
return css_ca(task_css(tsk, cpuacct_subsys_id));
|
||||
return css_ca(task_css(tsk, cpuacct_cgrp_id));
|
||||
}
|
||||
|
||||
static inline struct cpuacct *parent_ca(struct cpuacct *ca)
|
||||
|
|
@ -275,11 +275,9 @@ void cpuacct_account_field(struct task_struct *p, int index, u64 val)
|
|||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
struct cgroup_subsys cpuacct_subsys = {
|
||||
.name = "cpuacct",
|
||||
struct cgroup_subsys cpuacct_cgrp_subsys = {
|
||||
.css_alloc = cpuacct_css_alloc,
|
||||
.css_free = cpuacct_css_free,
|
||||
.subsys_id = cpuacct_subsys_id,
|
||||
.base_cftypes = files,
|
||||
.early_init = 1,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -111,8 +111,7 @@ static char *task_group_path(struct task_group *tg)
|
|||
if (autogroup_path(tg, group_path, PATH_MAX))
|
||||
return group_path;
|
||||
|
||||
cgroup_path(tg->css.cgroup, group_path, PATH_MAX);
|
||||
return group_path;
|
||||
return cgroup_path(tg->css.cgroup, group_path, PATH_MAX);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue