aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fs_struct.c
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2011-05-10 14:52:07 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2011-05-10 16:50:41 -0400
commit020abf03cd659388f94cb328e1e1df0656e0d7ff (patch)
tree40d05011708ad1b4a05928d167eb120420581aa6 /fs/fs_struct.c
parent0ff8fbc61727c926883eec381fbd3d32d1fab504 (diff)
parent693d92a1bbc9e42681c42ed190bd42b636ca876f (diff)
Merge tag 'v2.6.39-rc7'
in order to pull in changes in drivers/media/dvb/firewire/ and sound/firewire/.
Diffstat (limited to 'fs/fs_struct.c')
-rw-r--r--fs/fs_struct.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index ed45a9cf5f3d..78b519c13536 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -4,6 +4,19 @@
4#include <linux/path.h> 4#include <linux/path.h>
5#include <linux/slab.h> 5#include <linux/slab.h>
6#include <linux/fs_struct.h> 6#include <linux/fs_struct.h>
7#include "internal.h"
8
9static inline void path_get_longterm(struct path *path)
10{
11 path_get(path);
12 mnt_make_longterm(path->mnt);
13}
14
15static inline void path_put_longterm(struct path *path)
16{
17 mnt_make_shortterm(path->mnt);
18 path_put(path);
19}
7 20
8/* 21/*
9 * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. 22 * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
@@ -14,12 +27,14 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
14 struct path old_root; 27 struct path old_root;
15 28
16 spin_lock(&fs->lock); 29 spin_lock(&fs->lock);
30 write_seqcount_begin(&fs->seq);
17 old_root = fs->root; 31 old_root = fs->root;
18 fs->root = *path; 32 fs->root = *path;
19 path_get(path); 33 path_get_longterm(path);
34 write_seqcount_end(&fs->seq);
20 spin_unlock(&fs->lock); 35 spin_unlock(&fs->lock);
21 if (old_root.dentry) 36 if (old_root.dentry)
22 path_put(&old_root); 37 path_put_longterm(&old_root);
23} 38}
24 39
25/* 40/*
@@ -31,13 +46,15 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
31 struct path old_pwd; 46 struct path old_pwd;
32 47
33 spin_lock(&fs->lock); 48 spin_lock(&fs->lock);
49 write_seqcount_begin(&fs->seq);
34 old_pwd = fs->pwd; 50 old_pwd = fs->pwd;
35 fs->pwd = *path; 51 fs->pwd = *path;
36 path_get(path); 52 path_get_longterm(path);
53 write_seqcount_end(&fs->seq);
37 spin_unlock(&fs->lock); 54 spin_unlock(&fs->lock);
38 55
39 if (old_pwd.dentry) 56 if (old_pwd.dentry)
40 path_put(&old_pwd); 57 path_put_longterm(&old_pwd);
41} 58}
42 59
43void chroot_fs_refs(struct path *old_root, struct path *new_root) 60void chroot_fs_refs(struct path *old_root, struct path *new_root)
@@ -52,31 +69,33 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root)
52 fs = p->fs; 69 fs = p->fs;
53 if (fs) { 70 if (fs) {
54 spin_lock(&fs->lock); 71 spin_lock(&fs->lock);
72 write_seqcount_begin(&fs->seq);
55 if (fs->root.dentry == old_root->dentry 73 if (fs->root.dentry == old_root->dentry
56 && fs->root.mnt == old_root->mnt) { 74 && fs->root.mnt == old_root->mnt) {
57 path_get(new_root); 75 path_get_longterm(new_root);
58 fs->root = *new_root; 76 fs->root = *new_root;
59 count++; 77 count++;
60 } 78 }
61 if (fs->pwd.dentry == old_root->dentry 79 if (fs->pwd.dentry == old_root->dentry
62 && fs->pwd.mnt == old_root->mnt) { 80 && fs->pwd.mnt == old_root->mnt) {
63 path_get(new_root); 81 path_get_longterm(new_root);
64 fs->pwd = *new_root; 82 fs->pwd = *new_root;
65 count++; 83 count++;
66 } 84 }
85 write_seqcount_end(&fs->seq);
67 spin_unlock(&fs->lock); 86 spin_unlock(&fs->lock);
68 } 87 }
69 task_unlock(p); 88 task_unlock(p);
70 } while_each_thread(g, p); 89 } while_each_thread(g, p);
71 read_unlock(&tasklist_lock); 90 read_unlock(&tasklist_lock);
72 while (count--) 91 while (count--)
73 path_put(old_root); 92 path_put_longterm(old_root);
74} 93}
75 94
76void free_fs_struct(struct fs_struct *fs) 95void free_fs_struct(struct fs_struct *fs)
77{ 96{
78 path_put(&fs->root); 97 path_put_longterm(&fs->root);
79 path_put(&fs->pwd); 98 path_put_longterm(&fs->pwd);
80 kmem_cache_free(fs_cachep, fs); 99 kmem_cache_free(fs_cachep, fs);
81} 100}
82 101
@@ -88,8 +107,10 @@ void exit_fs(struct task_struct *tsk)
88 int kill; 107 int kill;
89 task_lock(tsk); 108 task_lock(tsk);
90 spin_lock(&fs->lock); 109 spin_lock(&fs->lock);
110 write_seqcount_begin(&fs->seq);
91 tsk->fs = NULL; 111 tsk->fs = NULL;
92 kill = !--fs->users; 112 kill = !--fs->users;
113 write_seqcount_end(&fs->seq);
93 spin_unlock(&fs->lock); 114 spin_unlock(&fs->lock);
94 task_unlock(tsk); 115 task_unlock(tsk);
95 if (kill) 116 if (kill)
@@ -105,8 +126,15 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old)
105 fs->users = 1; 126 fs->users = 1;
106 fs->in_exec = 0; 127 fs->in_exec = 0;
107 spin_lock_init(&fs->lock); 128 spin_lock_init(&fs->lock);
129 seqcount_init(&fs->seq);
108 fs->umask = old->umask; 130 fs->umask = old->umask;
109 get_fs_root_and_pwd(old, &fs->root, &fs->pwd); 131
132 spin_lock(&old->lock);
133 fs->root = old->root;
134 path_get_longterm(&fs->root);
135 fs->pwd = old->pwd;
136 path_get_longterm(&fs->pwd);
137 spin_unlock(&old->lock);
110 } 138 }
111 return fs; 139 return fs;
112} 140}
@@ -144,6 +172,7 @@ EXPORT_SYMBOL(current_umask);
144struct fs_struct init_fs = { 172struct fs_struct init_fs = {
145 .users = 1, 173 .users = 1,
146 .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock), 174 .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock),
175 .seq = SEQCNT_ZERO,
147 .umask = 0022, 176 .umask = 0022,
148}; 177};
149 178