cgroup: Fix an RCU warning in cgroup_path()

with CONFIG_PROVE_RCU=y, a warning can be triggered:

  # mount -t cgroup -o debug xxx /mnt
  # cat /proc/$$/cgroup

...
kernel/cgroup.c:1649 invoked rcu_dereference_check() without protection!
...

This is a false-positive, because cgroup_path() can be called
with either rcu_read_lock() held or cgroup_mutex held.

Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
This commit is contained in:
Li Zefan 2010-04-22 17:29:24 +08:00 committed by Paul E. McKenney
parent e35ec2d2c1
commit 9a9686b634

View File

@ -1646,7 +1646,9 @@ static inline struct cftype *__d_cft(struct dentry *dentry)
int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen) int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
{ {
char *start; char *start;
struct dentry *dentry = rcu_dereference(cgrp->dentry); struct dentry *dentry = rcu_dereference_check(cgrp->dentry,
rcu_read_lock_held() ||
cgroup_lock_is_held());
if (!dentry || cgrp == dummytop) { if (!dentry || cgrp == dummytop) {
/* /*
@ -1662,13 +1664,17 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
*--start = '\0'; *--start = '\0';
for (;;) { for (;;) {
int len = dentry->d_name.len; int len = dentry->d_name.len;
if ((start -= len) < buf) if ((start -= len) < buf)
return -ENAMETOOLONG; return -ENAMETOOLONG;
memcpy(start, cgrp->dentry->d_name.name, len); memcpy(start, dentry->d_name.name, len);
cgrp = cgrp->parent; cgrp = cgrp->parent;
if (!cgrp) if (!cgrp)
break; break;
dentry = rcu_dereference(cgrp->dentry);
dentry = rcu_dereference_check(cgrp->dentry,
rcu_read_lock_held() ||
cgroup_lock_is_held());
if (!cgrp->parent) if (!cgrp->parent)
continue; continue;
if (--start < buf) if (--start < buf)