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/slab.h>
12 : #include <linux/kmod.h>
13 : #include <linux/init.h>
14 : #include <linux/module.h>
15 : #include <asm/uaccess.h>
16 :
17 : /*
18 : * Handling of filesystem drivers list.
19 : * Rules:
20 : * Inclusion to/removals from/scanning of list are protected by spinlock.
21 : * During the unload module must call unregister_filesystem().
22 : * We can access the fields of list element if:
23 : * 1) spinlock is held or
24 : * 2) we hold the reference to the module.
25 : * The latter can be guaranteed by call of try_module_get(); if it
26 : * returned 0 we must skip the element, otherwise we got the reference.
27 : * Once the reference is obtained we can drop the spinlock.
28 : */
29 :
30 : static struct file_system_type *file_systems;
31 : static DEFINE_RWLOCK(file_systems_lock);
32 :
33 : /* WARNING: This can be used only if we _already_ own a reference */
34 : void get_filesystem(struct file_system_type *fs)
35 20 : {
36 20 : __module_get(fs->owner);
37 : }
38 :
39 : void put_filesystem(struct file_system_type *fs)
40 26 : {
41 26 : module_put(fs->owner);
42 : }
43 :
44 : static struct file_system_type **find_filesystem(const char *name)
45 53 : {
46 53 : struct file_system_type **p;
47 644 : for (p=&file_systems; *p; p=&(*p)->next)
48 617 : if (strcmp((*p)->name,name) == 0)
49 591 : break;
50 53 : return p;
51 : }
52 :
53 : /**
54 : * register_filesystem - register a new filesystem
55 : * @fs: the file system structure
56 : *
57 : * Adds the file system passed to the list of file systems the kernel
58 : * is aware of for mount and other syscalls. Returns 0 on success,
59 : * or a negative errno code on an error.
60 : *
61 : * The &struct file_system_type that is passed is linked into the kernel
62 : * structures and must not be freed until the file system has been
63 : * unregistered.
64 : */
65 :
66 : int register_filesystem(struct file_system_type * fs)
67 27 : {
68 27 : int res = 0;
69 27 : struct file_system_type ** p;
70 :
71 27 : if (!fs)
72 0 : return -EINVAL;
73 27 : if (fs->next)
74 0 : return -EBUSY;
75 27 : INIT_LIST_HEAD(&fs->fs_supers);
76 27 : write_lock(&file_systems_lock);
77 27 : p = find_filesystem(fs->name);
78 27 : if (*p)
79 0 : res = -EBUSY;
80 : else
81 27 : *p = fs;
82 27 : write_unlock(&file_systems_lock);
83 27 : return res;
84 : }
85 :
86 : EXPORT_SYMBOL(register_filesystem);
87 :
88 : /**
89 : * unregister_filesystem - unregister a file system
90 : * @fs: filesystem to unregister
91 : *
92 : * Remove a file system that was previously successfully registered
93 : * with the kernel. An error is returned if the file system is not found.
94 : * Zero is returned on a success.
95 : *
96 : * Once this function has returned the &struct file_system_type structure
97 : * may be freed or reused.
98 : */
99 :
100 : int unregister_filesystem(struct file_system_type * fs)
101 0 : {
102 0 : struct file_system_type ** tmp;
103 :
104 0 : write_lock(&file_systems_lock);
105 0 : tmp = &file_systems;
106 0 : while (*tmp) {
107 0 : if (fs == *tmp) {
108 0 : *tmp = fs->next;
109 0 : fs->next = NULL;
110 0 : write_unlock(&file_systems_lock);
111 0 : return 0;
112 : }
113 0 : tmp = &(*tmp)->next;
114 : }
115 0 : write_unlock(&file_systems_lock);
116 0 : return -EINVAL;
117 : }
118 :
119 : EXPORT_SYMBOL(unregister_filesystem);
120 :
121 : static int fs_index(const char __user * __name)
122 0 : {
123 0 : struct file_system_type * tmp;
124 0 : char * name;
125 0 : int err, index;
126 :
127 0 : name = getname(__name);
128 0 : err = PTR_ERR(name);
129 0 : if (IS_ERR(name))
130 0 : return err;
131 :
132 0 : err = -EINVAL;
133 0 : read_lock(&file_systems_lock);
134 0 : for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
135 0 : if (strcmp(tmp->name,name) == 0) {
136 0 : err = index;
137 0 : break;
138 : }
139 : }
140 0 : read_unlock(&file_systems_lock);
141 0 : putname(name);
142 0 : return err;
143 : }
144 :
145 : static int fs_name(unsigned int index, char __user * buf)
146 0 : {
147 0 : struct file_system_type * tmp;
148 0 : int len, res;
149 :
150 0 : read_lock(&file_systems_lock);
151 0 : for (tmp = file_systems; tmp; tmp = tmp->next, index--)
152 0 : if (index <= 0 && try_module_get(tmp->owner))
153 0 : break;
154 0 : read_unlock(&file_systems_lock);
155 0 : if (!tmp)
156 0 : return -EINVAL;
157 :
158 : /* OK, we got the reference, so we can safely block */
159 0 : len = strlen(tmp->name) + 1;
160 0 : res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
161 0 : put_filesystem(tmp);
162 0 : return res;
163 : }
164 :
165 : static int fs_maxindex(void)
166 0 : {
167 0 : struct file_system_type * tmp;
168 0 : int index;
169 :
170 0 : read_lock(&file_systems_lock);
171 0 : for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
172 : ;
173 0 : read_unlock(&file_systems_lock);
174 0 : return index;
175 : }
176 :
177 : /*
178 : * Whee.. Weird sysv syscall.
179 : */
180 : asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
181 0 : {
182 0 : int retval = -EINVAL;
183 :
184 0 : switch (option) {
185 : case 1:
186 0 : retval = fs_index((const char __user *) arg1);
187 0 : break;
188 :
189 : case 2:
190 0 : retval = fs_name(arg1, (char __user *) arg2);
191 0 : break;
192 :
193 : case 3:
194 0 : retval = fs_maxindex();
195 0 : break;
196 : }
197 0 : return retval;
198 : }
199 :
200 : int get_filesystem_list(char * buf)
201 5 : {
202 5 : int len = 0;
203 5 : struct file_system_type * tmp;
204 :
205 5 : read_lock(&file_systems_lock);
206 5 : tmp = file_systems;
207 5 : while (tmp && len < PAGE_SIZE - 80) {
208 135 : len += sprintf(buf+len, "%s\t%s\n",
209 : (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
210 : tmp->name);
211 135 : tmp = tmp->next;
212 : }
213 5 : read_unlock(&file_systems_lock);
214 5 : return len;
215 : }
216 :
217 : struct file_system_type *get_fs_type(const char *name)
218 26 : {
219 26 : struct file_system_type *fs;
220 :
221 26 : read_lock(&file_systems_lock);
222 26 : fs = *(find_filesystem(name));
223 26 : if (fs && !try_module_get(fs->owner))
224 0 : fs = NULL;
225 26 : read_unlock(&file_systems_lock);
226 26 : if (!fs && (request_module("%s", name) == 0)) {
227 0 : read_lock(&file_systems_lock);
228 0 : fs = *(find_filesystem(name));
229 0 : if (fs && !try_module_get(fs->owner))
230 0 : fs = NULL;
231 0 : read_unlock(&file_systems_lock);
232 : }
233 26 : return fs;
234 : }
235 :
236 : EXPORT_SYMBOL(get_fs_type);
|