|
|
|
|
@@ -1392,6 +1392,9 @@ static void cgroup_destroy_root(struct cgroup_root *root)
|
|
|
|
|
cgroup_free_root(root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returned cgroup is without refcount but it's valid as long as cset pins it.
|
|
|
|
|
*/
|
|
|
|
|
static inline struct cgroup *__cset_cgroup_from_root(struct css_set *cset,
|
|
|
|
|
struct cgroup_root *root)
|
|
|
|
|
{
|
|
|
|
|
@@ -1403,6 +1406,7 @@ static inline struct cgroup *__cset_cgroup_from_root(struct css_set *cset,
|
|
|
|
|
res_cgroup = cset->dfl_cgrp;
|
|
|
|
|
} else {
|
|
|
|
|
struct cgrp_cset_link *link;
|
|
|
|
|
lockdep_assert_held(&css_set_lock);
|
|
|
|
|
|
|
|
|
|
list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
|
|
|
|
|
struct cgroup *c = link->cgrp;
|
|
|
|
|
@@ -1414,6 +1418,7 @@ static inline struct cgroup *__cset_cgroup_from_root(struct css_set *cset,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BUG_ON(!res_cgroup);
|
|
|
|
|
return res_cgroup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1436,23 +1441,36 @@ current_cgns_cgroup_from_root(struct cgroup_root *root)
|
|
|
|
|
|
|
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
|
|
BUG_ON(!res);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Look up cgroup associated with current task's cgroup namespace on the default
|
|
|
|
|
* hierarchy.
|
|
|
|
|
*
|
|
|
|
|
* Unlike current_cgns_cgroup_from_root(), this doesn't need locks:
|
|
|
|
|
* - Internal rcu_read_lock is unnecessary because we don't dereference any rcu
|
|
|
|
|
* pointers.
|
|
|
|
|
* - css_set_lock is not needed because we just read cset->dfl_cgrp.
|
|
|
|
|
* - As a bonus returned cgrp is pinned with the current because it cannot
|
|
|
|
|
* switch cgroup_ns asynchronously.
|
|
|
|
|
*/
|
|
|
|
|
static struct cgroup *current_cgns_cgroup_dfl(void)
|
|
|
|
|
{
|
|
|
|
|
struct css_set *cset;
|
|
|
|
|
|
|
|
|
|
cset = current->nsproxy->cgroup_ns->root_cset;
|
|
|
|
|
return __cset_cgroup_from_root(cset, &cgrp_dfl_root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* look up cgroup associated with given css_set on the specified hierarchy */
|
|
|
|
|
static struct cgroup *cset_cgroup_from_root(struct css_set *cset,
|
|
|
|
|
struct cgroup_root *root)
|
|
|
|
|
{
|
|
|
|
|
struct cgroup *res = NULL;
|
|
|
|
|
|
|
|
|
|
lockdep_assert_held(&cgroup_mutex);
|
|
|
|
|
lockdep_assert_held(&css_set_lock);
|
|
|
|
|
|
|
|
|
|
res = __cset_cgroup_from_root(cset, root);
|
|
|
|
|
|
|
|
|
|
BUG_ON(!res);
|
|
|
|
|
return res;
|
|
|
|
|
return __cset_cgroup_from_root(cset, root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@@ -6191,9 +6209,7 @@ struct cgroup *cgroup_get_from_id(u64 id)
|
|
|
|
|
if (!cgrp)
|
|
|
|
|
return ERR_PTR(-ENOENT);
|
|
|
|
|
|
|
|
|
|
spin_lock_irq(&css_set_lock);
|
|
|
|
|
root_cgrp = current_cgns_cgroup_from_root(&cgrp_dfl_root);
|
|
|
|
|
spin_unlock_irq(&css_set_lock);
|
|
|
|
|
root_cgrp = current_cgns_cgroup_dfl();
|
|
|
|
|
if (!cgroup_is_descendant(cgrp, root_cgrp)) {
|
|
|
|
|
cgroup_put(cgrp);
|
|
|
|
|
return ERR_PTR(-ENOENT);
|
|
|
|
|
@@ -6294,16 +6310,42 @@ void cgroup_fork(struct task_struct *child)
|
|
|
|
|
INIT_LIST_HEAD(&child->cg_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct cgroup *cgroup_get_from_file(struct file *f)
|
|
|
|
|
/**
|
|
|
|
|
* cgroup_v1v2_get_from_file - get a cgroup pointer from a file pointer
|
|
|
|
|
* @f: file corresponding to cgroup_dir
|
|
|
|
|
*
|
|
|
|
|
* Find the cgroup from a file pointer associated with a cgroup directory.
|
|
|
|
|
* Returns a pointer to the cgroup on success. ERR_PTR is returned if the
|
|
|
|
|
* cgroup cannot be found.
|
|
|
|
|
*/
|
|
|
|
|
static struct cgroup *cgroup_v1v2_get_from_file(struct file *f)
|
|
|
|
|
{
|
|
|
|
|
struct cgroup_subsys_state *css;
|
|
|
|
|
struct cgroup *cgrp;
|
|
|
|
|
|
|
|
|
|
css = css_tryget_online_from_dir(f->f_path.dentry, NULL);
|
|
|
|
|
if (IS_ERR(css))
|
|
|
|
|
return ERR_CAST(css);
|
|
|
|
|
|
|
|
|
|
cgrp = css->cgroup;
|
|
|
|
|
return css->cgroup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* cgroup_get_from_file - same as cgroup_v1v2_get_from_file, but only supports
|
|
|
|
|
* cgroup2.
|
|
|
|
|
* @f: file corresponding to cgroup2_dir
|
|
|
|
|
*/
|
|
|
|
|
static struct cgroup *cgroup_get_from_file(struct file *f)
|
|
|
|
|
{
|
|
|
|
|
struct cgroup *cgrp = cgroup_v1v2_get_from_file(f);
|
|
|
|
|
|
|
|
|
|
if (IS_ERR(cgrp))
|
|
|
|
|
return ERR_CAST(cgrp);
|
|
|
|
|
|
|
|
|
|
if (!cgroup_on_dfl(cgrp)) {
|
|
|
|
|
cgroup_put(cgrp);
|
|
|
|
|
return ERR_PTR(-EBADF);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cgrp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -6772,10 +6814,8 @@ struct cgroup *cgroup_get_from_path(const char *path)
|
|
|
|
|
struct cgroup *cgrp = ERR_PTR(-ENOENT);
|
|
|
|
|
struct cgroup *root_cgrp;
|
|
|
|
|
|
|
|
|
|
spin_lock_irq(&css_set_lock);
|
|
|
|
|
root_cgrp = current_cgns_cgroup_from_root(&cgrp_dfl_root);
|
|
|
|
|
root_cgrp = current_cgns_cgroup_dfl();
|
|
|
|
|
kn = kernfs_walk_and_get(root_cgrp->kn, path);
|
|
|
|
|
spin_unlock_irq(&css_set_lock);
|
|
|
|
|
if (!kn)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
@@ -6800,15 +6840,15 @@ out:
|
|
|
|
|
EXPORT_SYMBOL_GPL(cgroup_get_from_path);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* cgroup_get_from_fd - get a cgroup pointer from a fd
|
|
|
|
|
* @fd: fd obtained by open(cgroup2_dir)
|
|
|
|
|
* cgroup_v1v2_get_from_fd - get a cgroup pointer from a fd
|
|
|
|
|
* @fd: fd obtained by open(cgroup_dir)
|
|
|
|
|
*
|
|
|
|
|
* Find the cgroup from a fd which should be obtained
|
|
|
|
|
* by opening a cgroup directory. Returns a pointer to the
|
|
|
|
|
* cgroup on success. ERR_PTR is returned if the cgroup
|
|
|
|
|
* cannot be found.
|
|
|
|
|
*/
|
|
|
|
|
struct cgroup *cgroup_get_from_fd(int fd)
|
|
|
|
|
struct cgroup *cgroup_v1v2_get_from_fd(int fd)
|
|
|
|
|
{
|
|
|
|
|
struct cgroup *cgrp;
|
|
|
|
|
struct file *f;
|
|
|
|
|
@@ -6817,10 +6857,29 @@ struct cgroup *cgroup_get_from_fd(int fd)
|
|
|
|
|
if (!f)
|
|
|
|
|
return ERR_PTR(-EBADF);
|
|
|
|
|
|
|
|
|
|
cgrp = cgroup_get_from_file(f);
|
|
|
|
|
cgrp = cgroup_v1v2_get_from_file(f);
|
|
|
|
|
fput(f);
|
|
|
|
|
return cgrp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* cgroup_get_from_fd - same as cgroup_v1v2_get_from_fd, but only supports
|
|
|
|
|
* cgroup2.
|
|
|
|
|
* @fd: fd obtained by open(cgroup2_dir)
|
|
|
|
|
*/
|
|
|
|
|
struct cgroup *cgroup_get_from_fd(int fd)
|
|
|
|
|
{
|
|
|
|
|
struct cgroup *cgrp = cgroup_v1v2_get_from_fd(fd);
|
|
|
|
|
|
|
|
|
|
if (IS_ERR(cgrp))
|
|
|
|
|
return ERR_CAST(cgrp);
|
|
|
|
|
|
|
|
|
|
if (!cgroup_on_dfl(cgrp)) {
|
|
|
|
|
cgroup_put(cgrp);
|
|
|
|
|
return ERR_PTR(-EBADF);
|
|
|
|
|
}
|
|
|
|
|
return cgrp;
|
|
|
|
|
}
|
|
|
|
|
EXPORT_SYMBOL_GPL(cgroup_get_from_fd);
|
|
|
|
|
|
|
|
|
|
static u64 power_of_ten(int power)
|
|
|
|
|
|