Merge branch 'for-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup updates from Tejun Heo: - cgroup v2 interface is now official. It's no longer hidden behind a devel flag and can be mounted using the new cgroup2 fs type. Unfortunately, cpu v2 interface hasn't made it yet due to the discussion around in-process hierarchical resource distribution and only memory and io controllers can be used on the v2 interface at the moment. - The existing documentation which has always been a bit of mess is relocated under Documentation/cgroup-v1/. Documentation/cgroup-v2.txt is added as the authoritative documentation for the v2 interface. - Some features are added through for-4.5-ancestor-test branch to enable netfilter xt_cgroup match to use cgroup v2 paths. The actual netfilter changes will be merged through the net tree which pulled in the said branch. - Various cleanups * 'for-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup: rename cgroup documentations cgroup: fix a typo. cgroup: Remove resource_counter.txt in Documentation/cgroup-legacy/00-INDEX. cgroup: demote subsystem init messages to KERN_DEBUG cgroup: Fix uninitialized variable warning cgroup: put controller Kconfig options in meaningful order cgroup: clean up the kernel configuration menu nomenclature cgroup_pids: fix a typo. Subject: cgroup: Fix incomplete dd command in blkio documentation cgroup: kill cgrp_ss_priv[CGROUP_CANFORK_COUNT] and friends cpuset: Replace all instances of time_t with time64_t cgroup: replace unified-hierarchy.txt with a proper cgroup v2 documentation cgroup: rename Documentation/cgroups/ to Documentation/cgroup-legacy/ cgroup: replace __DEVEL__sane_behavior with cgroup2 fs type
This commit is contained in:
+32
-49
@@ -211,6 +211,7 @@ static unsigned long have_free_callback __read_mostly;
|
||||
/* Ditto for the can_fork callback. */
|
||||
static unsigned long have_canfork_callback __read_mostly;
|
||||
|
||||
static struct file_system_type cgroup2_fs_type;
|
||||
static struct cftype cgroup_dfl_base_files[];
|
||||
static struct cftype cgroup_legacy_base_files[];
|
||||
|
||||
@@ -1623,10 +1624,6 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
|
||||
all_ss = true;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(token, "__DEVEL__sane_behavior")) {
|
||||
opts->flags |= CGRP_ROOT_SANE_BEHAVIOR;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(token, "noprefix")) {
|
||||
opts->flags |= CGRP_ROOT_NOPREFIX;
|
||||
continue;
|
||||
@@ -1693,15 +1690,6 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (opts->flags & CGRP_ROOT_SANE_BEHAVIOR) {
|
||||
pr_warn("sane_behavior: this is still under development and its behaviors will change, proceed at your own risk\n");
|
||||
if (nr_opts != 1) {
|
||||
pr_err("sane_behavior: no other mount options allowed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the 'all' option was specified select all the subsystems,
|
||||
* otherwise if 'none', 'name=' and a subsystem name options were
|
||||
@@ -1981,6 +1969,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *unused_dev_name,
|
||||
void *data)
|
||||
{
|
||||
bool is_v2 = fs_type == &cgroup2_fs_type;
|
||||
struct super_block *pinned_sb = NULL;
|
||||
struct cgroup_subsys *ss;
|
||||
struct cgroup_root *root;
|
||||
@@ -1997,6 +1986,17 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
||||
if (!use_task_css_set_links)
|
||||
cgroup_enable_task_cg_lists();
|
||||
|
||||
if (is_v2) {
|
||||
if (data) {
|
||||
pr_err("cgroup2: unknown option \"%s\"\n", (char *)data);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
cgrp_dfl_root_visible = true;
|
||||
root = &cgrp_dfl_root;
|
||||
cgroup_get(&root->cgrp);
|
||||
goto out_mount;
|
||||
}
|
||||
|
||||
mutex_lock(&cgroup_mutex);
|
||||
|
||||
/* First find the desired set of subsystems */
|
||||
@@ -2004,15 +2004,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
/* look for a matching existing root */
|
||||
if (opts.flags & CGRP_ROOT_SANE_BEHAVIOR) {
|
||||
cgrp_dfl_root_visible = true;
|
||||
root = &cgrp_dfl_root;
|
||||
cgroup_get(&root->cgrp);
|
||||
ret = 0;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destruction of cgroup root is asynchronous, so subsystems may
|
||||
* still be dying after the previous unmount. Let's drain the
|
||||
@@ -2123,9 +2114,10 @@ out_free:
|
||||
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
out_mount:
|
||||
dentry = kernfs_mount(fs_type, flags, root->kf_root,
|
||||
CGROUP_SUPER_MAGIC, &new_sb);
|
||||
is_v2 ? CGROUP2_SUPER_MAGIC : CGROUP_SUPER_MAGIC,
|
||||
&new_sb);
|
||||
if (IS_ERR(dentry) || !new_sb)
|
||||
cgroup_put(&root->cgrp);
|
||||
|
||||
@@ -2168,6 +2160,12 @@ static struct file_system_type cgroup_fs_type = {
|
||||
.kill_sb = cgroup_kill_sb,
|
||||
};
|
||||
|
||||
static struct file_system_type cgroup2_fs_type = {
|
||||
.name = "cgroup2",
|
||||
.mount = cgroup_mount,
|
||||
.kill_sb = cgroup_kill_sb,
|
||||
};
|
||||
|
||||
/**
|
||||
* task_cgroup_path - cgroup path of a task in the first cgroup hierarchy
|
||||
* @task: target task
|
||||
@@ -4039,7 +4037,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
|
||||
goto out_err;
|
||||
|
||||
/*
|
||||
* Migrate tasks one-by-one until @form is empty. This fails iff
|
||||
* Migrate tasks one-by-one until @from is empty. This fails iff
|
||||
* ->can_attach() fails.
|
||||
*/
|
||||
do {
|
||||
@@ -5171,7 +5169,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early)
|
||||
{
|
||||
struct cgroup_subsys_state *css;
|
||||
|
||||
printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
|
||||
pr_debug("Initializing cgroup subsys %s\n", ss->name);
|
||||
|
||||
mutex_lock(&cgroup_mutex);
|
||||
|
||||
@@ -5329,6 +5327,7 @@ int __init cgroup_init(void)
|
||||
|
||||
WARN_ON(sysfs_create_mount_point(fs_kobj, "cgroup"));
|
||||
WARN_ON(register_filesystem(&cgroup_fs_type));
|
||||
WARN_ON(register_filesystem(&cgroup2_fs_type));
|
||||
WARN_ON(!proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations));
|
||||
|
||||
return 0;
|
||||
@@ -5472,19 +5471,6 @@ static const struct file_operations proc_cgroupstats_operations = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static void **subsys_canfork_priv_p(void *ss_priv[CGROUP_CANFORK_COUNT], int i)
|
||||
{
|
||||
if (CGROUP_CANFORK_START <= i && i < CGROUP_CANFORK_END)
|
||||
return &ss_priv[i - CGROUP_CANFORK_START];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *subsys_canfork_priv(void *ss_priv[CGROUP_CANFORK_COUNT], int i)
|
||||
{
|
||||
void **private = subsys_canfork_priv_p(ss_priv, i);
|
||||
return private ? *private : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* cgroup_fork - initialize cgroup related fields during copy_process()
|
||||
* @child: pointer to task_struct of forking parent process.
|
||||
@@ -5507,14 +5493,13 @@ void cgroup_fork(struct task_struct *child)
|
||||
* returns an error, the fork aborts with that error code. This allows for
|
||||
* a cgroup subsystem to conditionally allow or deny new forks.
|
||||
*/
|
||||
int cgroup_can_fork(struct task_struct *child,
|
||||
void *ss_priv[CGROUP_CANFORK_COUNT])
|
||||
int cgroup_can_fork(struct task_struct *child)
|
||||
{
|
||||
struct cgroup_subsys *ss;
|
||||
int i, j, ret;
|
||||
|
||||
for_each_subsys_which(ss, i, &have_canfork_callback) {
|
||||
ret = ss->can_fork(child, subsys_canfork_priv_p(ss_priv, i));
|
||||
ret = ss->can_fork(child);
|
||||
if (ret)
|
||||
goto out_revert;
|
||||
}
|
||||
@@ -5526,7 +5511,7 @@ out_revert:
|
||||
if (j >= i)
|
||||
break;
|
||||
if (ss->cancel_fork)
|
||||
ss->cancel_fork(child, subsys_canfork_priv(ss_priv, j));
|
||||
ss->cancel_fork(child);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -5539,15 +5524,14 @@ out_revert:
|
||||
* This calls the cancel_fork() callbacks if a fork failed *after*
|
||||
* cgroup_can_fork() succeded.
|
||||
*/
|
||||
void cgroup_cancel_fork(struct task_struct *child,
|
||||
void *ss_priv[CGROUP_CANFORK_COUNT])
|
||||
void cgroup_cancel_fork(struct task_struct *child)
|
||||
{
|
||||
struct cgroup_subsys *ss;
|
||||
int i;
|
||||
|
||||
for_each_subsys(ss, i)
|
||||
if (ss->cancel_fork)
|
||||
ss->cancel_fork(child, subsys_canfork_priv(ss_priv, i));
|
||||
ss->cancel_fork(child);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5560,8 +5544,7 @@ void cgroup_cancel_fork(struct task_struct *child,
|
||||
* cgroup_task_iter_start() - to guarantee that the new task ends up on its
|
||||
* list.
|
||||
*/
|
||||
void cgroup_post_fork(struct task_struct *child,
|
||||
void *old_ss_priv[CGROUP_CANFORK_COUNT])
|
||||
void cgroup_post_fork(struct task_struct *child)
|
||||
{
|
||||
struct cgroup_subsys *ss;
|
||||
int i;
|
||||
@@ -5605,7 +5588,7 @@ void cgroup_post_fork(struct task_struct *child,
|
||||
* and addition to css_set.
|
||||
*/
|
||||
for_each_subsys_which(ss, i, &have_fork_callback)
|
||||
ss->fork(child, subsys_canfork_priv(old_ss_priv, i));
|
||||
ss->fork(child);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -200,7 +200,7 @@ static void freezer_attach(struct cgroup_taskset *tset)
|
||||
* to do anything as freezer_attach() will put @task into the appropriate
|
||||
* state.
|
||||
*/
|
||||
static void freezer_fork(struct task_struct *task, void *private)
|
||||
static void freezer_fork(struct task_struct *task)
|
||||
{
|
||||
struct freezer *freezer;
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ static void pids_charge(struct pids_cgroup *pids, int num)
|
||||
*
|
||||
* This function follows the set limit. It will fail if the charge would cause
|
||||
* the new value to exceed the hierarchical limit. Returns 0 if the charge
|
||||
* succeded, otherwise -EAGAIN.
|
||||
* succeeded, otherwise -EAGAIN.
|
||||
*/
|
||||
static int pids_try_charge(struct pids_cgroup *pids, int num)
|
||||
{
|
||||
@@ -209,7 +209,7 @@ static void pids_cancel_attach(struct cgroup_taskset *tset)
|
||||
* task_css_check(true) in pids_can_fork() and pids_cancel_fork() relies
|
||||
* on threadgroup_change_begin() held by the copy_process().
|
||||
*/
|
||||
static int pids_can_fork(struct task_struct *task, void **priv_p)
|
||||
static int pids_can_fork(struct task_struct *task)
|
||||
{
|
||||
struct cgroup_subsys_state *css;
|
||||
struct pids_cgroup *pids;
|
||||
@@ -219,7 +219,7 @@ static int pids_can_fork(struct task_struct *task, void **priv_p)
|
||||
return pids_try_charge(pids, 1);
|
||||
}
|
||||
|
||||
static void pids_cancel_fork(struct task_struct *task, void *priv)
|
||||
static void pids_cancel_fork(struct task_struct *task)
|
||||
{
|
||||
struct cgroup_subsys_state *css;
|
||||
struct pids_cgroup *pids;
|
||||
|
||||
+8
-4
@@ -51,6 +51,7 @@
|
||||
#include <linux/stat.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/time64.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/sort.h>
|
||||
|
||||
@@ -68,7 +69,7 @@ struct static_key cpusets_enabled_key __read_mostly = STATIC_KEY_INIT_FALSE;
|
||||
struct fmeter {
|
||||
int cnt; /* unprocessed events count */
|
||||
int val; /* most recent output value */
|
||||
time_t time; /* clock (secs) when val computed */
|
||||
time64_t time; /* clock (secs) when val computed */
|
||||
spinlock_t lock; /* guards read or write of above */
|
||||
};
|
||||
|
||||
@@ -1374,7 +1375,7 @@ out:
|
||||
*/
|
||||
|
||||
#define FM_COEF 933 /* coefficient for half-life of 10 secs */
|
||||
#define FM_MAXTICKS ((time_t)99) /* useless computing more ticks than this */
|
||||
#define FM_MAXTICKS ((u32)99) /* useless computing more ticks than this */
|
||||
#define FM_MAXCNT 1000000 /* limit cnt to avoid overflow */
|
||||
#define FM_SCALE 1000 /* faux fixed point scale */
|
||||
|
||||
@@ -1390,8 +1391,11 @@ static void fmeter_init(struct fmeter *fmp)
|
||||
/* Internal meter update - process cnt events and update value */
|
||||
static void fmeter_update(struct fmeter *fmp)
|
||||
{
|
||||
time_t now = get_seconds();
|
||||
time_t ticks = now - fmp->time;
|
||||
time64_t now;
|
||||
u32 ticks;
|
||||
|
||||
now = ktime_get_seconds();
|
||||
ticks = now - fmp->time;
|
||||
|
||||
if (ticks == 0)
|
||||
return;
|
||||
|
||||
+3
-4
@@ -1250,7 +1250,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
||||
{
|
||||
int retval;
|
||||
struct task_struct *p;
|
||||
void *cgrp_ss_priv[CGROUP_CANFORK_COUNT] = {};
|
||||
|
||||
if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
|
||||
return ERR_PTR(-EINVAL);
|
||||
@@ -1527,7 +1526,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
||||
* between here and cgroup_post_fork() if an organisation operation is in
|
||||
* progress.
|
||||
*/
|
||||
retval = cgroup_can_fork(p, cgrp_ss_priv);
|
||||
retval = cgroup_can_fork(p);
|
||||
if (retval)
|
||||
goto bad_fork_free_pid;
|
||||
|
||||
@@ -1609,7 +1608,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
|
||||
proc_fork_connector(p);
|
||||
cgroup_post_fork(p, cgrp_ss_priv);
|
||||
cgroup_post_fork(p);
|
||||
threadgroup_change_end(current);
|
||||
perf_event_fork(p);
|
||||
|
||||
@@ -1619,7 +1618,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
||||
return p;
|
||||
|
||||
bad_fork_cancel_cgroup:
|
||||
cgroup_cancel_fork(p, cgrp_ss_priv);
|
||||
cgroup_cancel_fork(p);
|
||||
bad_fork_free_pid:
|
||||
if (pid != &init_struct_pid)
|
||||
free_pid(pid);
|
||||
|
||||
+1
-1
@@ -8342,7 +8342,7 @@ static void cpu_cgroup_css_offline(struct cgroup_subsys_state *css)
|
||||
sched_offline_group(tg);
|
||||
}
|
||||
|
||||
static void cpu_cgroup_fork(struct task_struct *task, void *private)
|
||||
static void cpu_cgroup_fork(struct task_struct *task)
|
||||
{
|
||||
sched_move_task(task);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user