Take fs_struct handling to new file (fs/fs_struct.c)
[linux-2.6] / fs / fs_struct.c
1 #include <linux/module.h>
2 #include <linux/sched.h>
3 #include <linux/fs.h>
4 #include <linux/path.h>
5 #include <linux/slab.h>
6
7 /*
8  * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
9  * It can block.
10  */
11 void set_fs_root(struct fs_struct *fs, struct path *path)
12 {
13         struct path old_root;
14
15         write_lock(&fs->lock);
16         old_root = fs->root;
17         fs->root = *path;
18         path_get(path);
19         write_unlock(&fs->lock);
20         if (old_root.dentry)
21                 path_put(&old_root);
22 }
23
24 /*
25  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
26  * It can block.
27  */
28 void set_fs_pwd(struct fs_struct *fs, struct path *path)
29 {
30         struct path old_pwd;
31
32         write_lock(&fs->lock);
33         old_pwd = fs->pwd;
34         fs->pwd = *path;
35         path_get(path);
36         write_unlock(&fs->lock);
37
38         if (old_pwd.dentry)
39                 path_put(&old_pwd);
40 }
41
42 void chroot_fs_refs(struct path *old_root, struct path *new_root)
43 {
44         struct task_struct *g, *p;
45         struct fs_struct *fs;
46         int count = 0;
47
48         read_lock(&tasklist_lock);
49         do_each_thread(g, p) {
50                 task_lock(p);
51                 fs = p->fs;
52                 if (fs) {
53                         write_lock(&fs->lock);
54                         if (fs->root.dentry == old_root->dentry
55                             && fs->root.mnt == old_root->mnt) {
56                                 path_get(new_root);
57                                 fs->root = *new_root;
58                                 count++;
59                         }
60                         if (fs->pwd.dentry == old_root->dentry
61                             && fs->pwd.mnt == old_root->mnt) {
62                                 path_get(new_root);
63                                 fs->pwd = *new_root;
64                                 count++;
65                         }
66                         write_unlock(&fs->lock);
67                 }
68                 task_unlock(p);
69         } while_each_thread(g, p);
70         read_unlock(&tasklist_lock);
71         while (count--)
72                 path_put(old_root);
73 }
74
75 void put_fs_struct(struct fs_struct *fs)
76 {
77         /* No need to hold fs->lock if we are killing it */
78         if (atomic_dec_and_test(&fs->count)) {
79                 path_put(&fs->root);
80                 path_put(&fs->pwd);
81                 kmem_cache_free(fs_cachep, fs);
82         }
83 }
84
85 void exit_fs(struct task_struct *tsk)
86 {
87         struct fs_struct * fs = tsk->fs;
88
89         if (fs) {
90                 task_lock(tsk);
91                 tsk->fs = NULL;
92                 task_unlock(tsk);
93                 put_fs_struct(fs);
94         }
95 }
96
97 struct fs_struct *copy_fs_struct(struct fs_struct *old)
98 {
99         struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
100         /* We don't need to lock fs - think why ;-) */
101         if (fs) {
102                 atomic_set(&fs->count, 1);
103                 rwlock_init(&fs->lock);
104                 fs->umask = old->umask;
105                 read_lock(&old->lock);
106                 fs->root = old->root;
107                 path_get(&old->root);
108                 fs->pwd = old->pwd;
109                 path_get(&old->pwd);
110                 read_unlock(&old->lock);
111         }
112         return fs;
113 }
114
115 int unshare_fs_struct(void)
116 {
117         struct fs_struct *fsp = copy_fs_struct(current->fs);
118         if (!fsp)
119                 return -ENOMEM;
120         exit_fs(current);
121         current->fs = fsp;
122         return 0;
123 }
124 EXPORT_SYMBOL_GPL(unshare_fs_struct);
125
126 /* to be mentioned only in INIT_TASK */
127 struct fs_struct init_fs = {
128         .count          = ATOMIC_INIT(1),
129         .lock           = __RW_LOCK_UNLOCKED(init_fs.lock),
130         .umask          = 0022,
131 };
132
133 void daemonize_fs_struct(void)
134 {
135         struct fs_struct *fs;
136
137         exit_fs(current);       /* current->fs->count--; */
138         fs = &init_fs;
139         current->fs = fs;
140         atomic_inc(&fs->count);
141 }