diff options
author | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:37 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:37 -0500 |
commit | b8a2df6a5b576d04f78f54abf254c283527d8bbc (patch) | |
tree | 6a49e4105d3bb3d813378d72ebf67c08d719d0de /kernel/cgroup.c | |
parent | d19e19de48aa0b90c56cd93c8a46ebac46273429 (diff) |
cgroup: use mutex_trylock() when grabbing i_mutex of a new cgroup directory
All cgroup directory i_mutexes nest outside cgroup_mutex; however, new
directory creation is a special case. A new cgroup directory is
created while holding cgroup_mutex. Populating the new directory
requires both the new directory's i_mutex and cgroup_mutex. Because
all directory i_mutexes nest outside cgroup_mutex, grabbing both
requires releasing cgroup_mutex first, which isn't a good idea as the
new cgroup isn't yet ready to be manipulated by other cgroup
opreations.
This is worked around by grabbing the new directory's i_mutex while
holding cgroup_mutex before making it visible. As there's no other
user at that point, grabbing the i_mutex under cgroup_mutex can't lead
to deadlock.
cgroup_create_file() was using I_MUTEX_CHILD to tell lockdep not to
worry about the reverse locking order; however, this creates pseudo
locking dependency cgroup_mutex -> I_MUTEX_CHILD, which isn't true -
all directory i_mutexes are still nested outside cgroup_mutex. This
pseudo locking dependency can lead to spurious lockdep warnings.
Use mutex_trylock() instead. This will always succeed and lockdep
doesn't create any locking dependency for it.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 166b5141f3d4..c53f42e31704 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2657,9 +2657,15 @@ static int cgroup_create_file(struct dentry *dentry, umode_t mode, | |||
2657 | inc_nlink(inode); | 2657 | inc_nlink(inode); |
2658 | inc_nlink(dentry->d_parent->d_inode); | 2658 | inc_nlink(dentry->d_parent->d_inode); |
2659 | 2659 | ||
2660 | /* start with the directory inode held, so that we can | 2660 | /* |
2661 | * populate it without racing with another mkdir */ | 2661 | * Control reaches here with cgroup_mutex held. |
2662 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); | 2662 | * @inode->i_mutex should nest outside cgroup_mutex but we |
2663 | * want to populate it immediately without releasing | ||
2664 | * cgroup_mutex. As @inode isn't visible to anyone else | ||
2665 | * yet, trylock will always succeed without affecting | ||
2666 | * lockdep checks. | ||
2667 | */ | ||
2668 | WARN_ON_ONCE(!mutex_trylock(&inode->i_mutex)); | ||
2663 | } else if (S_ISREG(mode)) { | 2669 | } else if (S_ISREG(mode)) { |
2664 | inode->i_size = 0; | 2670 | inode->i_size = 0; |
2665 | inode->i_fop = &cgroup_file_operations; | 2671 | inode->i_fop = &cgroup_file_operations; |