Commit 7d80fea4 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-3.10-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup

Pull cgroup fixes from Tejun Heo:

 - Fix for yet another xattr bug which may lead to NULL deref.

 - A subtle bug in for_each_descendant_pre().  This bug requires quite
   specific conditions to trigger and isn't too likely to actually
   happen in the wild, but maybe that just makes it that much more
   nastier.

 - A warning message added for silly cgroup re-mount (not -o remount,
   but unmount followed by mount) behavior.

* 'for-3.10-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
  cgroup: warn about mismatching options of a new mount of an existing hierarchy
  cgroup: fix a subtle bug in descendant pre-order walk
  cgroup: initialize xattr before calling d_instantiate()
parents 338e33ac 2a0ff3fb
...@@ -707,7 +707,7 @@ struct cgroup *cgroup_rightmost_descendant(struct cgroup *pos); ...@@ -707,7 +707,7 @@ struct cgroup *cgroup_rightmost_descendant(struct cgroup *pos);
* *
* If a subsystem synchronizes against the parent in its ->css_online() and * If a subsystem synchronizes against the parent in its ->css_online() and
* before starting iterating, and synchronizes against @pos on each * before starting iterating, and synchronizes against @pos on each
* iteration, any descendant cgroup which finished ->css_offline() is * iteration, any descendant cgroup which finished ->css_online() is
* guaranteed to be visible in the future iterations. * guaranteed to be visible in the future iterations.
* *
* In other words, the following guarantees that a descendant can't escape * In other words, the following guarantees that a descendant can't escape
......
...@@ -1686,11 +1686,14 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, ...@@ -1686,11 +1686,14 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
*/ */
cgroup_drop_root(opts.new_root); cgroup_drop_root(opts.new_root);
if (((root->flags | opts.flags) & CGRP_ROOT_SANE_BEHAVIOR) && if (root->flags != opts.flags) {
root->flags != opts.flags) { if ((root->flags | opts.flags) & CGRP_ROOT_SANE_BEHAVIOR) {
pr_err("cgroup: sane_behavior: new mount options should match the existing superblock\n"); pr_err("cgroup: sane_behavior: new mount options should match the existing superblock\n");
ret = -EINVAL; ret = -EINVAL;
goto drop_new_super; goto drop_new_super;
} else {
pr_warning("cgroup: new mount options do not match the existing superblock, will be ignored\n");
}
} }
/* no subsys rebinding, so refcounts don't change */ /* no subsys rebinding, so refcounts don't change */
...@@ -2699,13 +2702,14 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys, ...@@ -2699,13 +2702,14 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
goto out; goto out;
} }
mode = cgroup_file_mode(cft);
error = cgroup_create_file(dentry, mode | S_IFREG, cgrp->root->sb);
if (!error) {
cfe->type = (void *)cft; cfe->type = (void *)cft;
cfe->dentry = dentry; cfe->dentry = dentry;
dentry->d_fsdata = cfe; dentry->d_fsdata = cfe;
simple_xattrs_init(&cfe->xattrs); simple_xattrs_init(&cfe->xattrs);
mode = cgroup_file_mode(cft);
error = cgroup_create_file(dentry, mode | S_IFREG, cgrp->root->sb);
if (!error) {
list_add_tail(&cfe->node, &parent->files); list_add_tail(&cfe->node, &parent->files);
cfe = NULL; cfe = NULL;
} }
...@@ -2953,11 +2957,8 @@ struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos, ...@@ -2953,11 +2957,8 @@ struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos,
WARN_ON_ONCE(!rcu_read_lock_held()); WARN_ON_ONCE(!rcu_read_lock_held());
/* if first iteration, pretend we just visited @cgroup */ /* if first iteration, pretend we just visited @cgroup */
if (!pos) { if (!pos)
if (list_empty(&cgroup->children))
return NULL;
pos = cgroup; pos = cgroup;
}
/* visit the first child if exists */ /* visit the first child if exists */
next = list_first_or_null_rcu(&pos->children, struct cgroup, sibling); next = list_first_or_null_rcu(&pos->children, struct cgroup, sibling);
...@@ -2965,14 +2966,14 @@ struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos, ...@@ -2965,14 +2966,14 @@ struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos,
return next; return next;
/* no child, visit my or the closest ancestor's next sibling */ /* no child, visit my or the closest ancestor's next sibling */
do { while (pos != cgroup) {
next = list_entry_rcu(pos->sibling.next, struct cgroup, next = list_entry_rcu(pos->sibling.next, struct cgroup,
sibling); sibling);
if (&next->sibling != &pos->parent->children) if (&next->sibling != &pos->parent->children)
return next; return next;
pos = pos->parent; pos = pos->parent;
} while (pos != cgroup); }
return NULL; return NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment