aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fs_struct.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index 27114b413622..6324c4274959 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -26,11 +26,11 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
26{ 26{
27 struct path old_root; 27 struct path old_root;
28 28
29 path_get_longterm(path);
29 spin_lock(&fs->lock); 30 spin_lock(&fs->lock);
30 write_seqcount_begin(&fs->seq); 31 write_seqcount_begin(&fs->seq);
31 old_root = fs->root; 32 old_root = fs->root;
32 fs->root = *path; 33 fs->root = *path;
33 path_get_longterm(path);
34 write_seqcount_end(&fs->seq); 34 write_seqcount_end(&fs->seq);
35 spin_unlock(&fs->lock); 35 spin_unlock(&fs->lock);
36 if (old_root.dentry) 36 if (old_root.dentry)
@@ -45,11 +45,11 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
45{ 45{
46 struct path old_pwd; 46 struct path old_pwd;
47 47
48 path_get_longterm(path);
48 spin_lock(&fs->lock); 49 spin_lock(&fs->lock);
49 write_seqcount_begin(&fs->seq); 50 write_seqcount_begin(&fs->seq);
50 old_pwd = fs->pwd; 51 old_pwd = fs->pwd;
51 fs->pwd = *path; 52 fs->pwd = *path;
52 path_get_longterm(path);
53 write_seqcount_end(&fs->seq); 53 write_seqcount_end(&fs->seq);
54 spin_unlock(&fs->lock); 54 spin_unlock(&fs->lock);
55 55
@@ -57,6 +57,14 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
57 path_put_longterm(&old_pwd); 57 path_put_longterm(&old_pwd);
58} 58}
59 59
60static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
61{
62 if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
63 return 0;
64 *p = *new;
65 return 1;
66}
67
60void chroot_fs_refs(struct path *old_root, struct path *new_root) 68void chroot_fs_refs(struct path *old_root, struct path *new_root)
61{ 69{
62 struct task_struct *g, *p; 70 struct task_struct *g, *p;
@@ -68,21 +76,16 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root)
68 task_lock(p); 76 task_lock(p);
69 fs = p->fs; 77 fs = p->fs;
70 if (fs) { 78 if (fs) {
79 int hits = 0;
71 spin_lock(&fs->lock); 80 spin_lock(&fs->lock);
72 write_seqcount_begin(&fs->seq); 81 write_seqcount_begin(&fs->seq);
73 if (fs->root.dentry == old_root->dentry 82 hits += replace_path(&fs->root, old_root, new_root);
74 && fs->root.mnt == old_root->mnt) { 83 hits += replace_path(&fs->pwd, old_root, new_root);
75 path_get_longterm(new_root); 84 write_seqcount_end(&fs->seq);
76 fs->root = *new_root; 85 while (hits--) {
77 count++; 86 count++;
78 }
79 if (fs->pwd.dentry == old_root->dentry
80 && fs->pwd.mnt == old_root->mnt) {
81 path_get_longterm(new_root); 87 path_get_longterm(new_root);
82 fs->pwd = *new_root;
83 count++;
84 } 88 }
85 write_seqcount_end(&fs->seq);
86 spin_unlock(&fs->lock); 89 spin_unlock(&fs->lock);
87 } 90 }
88 task_unlock(p); 91 task_unlock(p);