diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-06-03 04:57:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-06-03 04:57:16 -0400 |
commit | 7d80fea4263d9a83ffedea448afa8510b05d04d0 (patch) | |
tree | 202118fd64ea1a661e3945e1a5bf13ef2d6f90eb /kernel | |
parent | 338e33acd820fa89b8a2d5b6574233784702f618 (diff) | |
parent | 2a0ff3fbe39bc93f719ff857e5a359d9780579ff (diff) |
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()
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cgroup.c | 31 |
1 files changed, 16 insertions, 15 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 2a9926275f80..a7c9e6ddb979 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1686,11 +1686,14 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, | |||
1686 | */ | 1686 | */ |
1687 | cgroup_drop_root(opts.new_root); | 1687 | cgroup_drop_root(opts.new_root); |
1688 | 1688 | ||
1689 | if (((root->flags | opts.flags) & CGRP_ROOT_SANE_BEHAVIOR) && | 1689 | if (root->flags != opts.flags) { |
1690 | root->flags != opts.flags) { | 1690 | if ((root->flags | opts.flags) & CGRP_ROOT_SANE_BEHAVIOR) { |
1691 | pr_err("cgroup: sane_behavior: new mount options should match the existing superblock\n"); | 1691 | pr_err("cgroup: sane_behavior: new mount options should match the existing superblock\n"); |
1692 | ret = -EINVAL; | 1692 | ret = -EINVAL; |
1693 | goto drop_new_super; | 1693 | goto drop_new_super; |
1694 | } else { | ||
1695 | pr_warning("cgroup: new mount options do not match the existing superblock, will be ignored\n"); | ||
1696 | } | ||
1694 | } | 1697 | } |
1695 | 1698 | ||
1696 | /* no subsys rebinding, so refcounts don't change */ | 1699 | /* 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 | goto out; | 2702 | goto out; |
2700 | } | 2703 | } |
2701 | 2704 | ||
2705 | cfe->type = (void *)cft; | ||
2706 | cfe->dentry = dentry; | ||
2707 | dentry->d_fsdata = cfe; | ||
2708 | simple_xattrs_init(&cfe->xattrs); | ||
2709 | |||
2702 | mode = cgroup_file_mode(cft); | 2710 | mode = cgroup_file_mode(cft); |
2703 | error = cgroup_create_file(dentry, mode | S_IFREG, cgrp->root->sb); | 2711 | error = cgroup_create_file(dentry, mode | S_IFREG, cgrp->root->sb); |
2704 | if (!error) { | 2712 | if (!error) { |
2705 | cfe->type = (void *)cft; | ||
2706 | cfe->dentry = dentry; | ||
2707 | dentry->d_fsdata = cfe; | ||
2708 | simple_xattrs_init(&cfe->xattrs); | ||
2709 | list_add_tail(&cfe->node, &parent->files); | 2713 | list_add_tail(&cfe->node, &parent->files); |
2710 | cfe = NULL; | 2714 | cfe = NULL; |
2711 | } | 2715 | } |
@@ -2953,11 +2957,8 @@ struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos, | |||
2953 | WARN_ON_ONCE(!rcu_read_lock_held()); | 2957 | WARN_ON_ONCE(!rcu_read_lock_held()); |
2954 | 2958 | ||
2955 | /* if first iteration, pretend we just visited @cgroup */ | 2959 | /* if first iteration, pretend we just visited @cgroup */ |
2956 | if (!pos) { | 2960 | if (!pos) |
2957 | if (list_empty(&cgroup->children)) | ||
2958 | return NULL; | ||
2959 | pos = cgroup; | 2961 | pos = cgroup; |
2960 | } | ||
2961 | 2962 | ||
2962 | /* visit the first child if exists */ | 2963 | /* visit the first child if exists */ |
2963 | next = list_first_or_null_rcu(&pos->children, struct cgroup, sibling); | 2964 | 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 | return next; | 2966 | return next; |
2966 | 2967 | ||
2967 | /* no child, visit my or the closest ancestor's next sibling */ | 2968 | /* no child, visit my or the closest ancestor's next sibling */ |
2968 | do { | 2969 | while (pos != cgroup) { |
2969 | next = list_entry_rcu(pos->sibling.next, struct cgroup, | 2970 | next = list_entry_rcu(pos->sibling.next, struct cgroup, |
2970 | sibling); | 2971 | sibling); |
2971 | if (&next->sibling != &pos->parent->children) | 2972 | if (&next->sibling != &pos->parent->children) |
2972 | return next; | 2973 | return next; |
2973 | 2974 | ||
2974 | pos = pos->parent; | 2975 | pos = pos->parent; |
2975 | } while (pos != cgroup); | 2976 | } |
2976 | 2977 | ||
2977 | return NULL; | 2978 | return NULL; |
2978 | } | 2979 | } |