Skip to content

Commit bb1a114

Browse files
committed
Merge tag 'cgroup-for-6.1-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup fixes from Tejun Heo: - Fix a recent regression where a sleeping kernfs function is called with css_set_lock (spinlock) held - Revert the commit to enable cgroup1 support for cgroup_get_from_fd/file() Multiple users assume that the lookup only works for cgroup2 and breaks when fed a cgroup1 file. Instead, introduce a separate set of functions to lookup both v1 and v2 and use them where the user explicitly wants to support both versions. - Compat update for tools/perf/util/bpf_skel/bperf_cgroup.bpf.c. - Add Josef Bacik as a blkcg maintainer. * tag 'cgroup-for-6.1-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: blkcg: Update MAINTAINERS entry mm: cgroup: fix comments for get from fd/file helpers perf stat: Support old kernels for bperf cgroup counting bpf: cgroup_iter: support cgroup1 using cgroup fd cgroup: add cgroup_v1v2_get_from_[fd/file]() Revert "cgroup: enable cgroup_get_from_file() on cgroup1" cgroup: Reorganize css_set_lock and kernfs path processing
2 parents bbb8ceb + 79a818b commit bb1a114

File tree

4 files changed

+83
-21
lines changed

4 files changed

+83
-21
lines changed

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5266,13 +5266,15 @@ F: tools/testing/selftests/cgroup/
52665266

52675267
CONTROL GROUP - BLOCK IO CONTROLLER (BLKIO)
52685268
M: Tejun Heo <[email protected]>
5269+
M: Josef Bacik <[email protected]>
52695270
M: Jens Axboe <[email protected]>
52705271
52715272
52725273
T: git git://git.kernel.dk/linux-block
52735274
F: Documentation/admin-guide/cgroup-v1/blkio-controller.rst
52745275
F: block/bfq-cgroup.c
52755276
F: block/blk-cgroup.c
5277+
F: block/blk-iocost.c
52765278
F: block/blk-iolatency.c
52775279
F: block/blk-throttle.c
52785280
F: include/linux/blk-cgroup.h

include/linux/cgroup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry,
106106

107107
struct cgroup *cgroup_get_from_path(const char *path);
108108
struct cgroup *cgroup_get_from_fd(int fd);
109+
struct cgroup *cgroup_v1v2_get_from_fd(int fd);
109110

110111
int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
111112
int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);

kernel/bpf/cgroup_iter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ static int bpf_iter_attach_cgroup(struct bpf_prog *prog,
196196
return -EINVAL;
197197

198198
if (fd)
199-
cgrp = cgroup_get_from_fd(fd);
199+
cgrp = cgroup_v1v2_get_from_fd(fd);
200200
else if (id)
201201
cgrp = cgroup_get_from_id(id);
202202
else /* walk the entire hierarchy by default. */

kernel/cgroup/cgroup.c

Lines changed: 79 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,9 @@ static void cgroup_destroy_root(struct cgroup_root *root)
13921392
cgroup_free_root(root);
13931393
}
13941394

1395+
/*
1396+
* Returned cgroup is without refcount but it's valid as long as cset pins it.
1397+
*/
13951398
static inline struct cgroup *__cset_cgroup_from_root(struct css_set *cset,
13961399
struct cgroup_root *root)
13971400
{
@@ -1403,6 +1406,7 @@ static inline struct cgroup *__cset_cgroup_from_root(struct css_set *cset,
14031406
res_cgroup = cset->dfl_cgrp;
14041407
} else {
14051408
struct cgrp_cset_link *link;
1409+
lockdep_assert_held(&css_set_lock);
14061410

14071411
list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
14081412
struct cgroup *c = link->cgrp;
@@ -1414,6 +1418,7 @@ static inline struct cgroup *__cset_cgroup_from_root(struct css_set *cset,
14141418
}
14151419
}
14161420

1421+
BUG_ON(!res_cgroup);
14171422
return res_cgroup;
14181423
}
14191424

@@ -1436,23 +1441,36 @@ current_cgns_cgroup_from_root(struct cgroup_root *root)
14361441

14371442
rcu_read_unlock();
14381443

1439-
BUG_ON(!res);
14401444
return res;
14411445
}
14421446

1447+
/*
1448+
* Look up cgroup associated with current task's cgroup namespace on the default
1449+
* hierarchy.
1450+
*
1451+
* Unlike current_cgns_cgroup_from_root(), this doesn't need locks:
1452+
* - Internal rcu_read_lock is unnecessary because we don't dereference any rcu
1453+
* pointers.
1454+
* - css_set_lock is not needed because we just read cset->dfl_cgrp.
1455+
* - As a bonus returned cgrp is pinned with the current because it cannot
1456+
* switch cgroup_ns asynchronously.
1457+
*/
1458+
static struct cgroup *current_cgns_cgroup_dfl(void)
1459+
{
1460+
struct css_set *cset;
1461+
1462+
cset = current->nsproxy->cgroup_ns->root_cset;
1463+
return __cset_cgroup_from_root(cset, &cgrp_dfl_root);
1464+
}
1465+
14431466
/* look up cgroup associated with given css_set on the specified hierarchy */
14441467
static struct cgroup *cset_cgroup_from_root(struct css_set *cset,
14451468
struct cgroup_root *root)
14461469
{
1447-
struct cgroup *res = NULL;
1448-
14491470
lockdep_assert_held(&cgroup_mutex);
14501471
lockdep_assert_held(&css_set_lock);
14511472

1452-
res = __cset_cgroup_from_root(cset, root);
1453-
1454-
BUG_ON(!res);
1455-
return res;
1473+
return __cset_cgroup_from_root(cset, root);
14561474
}
14571475

14581476
/*
@@ -6191,9 +6209,7 @@ struct cgroup *cgroup_get_from_id(u64 id)
61916209
if (!cgrp)
61926210
return ERR_PTR(-ENOENT);
61936211

6194-
spin_lock_irq(&css_set_lock);
6195-
root_cgrp = current_cgns_cgroup_from_root(&cgrp_dfl_root);
6196-
spin_unlock_irq(&css_set_lock);
6212+
root_cgrp = current_cgns_cgroup_dfl();
61976213
if (!cgroup_is_descendant(cgrp, root_cgrp)) {
61986214
cgroup_put(cgrp);
61996215
return ERR_PTR(-ENOENT);
@@ -6294,16 +6310,42 @@ void cgroup_fork(struct task_struct *child)
62946310
INIT_LIST_HEAD(&child->cg_list);
62956311
}
62966312

6297-
static struct cgroup *cgroup_get_from_file(struct file *f)
6313+
/**
6314+
* cgroup_v1v2_get_from_file - get a cgroup pointer from a file pointer
6315+
* @f: file corresponding to cgroup_dir
6316+
*
6317+
* Find the cgroup from a file pointer associated with a cgroup directory.
6318+
* Returns a pointer to the cgroup on success. ERR_PTR is returned if the
6319+
* cgroup cannot be found.
6320+
*/
6321+
static struct cgroup *cgroup_v1v2_get_from_file(struct file *f)
62986322
{
62996323
struct cgroup_subsys_state *css;
6300-
struct cgroup *cgrp;
63016324

63026325
css = css_tryget_online_from_dir(f->f_path.dentry, NULL);
63036326
if (IS_ERR(css))
63046327
return ERR_CAST(css);
63056328

6306-
cgrp = css->cgroup;
6329+
return css->cgroup;
6330+
}
6331+
6332+
/**
6333+
* cgroup_get_from_file - same as cgroup_v1v2_get_from_file, but only supports
6334+
* cgroup2.
6335+
* @f: file corresponding to cgroup2_dir
6336+
*/
6337+
static struct cgroup *cgroup_get_from_file(struct file *f)
6338+
{
6339+
struct cgroup *cgrp = cgroup_v1v2_get_from_file(f);
6340+
6341+
if (IS_ERR(cgrp))
6342+
return ERR_CAST(cgrp);
6343+
6344+
if (!cgroup_on_dfl(cgrp)) {
6345+
cgroup_put(cgrp);
6346+
return ERR_PTR(-EBADF);
6347+
}
6348+
63076349
return cgrp;
63086350
}
63096351

@@ -6772,10 +6814,8 @@ struct cgroup *cgroup_get_from_path(const char *path)
67726814
struct cgroup *cgrp = ERR_PTR(-ENOENT);
67736815
struct cgroup *root_cgrp;
67746816

6775-
spin_lock_irq(&css_set_lock);
6776-
root_cgrp = current_cgns_cgroup_from_root(&cgrp_dfl_root);
6817+
root_cgrp = current_cgns_cgroup_dfl();
67776818
kn = kernfs_walk_and_get(root_cgrp->kn, path);
6778-
spin_unlock_irq(&css_set_lock);
67796819
if (!kn)
67806820
goto out;
67816821

@@ -6800,15 +6840,15 @@ struct cgroup *cgroup_get_from_path(const char *path)
68006840
EXPORT_SYMBOL_GPL(cgroup_get_from_path);
68016841

68026842
/**
6803-
* cgroup_get_from_fd - get a cgroup pointer from a fd
6804-
* @fd: fd obtained by open(cgroup2_dir)
6843+
* cgroup_v1v2_get_from_fd - get a cgroup pointer from a fd
6844+
* @fd: fd obtained by open(cgroup_dir)
68056845
*
68066846
* Find the cgroup from a fd which should be obtained
68076847
* by opening a cgroup directory. Returns a pointer to the
68086848
* cgroup on success. ERR_PTR is returned if the cgroup
68096849
* cannot be found.
68106850
*/
6811-
struct cgroup *cgroup_get_from_fd(int fd)
6851+
struct cgroup *cgroup_v1v2_get_from_fd(int fd)
68126852
{
68136853
struct cgroup *cgrp;
68146854
struct file *f;
@@ -6817,10 +6857,29 @@ struct cgroup *cgroup_get_from_fd(int fd)
68176857
if (!f)
68186858
return ERR_PTR(-EBADF);
68196859

6820-
cgrp = cgroup_get_from_file(f);
6860+
cgrp = cgroup_v1v2_get_from_file(f);
68216861
fput(f);
68226862
return cgrp;
68236863
}
6864+
6865+
/**
6866+
* cgroup_get_from_fd - same as cgroup_v1v2_get_from_fd, but only supports
6867+
* cgroup2.
6868+
* @fd: fd obtained by open(cgroup2_dir)
6869+
*/
6870+
struct cgroup *cgroup_get_from_fd(int fd)
6871+
{
6872+
struct cgroup *cgrp = cgroup_v1v2_get_from_fd(fd);
6873+
6874+
if (IS_ERR(cgrp))
6875+
return ERR_CAST(cgrp);
6876+
6877+
if (!cgroup_on_dfl(cgrp)) {
6878+
cgroup_put(cgrp);
6879+
return ERR_PTR(-EBADF);
6880+
}
6881+
return cgrp;
6882+
}
68246883
EXPORT_SYMBOL_GPL(cgroup_get_from_fd);
68256884

68266885
static u64 power_of_ten(int power)

0 commit comments

Comments
 (0)