summaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/super.c b/fs/super.c
index 91e17f2b6..8576d79d0 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1566,15 +1566,22 @@ static void chroot_fs_refs(struct dentry *old_root,
struct vfsmount *new_rootmnt)
{
struct task_struct *p;
+ struct fs_struct *fs;
read_lock(&tasklist_lock);
for_each_task(p) {
- /* FIXME - unprotected usage of ->fs + (harmless) race */
- if (!p->fs) continue;
- if (p->fs->root == old_root && p->fs->rootmnt == old_rootmnt)
- set_fs_root(p->fs, new_rootmnt, new_root);
- if (p->fs->pwd == old_root && p->fs->pwdmnt == old_rootmnt)
- set_fs_pwd(p->fs, new_rootmnt, new_root);
+ task_lock(p);
+ fs = p->fs;
+ if (fs) {
+ atomic_inc(&fs->count);
+ task_unlock(p);
+ if (fs->root==old_root && fs->rootmnt==old_rootmnt)
+ set_fs_root(fs, new_rootmnt, new_root);
+ if (fs->pwd==old_root && fs->pwdmnt==old_rootmnt)
+ set_fs_pwd(fs, new_rootmnt, new_root);
+ put_fs_struct(fs);
+ } else
+ task_unlock(p);
}
read_unlock(&tasklist_lock);
}