Skip to content

Commit 0083d27

Browse files
committed
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 <[email protected]>
1 parent a8c52eb commit 0083d27

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

include/linux/cgroup-defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ enum {
131131
/* internal flags, do not use outside cgroup core proper */
132132
__CFTYPE_ONLY_ON_DFL = (1 << 16), /* only on default hierarchy */
133133
__CFTYPE_NOT_ON_DFL = (1 << 17), /* not on default hierarchy */
134+
__CFTYPE_ADDED = (1 << 18),
134135
};
135136

136137
/*

kernel/cgroup/cgroup.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4198,19 +4198,26 @@ static void cgroup_exit_cftypes(struct cftype *cfts)
41984198
cft->ss = NULL;
41994199

42004200
/* revert flags set by cgroup core while adding @cfts */
4201-
cft->flags &= ~(__CFTYPE_ONLY_ON_DFL | __CFTYPE_NOT_ON_DFL);
4201+
cft->flags &= ~(__CFTYPE_ONLY_ON_DFL | __CFTYPE_NOT_ON_DFL |
4202+
__CFTYPE_ADDED);
42024203
}
42034204
}
42044205

42054206
static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
42064207
{
42074208
struct cftype *cft;
4209+
int ret = 0;
42084210

42094211
for (cft = cfts; cft->name[0] != '\0'; cft++) {
42104212
struct kernfs_ops *kf_ops;
42114213

42124214
WARN_ON(cft->ss || cft->kf_ops);
42134215

4216+
if (cft->flags & __CFTYPE_ADDED) {
4217+
ret = -EBUSY;
4218+
break;
4219+
}
4220+
42144221
if ((cft->flags & CFTYPE_PRESSURE) && !cgroup_psi_enabled())
42154222
continue;
42164223

@@ -4226,26 +4233,26 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
42264233
if (cft->max_write_len && cft->max_write_len != PAGE_SIZE) {
42274234
kf_ops = kmemdup(kf_ops, sizeof(*kf_ops), GFP_KERNEL);
42284235
if (!kf_ops) {
4229-
cgroup_exit_cftypes(cfts);
4230-
return -ENOMEM;
4236+
ret = -ENOMEM;
4237+
break;
42314238
}
42324239
kf_ops->atomic_write_len = cft->max_write_len;
42334240
}
42344241

42354242
cft->kf_ops = kf_ops;
42364243
cft->ss = ss;
4244+
cft->flags |= __CFTYPE_ADDED;
42374245
}
42384246

4239-
return 0;
4247+
if (ret)
4248+
cgroup_exit_cftypes(cfts);
4249+
return ret;
42404250
}
42414251

42424252
static int cgroup_rm_cftypes_locked(struct cftype *cfts)
42434253
{
42444254
lockdep_assert_held(&cgroup_mutex);
42454255

4246-
if (!cfts || !cfts[0].ss)
4247-
return -ENOENT;
4248-
42494256
list_del(&cfts->node);
42504257
cgroup_apply_cftypes(cfts, false);
42514258
cgroup_exit_cftypes(cfts);
@@ -4267,6 +4274,12 @@ int cgroup_rm_cftypes(struct cftype *cfts)
42674274
{
42684275
int ret;
42694276

4277+
if (!cfts || cfts[0].name[0] == '\0')
4278+
return 0;
4279+
4280+
if (!(cfts[0].flags & __CFTYPE_ADDED))
4281+
return -ENOENT;
4282+
42704283
mutex_lock(&cgroup_mutex);
42714284
ret = cgroup_rm_cftypes_locked(cfts);
42724285
mutex_unlock(&cgroup_mutex);

0 commit comments

Comments
 (0)