cgroup: Improve cftype add/rm error handling
Let's track whether a cftype is currently added or not using a new flag __CFTYPE_ADDED so that duplicate operations can be failed safely and consistently allow using empty cftypes. Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Родитель
a8c52eba88
Коммит
0083d27b21
|
@ -131,6 +131,7 @@ enum {
|
|||
/* internal flags, do not use outside cgroup core proper */
|
||||
__CFTYPE_ONLY_ON_DFL = (1 << 16), /* only on default hierarchy */
|
||||
__CFTYPE_NOT_ON_DFL = (1 << 17), /* not on default hierarchy */
|
||||
__CFTYPE_ADDED = (1 << 18),
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -4198,19 +4198,26 @@ static void cgroup_exit_cftypes(struct cftype *cfts)
|
|||
cft->ss = NULL;
|
||||
|
||||
/* revert flags set by cgroup core while adding @cfts */
|
||||
cft->flags &= ~(__CFTYPE_ONLY_ON_DFL | __CFTYPE_NOT_ON_DFL);
|
||||
cft->flags &= ~(__CFTYPE_ONLY_ON_DFL | __CFTYPE_NOT_ON_DFL |
|
||||
__CFTYPE_ADDED);
|
||||
}
|
||||
}
|
||||
|
||||
static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
|
||||
{
|
||||
struct cftype *cft;
|
||||
int ret = 0;
|
||||
|
||||
for (cft = cfts; cft->name[0] != '\0'; cft++) {
|
||||
struct kernfs_ops *kf_ops;
|
||||
|
||||
WARN_ON(cft->ss || cft->kf_ops);
|
||||
|
||||
if (cft->flags & __CFTYPE_ADDED) {
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((cft->flags & CFTYPE_PRESSURE) && !cgroup_psi_enabled())
|
||||
continue;
|
||||
|
||||
|
@ -4226,26 +4233,26 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
|
|||
if (cft->max_write_len && cft->max_write_len != PAGE_SIZE) {
|
||||
kf_ops = kmemdup(kf_ops, sizeof(*kf_ops), GFP_KERNEL);
|
||||
if (!kf_ops) {
|
||||
cgroup_exit_cftypes(cfts);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
kf_ops->atomic_write_len = cft->max_write_len;
|
||||
}
|
||||
|
||||
cft->kf_ops = kf_ops;
|
||||
cft->ss = ss;
|
||||
cft->flags |= __CFTYPE_ADDED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (ret)
|
||||
cgroup_exit_cftypes(cfts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cgroup_rm_cftypes_locked(struct cftype *cfts)
|
||||
{
|
||||
lockdep_assert_held(&cgroup_mutex);
|
||||
|
||||
if (!cfts || !cfts[0].ss)
|
||||
return -ENOENT;
|
||||
|
||||
list_del(&cfts->node);
|
||||
cgroup_apply_cftypes(cfts, false);
|
||||
cgroup_exit_cftypes(cfts);
|
||||
|
@ -4267,6 +4274,12 @@ int cgroup_rm_cftypes(struct cftype *cfts)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (!cfts || cfts[0].name[0] == '\0')
|
||||
return 0;
|
||||
|
||||
if (!(cfts[0].flags & __CFTYPE_ADDED))
|
||||
return -ENOENT;
|
||||
|
||||
mutex_lock(&cgroup_mutex);
|
||||
ret = cgroup_rm_cftypes_locked(cfts);
|
||||
mutex_unlock(&cgroup_mutex);
|
||||
|
|
Загрузка…
Ссылка в новой задаче