aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2009-03-30 20:36:33 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-03-31 23:00:25 -0400
commitf8ef3ed2bebd2c4cb9ece92efa185d7aead8831a (patch)
treef6208725f0b2ecd43e393435fa7fb8ad1be1b14b
parent11d06b2a1e5658f448a308aa3beb97bacd64a940 (diff)
Get rid of bumping fs_struct refcount in pivot_root(2)
Not because execve races with _that_ are serious - we really need a situation when final drop of fs_struct refcount is done by something that used to have it as current->fs. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/namespace.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 0a42e0e9602..f7ec283ccfb 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2131,25 +2131,33 @@ static void chroot_fs_refs(struct path *old_root, struct path *new_root)
2131{ 2131{
2132 struct task_struct *g, *p; 2132 struct task_struct *g, *p;
2133 struct fs_struct *fs; 2133 struct fs_struct *fs;
2134 int count = 0;
2134 2135
2135 read_lock(&tasklist_lock); 2136 read_lock(&tasklist_lock);
2136 do_each_thread(g, p) { 2137 do_each_thread(g, p) {
2137 task_lock(p); 2138 task_lock(p);
2138 fs = p->fs; 2139 fs = p->fs;
2139 if (fs) { 2140 if (fs) {
2140 atomic_inc(&fs->count); 2141 write_lock(&fs->lock);
2141 task_unlock(p);
2142 if (fs->root.dentry == old_root->dentry 2142 if (fs->root.dentry == old_root->dentry
2143 && fs->root.mnt == old_root->mnt) 2143 && fs->root.mnt == old_root->mnt) {
2144 set_fs_root(fs, new_root); 2144 path_get(new_root);
2145 fs->root = *new_root;
2146 count++;
2147 }
2145 if (fs->pwd.dentry == old_root->dentry 2148 if (fs->pwd.dentry == old_root->dentry
2146 && fs->pwd.mnt == old_root->mnt) 2149 && fs->pwd.mnt == old_root->mnt) {
2147 set_fs_pwd(fs, new_root); 2150 path_get(new_root);
2148 put_fs_struct(fs); 2151 fs->pwd = *new_root;
2149 } else 2152 count++;
2150 task_unlock(p); 2153 }
2154 write_unlock(&fs->lock);
2155 }
2156 task_unlock(p);
2151 } while_each_thread(g, p); 2157 } while_each_thread(g, p);
2152 read_unlock(&tasklist_lock); 2158 read_unlock(&tasklist_lock);
2159 while (count--)
2160 path_put(old_root);
2153} 2161}
2154 2162
2155/* 2163/*