* [PATCH cgroup/for-3.11 1/2] cgroup: fix deadlock on cgroup_mutex via drop_parsed_module_refcounts()
@ 2013-06-28 2:39 Tejun Heo
[not found] ` <20130628023930.GA2500-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
0 siblings, 1 reply; 3+ messages in thread
From: Tejun Heo @ 2013-06-28 2:39 UTC (permalink / raw)
To: Li Zefan
Cc: cgroups-u79uwXL29TY76Z2rM5mHXA,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
From e2bd416f6246d11be29999c177d2534943a5c2df Mon Sep 17 00:00:00 2001
From: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Date: Thu, 27 Jun 2013 19:37:23 -0700
eb178d06332 ("cgroup: grab cgroup_mutex in
drop_parsed_module_refcounts()") made drop_parsed_module_refcounts()
grab cgroup_mutex to make lockdep assertion in for_each_subsys()
happy. Unfortunately, cgroup_remount() calls the function while
holding cgroup_mutex in its failure path leading to the following
deadlock.
# mount -t cgroup -o remount,memory,blkio cgroup blkio
cgroup: option changes via remount are deprecated (pid=525 comm=mount)
=============================================
[ INFO: possible recursive locking detected ]
3.10.0-rc4-work+ #1 Not tainted
---------------------------------------------
mount/525 is trying to acquire lock:
(cgroup_mutex){+.+.+.}, at: [<ffffffff8110a3e1>] drop_parsed_module_refcounts+0x21/0xb0
but task is already holding lock:
(cgroup_mutex){+.+.+.}, at: [<ffffffff8110e4e1>] cgroup_remount+0x51/0x200
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(cgroup_mutex);
lock(cgroup_mutex);
*** DEADLOCK ***
May be due to missing lock nesting notation
4 locks held by mount/525:
#0: (&type->s_umount_key#30){+.+...}, at: [<ffffffff811e9a0d>] do_mount+0x2bd/0xa30
#1: (&sb->s_type->i_mutex_key#9){+.+.+.}, at: [<ffffffff8110e4d3>] cgroup_remount+0x43/0x200
#2: (cgroup_mutex){+.+.+.}, at: [<ffffffff8110e4e1>] cgroup_remount+0x51/0x200
#3: (cgroup_root_mutex){+.+.+.}, at: [<ffffffff8110e4ef>] cgroup_remount+0x5f/0x200
stack backtrace:
CPU: 2 PID: 525 Comm: mount Not tainted 3.10.0-rc4-work+ #1
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
ffffffff829651f0 ffff88000ec2fc28 ffffffff81c24bb1 ffff88000ec2fce8
ffffffff810f420d 0000000000000006 0000000000000001 0000000000000056
ffff8800153b4640 ffff880000000000 ffffffff81c2e468 ffff8800153b4640
Call Trace:
[<ffffffff81c24bb1>] dump_stack+0x19/0x1b
[<ffffffff810f420d>] __lock_acquire+0x15dd/0x1e60
[<ffffffff810f531c>] lock_acquire+0x9c/0x1f0
[<ffffffff81c2a805>] mutex_lock_nested+0x65/0x410
[<ffffffff8110a3e1>] drop_parsed_module_refcounts+0x21/0xb0
[<ffffffff8110e63e>] cgroup_remount+0x1ae/0x200
[<ffffffff811c9bb2>] do_remount_sb+0x82/0x190
[<ffffffff811e9d41>] do_mount+0x5f1/0xa30
[<ffffffff811ea203>] SyS_mount+0x83/0xc0
[<ffffffff81c2fb82>] system_call_fastpath+0x16/0x1b
Fix it by moving the drop_parsed_module_refcounts() invocation outside
cgroup_mutex.
Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Two patches to fix regressions that I introduced lately. Given that
-rc1 is imminent, I applied them to for-3.11 directly so that they can
get exposure in -next ASAP.
Thanks!
kernel/cgroup.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 4ed8677..1b7b567 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1365,7 +1365,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
if (opts.flags != root->flags ||
(opts.name && strcmp(opts.name, root->name))) {
ret = -EINVAL;
- drop_parsed_module_refcounts(opts.subsys_mask);
goto out_unlock;
}
@@ -1380,7 +1379,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
if (ret) {
/* rebind_subsystems failed, re-populate the removed files */
cgroup_populate_dir(cgrp, false, removed_mask);
- drop_parsed_module_refcounts(opts.subsys_mask);
goto out_unlock;
}
@@ -1395,6 +1393,8 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
mutex_unlock(&cgroup_root_mutex);
mutex_unlock(&cgroup_mutex);
mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
+ if (ret)
+ drop_parsed_module_refcounts(opts.subsys_mask);
return ret;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH cgroup/for-3.11 2/2] cgroup: CGRP_ROOT_SUBSYS_BOUND should be ignored when comparing mount options
[not found] ` <20130628023930.GA2500-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
@ 2013-06-28 2:40 ` Tejun Heo
[not found] ` <20130628024003.GB2500-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
0 siblings, 1 reply; 3+ messages in thread
From: Tejun Heo @ 2013-06-28 2:40 UTC (permalink / raw)
To: Li Zefan
Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
cgroups-u79uwXL29TY76Z2rM5mHXA
From 0ce6cba35777cf96a54ce0d5856dc962566b8717 Mon Sep 17 00:00:00 2001
From: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Date: Thu, 27 Jun 2013 19:37:26 -0700
1672d04070 ("cgroup: fix cgroupfs_root early destruction path")
introduced CGRP_ROOT_SUBSYS_BOUND which is used to mark completion of
subsys binding on a new root; however, this broke remounts.
cgroup_remount() doesn't allow changing root options via remount and
CGRP_ROOT_SUBSYS_BOUND, which is set on all fully initialized roots,
makes the function reject all remounts.
Fix it by putting the options part in the lower 16 bits of root->flags
and masking the comparions. While at it, make cgroup_remount() emit
an error message explaining why it's rejecting a remount request, so
that it's less of a mystery.
Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
include/linux/cgroup.h | 6 +++++-
kernel/cgroup.c | 5 ++++-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index ad3555b..8db5397 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -276,7 +276,11 @@ enum {
CGRP_ROOT_NOPREFIX = (1 << 1), /* mounted subsystems have no named prefix */
CGRP_ROOT_XATTR = (1 << 2), /* supports extended attributes */
- CGRP_ROOT_SUBSYS_BOUND = (1 << 3), /* subsystems finished binding */
+
+ /* mount options live below bit 16 */
+ CGRP_ROOT_OPTION_MASK = (1 << 16) - 1,
+
+ CGRP_ROOT_SUBSYS_BOUND = (1 << 16), /* subsystems finished binding */
};
/*
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 1b7b567..5a2fcf5 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1362,8 +1362,11 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
removed_mask = root->subsys_mask & ~opts.subsys_mask;
/* Don't allow flags or name to change at remount */
- if (opts.flags != root->flags ||
+ if (((opts.flags ^ root->flags) & CGRP_ROOT_OPTION_MASK) ||
(opts.name && strcmp(opts.name, root->name))) {
+ pr_err("cgroup: option or name mismatch, new: 0x%lx \"%s\", old: 0x%lx \"%s\"\n",
+ opts.flags & CGRP_ROOT_OPTION_MASK, opts.name ?: "",
+ root->flags & CGRP_ROOT_OPTION_MASK, root->name);
ret = -EINVAL;
goto out_unlock;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH cgroup/for-3.11 3/2] cgroup: CGRP_ROOT_SUBSYS_BOUND should also be ignored when mounting an existing hierarchy
[not found] ` <20130628024003.GB2500-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
@ 2013-06-29 21:17 ` Tejun Heo
0 siblings, 0 replies; 3+ messages in thread
From: Tejun Heo @ 2013-06-29 21:17 UTC (permalink / raw)
To: Li Zefan
Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
cgroups-u79uwXL29TY76Z2rM5mHXA
From c7ba8287cd11f2fc9e2feee9e1fac34b7293658f Mon Sep 17 00:00:00 2001
From: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Date: Sat, 29 Jun 2013 14:06:10 -0700
0ce6cba357 ("cgroup: CGRP_ROOT_SUBSYS_BOUND should be ignored when
comparing mount options") only updated the remount path but
CGRP_ROOT_SUBSYS_BOUND should also be ignored when comparing options
while mounting an existing hierarchy. As option mismatch triggers a
warning but doesn't fail the mount without sane_behavior, this only
triggers a spurious warning message.
Fix it by only comparing CGRP_ROOT_OPTION_MASK bits when comparing new
and existing root options.
Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Oops, missed one. This one isn't critical but let's get it fixed too.
Thanks.
kernel/cgroup.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 5a2fcf5..e5583d1 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1703,7 +1703,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
*/
cgroup_free_root(opts.new_root);
- if (root->flags != opts.flags) {
+ if ((root->flags ^ opts.flags) & CGRP_ROOT_OPTION_MASK) {
if ((root->flags | opts.flags) & CGRP_ROOT_SANE_BEHAVIOR) {
pr_err("cgroup: sane_behavior: new mount options should match the existing superblock\n");
ret = -EINVAL;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2013-06-29 21:17 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-28 2:39 [PATCH cgroup/for-3.11 1/2] cgroup: fix deadlock on cgroup_mutex via drop_parsed_module_refcounts() Tejun Heo
[not found] ` <20130628023930.GA2500-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
2013-06-28 2:40 ` [PATCH cgroup/for-3.11 2/2] cgroup: CGRP_ROOT_SUBSYS_BOUND should be ignored when comparing mount options Tejun Heo
[not found] ` <20130628024003.GB2500-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
2013-06-29 21:17 ` [PATCH cgroup/for-3.11 3/2] cgroup: CGRP_ROOT_SUBSYS_BOUND should also be ignored when mounting an existing hierarchy Tejun Heo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).