devcg: use css_online and css_offline

Allocate resources and change behavior only when online. This is needed in
order to determine if a node is suitable for hierarchy propagation or if it's
being removed.

Locking:
Both functions take devcgroup_mutex to make changes to device_cgroup structure.
Hierarchy propagation will also take devcgroup_mutex before walking the
tree while walking the tree itself is protected by rcu lock.

Acked-by: Tejun Heo <tj@kernel.org>
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Aristeu Rozanski <aris@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Aristeu Rozanski 2013-02-15 11:55:46 -05:00 committed by Tejun Heo
parent c39a2a3018
commit 1909554c97

View file

@ -185,36 +185,59 @@ static void dev_exception_clean(struct dev_cgroup *dev_cgroup)
__dev_exception_clean(dev_cgroup); __dev_exception_clean(dev_cgroup);
} }
/**
* devcgroup_online - initializes devcgroup's behavior and exceptions based on
* parent's
* @cgroup: cgroup getting online
* returns 0 in case of success, error code otherwise
*/
static int devcgroup_online(struct cgroup *cgroup)
{
struct dev_cgroup *dev_cgroup, *parent_dev_cgroup = NULL;
int ret = 0;
mutex_lock(&devcgroup_mutex);
dev_cgroup = cgroup_to_devcgroup(cgroup);
if (cgroup->parent)
parent_dev_cgroup = cgroup_to_devcgroup(cgroup->parent);
if (parent_dev_cgroup == NULL)
dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;
else {
ret = dev_exceptions_copy(&dev_cgroup->exceptions,
&parent_dev_cgroup->exceptions);
if (!ret)
dev_cgroup->behavior = parent_dev_cgroup->behavior;
}
mutex_unlock(&devcgroup_mutex);
return ret;
}
static void devcgroup_offline(struct cgroup *cgroup)
{
struct dev_cgroup *dev_cgroup = cgroup_to_devcgroup(cgroup);
mutex_lock(&devcgroup_mutex);
dev_cgroup->behavior = DEVCG_DEFAULT_NONE;
mutex_unlock(&devcgroup_mutex);
}
/* /*
* called from kernel/cgroup.c with cgroup_lock() held. * called from kernel/cgroup.c with cgroup_lock() held.
*/ */
static struct cgroup_subsys_state *devcgroup_css_alloc(struct cgroup *cgroup) static struct cgroup_subsys_state *devcgroup_css_alloc(struct cgroup *cgroup)
{ {
struct dev_cgroup *dev_cgroup, *parent_dev_cgroup; struct dev_cgroup *dev_cgroup;
struct cgroup *parent_cgroup; struct cgroup *parent_cgroup;
int ret;
dev_cgroup = kzalloc(sizeof(*dev_cgroup), GFP_KERNEL); dev_cgroup = kzalloc(sizeof(*dev_cgroup), GFP_KERNEL);
if (!dev_cgroup) if (!dev_cgroup)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&dev_cgroup->exceptions); INIT_LIST_HEAD(&dev_cgroup->exceptions);
dev_cgroup->behavior = DEVCG_DEFAULT_NONE;
parent_cgroup = cgroup->parent; parent_cgroup = cgroup->parent;
if (parent_cgroup == NULL)
dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;
else {
parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
mutex_lock(&devcgroup_mutex);
ret = dev_exceptions_copy(&dev_cgroup->exceptions,
&parent_dev_cgroup->exceptions);
dev_cgroup->behavior = parent_dev_cgroup->behavior;
mutex_unlock(&devcgroup_mutex);
if (ret) {
kfree(dev_cgroup);
return ERR_PTR(ret);
}
}
return &dev_cgroup->css; return &dev_cgroup->css;
} }
@ -587,6 +610,8 @@ struct cgroup_subsys devices_subsys = {
.can_attach = devcgroup_can_attach, .can_attach = devcgroup_can_attach,
.css_alloc = devcgroup_css_alloc, .css_alloc = devcgroup_css_alloc,
.css_free = devcgroup_css_free, .css_free = devcgroup_css_free,
.css_online = devcgroup_online,
.css_offline = devcgroup_offline,
.subsys_id = devices_subsys_id, .subsys_id = devices_subsys_id,
.base_cftypes = dev_cgroup_files, .base_cftypes = dev_cgroup_files,