diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-03-15 14:48:55 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-03-20 21:29:42 -0400 |
| commit | 82234e61a8fc75599f29026c0805fc0cfe2a6c87 (patch) | |
| tree | 6ee40363b259ed5de9d28b12f13646d6748214e2 | |
| parent | 3ee05ed0679f29ab19727067ff7c14f0c257fa9a (diff) | |
vfs: take path_get_longterm() out of write_seqcount scope
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/fs_struct.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/fs/fs_struct.c b/fs/fs_struct.c index 27114b41362..6324c427495 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 | ||
| 60 | static 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 | |||
| 60 | void chroot_fs_refs(struct path *old_root, struct path *new_root) | 68 | void 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); |
