Branch data Line data Source code
1 : : /*
2 : : * linux/fs/filesystems.c
3 : : *
4 : : * Copyright (C) 1991, 1992 Linus Torvalds
5 : : *
6 : : * table of configured filesystems
7 : : */
8 : :
9 : : #include <linux/syscalls.h>
10 : : #include <linux/fs.h>
11 : : #include <linux/proc_fs.h>
12 : : #include <linux/seq_file.h>
13 : : #include <linux/kmod.h>
14 : : #include <linux/init.h>
15 : : #include <linux/module.h>
16 : : #include <linux/slab.h>
17 : : #include <asm/uaccess.h>
18 : :
19 : : /*
20 : : * Handling of filesystem drivers list.
21 : : * Rules:
22 : : * Inclusion to/removals from/scanning of list are protected by spinlock.
23 : : * During the unload module must call unregister_filesystem().
24 : : * We can access the fields of list element if:
25 : : * 1) spinlock is held or
26 : : * 2) we hold the reference to the module.
27 : : * The latter can be guaranteed by call of try_module_get(); if it
28 : : * returned 0 we must skip the element, otherwise we got the reference.
29 : : * Once the reference is obtained we can drop the spinlock.
30 : : */
31 : :
32 : : static struct file_system_type *file_systems;
33 : : static DEFINE_RWLOCK(file_systems_lock);
34 : :
35 : : /* WARNING: This can be used only if we _already_ own a reference */
36 : 0 : void get_filesystem(struct file_system_type *fs)
37 : : {
38 : 28 : __module_get(fs->owner);
39 : 28 : }
40 : :
41 : 0 : void put_filesystem(struct file_system_type *fs)
42 : : {
43 : 3041 : module_put(fs->owner);
44 : 3039 : }
45 : :
46 : 0 : static struct file_system_type **find_filesystem(const char *name, unsigned len)
47 : : {
48 : : struct file_system_type **p;
49 [ + + ]: 18465 : for (p=&file_systems; *p; p=&(*p)->next)
50 [ + + ][ + + ]: 18462 : if (strlen((*p)->name) == len &&
51 : 6082 : strncmp((*p)->name, name, len) == 0)
52 : : break;
53 : 0 : return p;
54 : : }
55 : :
56 : : /**
57 : : * register_filesystem - register a new filesystem
58 : : * @fs: the file system structure
59 : : *
60 : : * Adds the file system passed to the list of file systems the kernel
61 : : * is aware of for mount and other syscalls. Returns 0 on success,
62 : : * or a negative errno code on an error.
63 : : *
64 : : * The &struct file_system_type that is passed is linked into the kernel
65 : : * structures and must not be freed until the file system has been
66 : : * unregistered.
67 : : */
68 : :
69 : 0 : int register_filesystem(struct file_system_type * fs)
70 : : {
71 : : int res = 0;
72 : : struct file_system_type ** p;
73 : :
74 [ # # ]: 0 : BUG_ON(strchr(fs->name, '.'));
75 [ # # ]: 0 : if (fs->next)
76 : : return -EBUSY;
77 : 0 : write_lock(&file_systems_lock);
78 : 0 : p = find_filesystem(fs->name, strlen(fs->name));
79 [ # # ]: 0 : if (*p)
80 : : res = -EBUSY;
81 : : else
82 : 0 : *p = fs;
83 : : write_unlock(&file_systems_lock);
84 : 0 : return res;
85 : : }
86 : :
87 : : EXPORT_SYMBOL(register_filesystem);
88 : :
89 : : /**
90 : : * unregister_filesystem - unregister a file system
91 : : * @fs: filesystem to unregister
92 : : *
93 : : * Remove a file system that was previously successfully registered
94 : : * with the kernel. An error is returned if the file system is not found.
95 : : * Zero is returned on a success.
96 : : *
97 : : * Once this function has returned the &struct file_system_type structure
98 : : * may be freed or reused.
99 : : */
100 : :
101 : 0 : int unregister_filesystem(struct file_system_type * fs)
102 : : {
103 : : struct file_system_type ** tmp;
104 : :
105 : 0 : write_lock(&file_systems_lock);
106 : : tmp = &file_systems;
107 [ # # ]: 0 : while (*tmp) {
108 [ # # ]: 0 : if (fs == *tmp) {
109 : 0 : *tmp = fs->next;
110 : 0 : fs->next = NULL;
111 : : write_unlock(&file_systems_lock);
112 : : synchronize_rcu();
113 : 0 : return 0;
114 : : }
115 : 0 : tmp = &(*tmp)->next;
116 : : }
117 : : write_unlock(&file_systems_lock);
118 : :
119 : 0 : return -EINVAL;
120 : : }
121 : :
122 : : EXPORT_SYMBOL(unregister_filesystem);
123 : :
124 : 0 : static int fs_index(const char __user * __name)
125 : : {
126 : : struct file_system_type * tmp;
127 : : struct filename *name;
128 : : int err, index;
129 : :
130 : 3 : name = getname(__name);
131 : : err = PTR_ERR(name);
132 [ + + ]: 3 : if (IS_ERR(name))
133 : : return err;
134 : :
135 : : err = -EINVAL;
136 : 2 : read_lock(&file_systems_lock);
137 [ + + ]: 36 : for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
138 [ + + ]: 35 : if (strcmp(tmp->name, name->name) == 0) {
139 : : err = index;
140 : : break;
141 : : }
142 : : }
143 : : read_unlock(&file_systems_lock);
144 : 2 : putname(name);
145 : 2 : return err;
146 : : }
147 : :
148 : 0 : static int fs_name(unsigned int index, char __user * buf)
149 : : {
150 : : struct file_system_type * tmp;
151 : : int len, res;
152 : :
153 : 3 : read_lock(&file_systems_lock);
154 [ + + ]: 34 : for (tmp = file_systems; tmp; tmp = tmp->next, index--)
155 [ + + ][ - + ]: 33 : if (index <= 0 && try_module_get(tmp->owner))
156 : : break;
157 : : read_unlock(&file_systems_lock);
158 [ + + ]: 3 : if (!tmp)
159 : : return -EINVAL;
160 : :
161 : : /* OK, we got the reference, so we can safely block */
162 : 2 : len = strlen(tmp->name) + 1;
163 [ + + ]: 5 : res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
164 : : put_filesystem(tmp);
165 : 2 : return res;
166 : : }
167 : :
168 : 0 : static int fs_maxindex(void)
169 : : {
170 : : struct file_system_type * tmp;
171 : : int index;
172 : :
173 : 1 : read_lock(&file_systems_lock);
174 [ + + ]: 31 : for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
175 : : ;
176 : : read_unlock(&file_systems_lock);
177 : 1 : return index;
178 : : }
179 : :
180 : : /*
181 : : * Whee.. Weird sysv syscall.
182 : : */
183 : 0 : SYSCALL_DEFINE3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2)
184 : : {
185 : : int retval = -EINVAL;
186 : :
187 [ + + + + ]: 10 : switch (option) {
188 : : case 1:
189 : 3 : retval = fs_index((const char __user *) arg1);
190 : : break;
191 : :
192 : : case 2:
193 : 3 : retval = fs_name(arg1, (char __user *) arg2);
194 : : break;
195 : :
196 : : case 3:
197 : 1 : retval = fs_maxindex();
198 : : break;
199 : : }
200 : : return retval;
201 : : }
202 : :
203 : 0 : int __init get_filesystem_list(char *buf)
204 : : {
205 : : int len = 0;
206 : : struct file_system_type * tmp;
207 : :
208 : 0 : read_lock(&file_systems_lock);
209 : 0 : tmp = file_systems;
210 [ # # ]: 0 : while (tmp && len < PAGE_SIZE - 80) {
211 [ # # ]: 0 : len += sprintf(buf+len, "%s\t%s\n",
212 : 0 : (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
213 : : tmp->name);
214 : 0 : tmp = tmp->next;
215 : : }
216 : : read_unlock(&file_systems_lock);
217 : 0 : return len;
218 : : }
219 : :
220 : : #ifdef CONFIG_PROC_FS
221 : 0 : static int filesystems_proc_show(struct seq_file *m, void *v)
222 : : {
223 : : struct file_system_type * tmp;
224 : :
225 : 8145 : read_lock(&file_systems_lock);
226 : 8151 : tmp = file_systems;
227 [ + + ]: 252469 : while (tmp) {
228 [ + + ]: 244324 : seq_printf(m, "%s\t%s\n",
229 : 244324 : (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
230 : : tmp->name);
231 : 244318 : tmp = tmp->next;
232 : : }
233 : : read_unlock(&file_systems_lock);
234 : 8145 : return 0;
235 : : }
236 : :
237 : 0 : static int filesystems_proc_open(struct inode *inode, struct file *file)
238 : : {
239 : 8145 : return single_open(file, filesystems_proc_show, NULL);
240 : : }
241 : :
242 : : static const struct file_operations filesystems_proc_fops = {
243 : : .open = filesystems_proc_open,
244 : : .read = seq_read,
245 : : .llseek = seq_lseek,
246 : : .release = single_release,
247 : : };
248 : :
249 : 0 : static int __init proc_filesystems_init(void)
250 : : {
251 : : proc_create("filesystems", 0, NULL, &filesystems_proc_fops);
252 : 0 : return 0;
253 : : }
254 : : module_init(proc_filesystems_init);
255 : : #endif
256 : :
257 : 0 : static struct file_system_type *__get_fs_type(const char *name, int len)
258 : : {
259 : : struct file_system_type *fs;
260 : :
261 : 3014 : read_lock(&file_systems_lock);
262 : 3014 : fs = *(find_filesystem(name, len));
263 [ + + ][ - + ]: 3014 : if (fs && !try_module_get(fs->owner))
264 : : fs = NULL;
265 : : read_unlock(&file_systems_lock);
266 : 3014 : return fs;
267 : : }
268 : :
269 : 0 : struct file_system_type *get_fs_type(const char *name)
270 : : {
271 : : struct file_system_type *fs;
272 : 3014 : const char *dot = strchr(name, '.');
273 [ - + ]: 3014 : int len = dot ? dot - name : strlen(name);
274 : :
275 : 3014 : fs = __get_fs_type(name, len);
276 [ + + ][ - + ]: 3014 : if (!fs && (request_module("fs-%.*s", len, name) == 0))
277 : 0 : fs = __get_fs_type(name, len);
278 : :
279 [ - + ][ # # ]: 3014 : if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) {
280 : : put_filesystem(fs);
281 : : fs = NULL;
282 : : }
283 : 0 : return fs;
284 : : }
285 : :
286 : : EXPORT_SYMBOL(get_fs_type);
|