Merge branch 'linux-linaro-lsk-v4.4-android' of git://git.linaro.org/kernel/linux...
[firefly-linux-kernel-4.4.55.git] / fs / fs_struct.c
1 #include <linux/export.h>
2 #include <linux/sched.h>
3 #include <linux/fs.h>
4 #include <linux/path.h>
5 #include <linux/slab.h>
6 #include <linux/fs_struct.h>
7 #include "internal.h"
8
9 /*
10  * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
11  * It can block.
12  */
13 void set_fs_root(struct fs_struct *fs, const struct path *path)
14 {
15         struct path old_root;
16
17         path_get(path);
18         spin_lock(&fs->lock);
19         write_seqcount_begin(&fs->seq);
20         old_root = fs->root;
21         fs->root = *path;
22         write_seqcount_end(&fs->seq);
23         spin_unlock(&fs->lock);
24         if (old_root.dentry)
25                 path_put(&old_root);
26 }
27
28 /*
29  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
30  * It can block.
31  */
32 void set_fs_pwd(struct fs_struct *fs, const struct path *path)
33 {
34         struct path old_pwd;
35
36         path_get(path);
37         spin_lock(&fs->lock);
38         write_seqcount_begin(&fs->seq);
39         old_pwd = fs->pwd;
40         fs->pwd = *path;
41         write_seqcount_end(&fs->seq);
42         spin_unlock(&fs->lock);
43
44         if (old_pwd.dentry)
45                 path_put(&old_pwd);
46 }
47 EXPORT_SYMBOL(set_fs_pwd);
48
49 static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
50 {
51         if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
52                 return 0;
53         *p = *new;
54         return 1;
55 }
56
57 void chroot_fs_refs(const struct path *old_root, const struct path *new_root)
58 {
59         struct task_struct *g, *p;
60         struct fs_struct *fs;
61         int count = 0;
62
63         read_lock(&tasklist_lock);
64         do_each_thread(g, p) {
65                 task_lock(p);
66                 fs = p->fs;
67                 if (fs) {
68                         int hits = 0;
69                         spin_lock(&fs->lock);
70                         write_seqcount_begin(&fs->seq);
71                         hits += replace_path(&fs->root, old_root, new_root);
72                         hits += replace_path(&fs->pwd, old_root, new_root);
73                         write_seqcount_end(&fs->seq);
74                         while (hits--) {
75                                 count++;
76                                 path_get(new_root);
77                         }
78                         spin_unlock(&fs->lock);
79                 }
80                 task_unlock(p);
81         } while_each_thread(g, p);
82         read_unlock(&tasklist_lock);
83         while (count--)
84                 path_put(old_root);
85 }
86
87 void free_fs_struct(struct fs_struct *fs)
88 {
89         path_put(&fs->root);
90         path_put(&fs->pwd);
91         kmem_cache_free(fs_cachep, fs);
92 }
93 EXPORT_SYMBOL(free_fs_struct);
94
95 void exit_fs(struct task_struct *tsk)
96 {
97         struct fs_struct *fs = tsk->fs;
98
99         if (fs) {
100                 int kill;
101                 task_lock(tsk);
102                 spin_lock(&fs->lock);
103                 tsk->fs = NULL;
104                 kill = !--fs->users;
105                 spin_unlock(&fs->lock);
106                 task_unlock(tsk);
107                 if (kill)
108                         free_fs_struct(fs);
109         }
110 }
111
112 struct fs_struct *copy_fs_struct(struct fs_struct *old)
113 {
114         struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
115         /* We don't need to lock fs - think why ;-) */
116         if (fs) {
117                 fs->users = 1;
118                 fs->in_exec = 0;
119                 spin_lock_init(&fs->lock);
120                 seqcount_init(&fs->seq);
121                 fs->umask = old->umask;
122
123                 spin_lock(&old->lock);
124                 fs->root = old->root;
125                 path_get(&fs->root);
126                 fs->pwd = old->pwd;
127                 path_get(&fs->pwd);
128                 spin_unlock(&old->lock);
129         }
130         return fs;
131 }
132 EXPORT_SYMBOL_GPL(copy_fs_struct);
133
134 int unshare_fs_struct(void)
135 {
136         struct fs_struct *fs = current->fs;
137         struct fs_struct *new_fs = copy_fs_struct(fs);
138         int kill;
139
140         if (!new_fs)
141                 return -ENOMEM;
142
143         task_lock(current);
144         spin_lock(&fs->lock);
145         kill = !--fs->users;
146         current->fs = new_fs;
147         spin_unlock(&fs->lock);
148         task_unlock(current);
149
150         if (kill)
151                 free_fs_struct(fs);
152
153         return 0;
154 }
155 EXPORT_SYMBOL_GPL(unshare_fs_struct);
156
157 int current_umask(void)
158 {
159         return current->fs->umask;
160 }
161 EXPORT_SYMBOL(current_umask);
162
163 /* to be mentioned only in INIT_TASK */
164 struct fs_struct init_fs = {
165         .users          = 1,
166         .lock           = __SPIN_LOCK_UNLOCKED(init_fs.lock),
167         .seq            = SEQCNT_ZERO(init_fs.seq),
168         .umask          = 0022,
169 };