Contents of /alx-src/tags/kernel26-2.6.12-alx-r9/fs/filesystems.c
Parent Directory | Revision Log
Revision 630 -
(show annotations)
(download)
Wed Mar 4 11:03:09 2009 UTC (15 years, 3 months ago) by niro
File MIME type: text/plain
File size: 5320 byte(s)
Wed Mar 4 11:03:09 2009 UTC (15 years, 3 months ago) by niro
File MIME type: text/plain
File size: 5320 byte(s)
Tag kernel26-2.6.12-alx-r9
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 | { |
36 | __module_get(fs->owner); |
37 | } |
38 | |
39 | void put_filesystem(struct file_system_type *fs) |
40 | { |
41 | module_put(fs->owner); |
42 | } |
43 | |
44 | static struct file_system_type **find_filesystem(const char *name) |
45 | { |
46 | struct file_system_type **p; |
47 | for (p=&file_systems; *p; p=&(*p)->next) |
48 | if (strcmp((*p)->name,name) == 0) |
49 | break; |
50 | 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 | { |
68 | int res = 0; |
69 | struct file_system_type ** p; |
70 | |
71 | if (!fs) |
72 | return -EINVAL; |
73 | if (fs->next) |
74 | return -EBUSY; |
75 | INIT_LIST_HEAD(&fs->fs_supers); |
76 | write_lock(&file_systems_lock); |
77 | p = find_filesystem(fs->name); |
78 | if (*p) |
79 | res = -EBUSY; |
80 | else |
81 | *p = fs; |
82 | write_unlock(&file_systems_lock); |
83 | 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 | { |
102 | struct file_system_type ** tmp; |
103 | |
104 | write_lock(&file_systems_lock); |
105 | tmp = &file_systems; |
106 | while (*tmp) { |
107 | if (fs == *tmp) { |
108 | *tmp = fs->next; |
109 | fs->next = NULL; |
110 | write_unlock(&file_systems_lock); |
111 | return 0; |
112 | } |
113 | tmp = &(*tmp)->next; |
114 | } |
115 | write_unlock(&file_systems_lock); |
116 | return -EINVAL; |
117 | } |
118 | |
119 | EXPORT_SYMBOL(unregister_filesystem); |
120 | |
121 | static int fs_index(const char __user * __name) |
122 | { |
123 | struct file_system_type * tmp; |
124 | char * name; |
125 | int err, index; |
126 | |
127 | name = getname(__name); |
128 | err = PTR_ERR(name); |
129 | if (IS_ERR(name)) |
130 | return err; |
131 | |
132 | err = -EINVAL; |
133 | read_lock(&file_systems_lock); |
134 | for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) { |
135 | if (strcmp(tmp->name,name) == 0) { |
136 | err = index; |
137 | break; |
138 | } |
139 | } |
140 | read_unlock(&file_systems_lock); |
141 | putname(name); |
142 | return err; |
143 | } |
144 | |
145 | static int fs_name(unsigned int index, char __user * buf) |
146 | { |
147 | struct file_system_type * tmp; |
148 | int len, res; |
149 | |
150 | read_lock(&file_systems_lock); |
151 | for (tmp = file_systems; tmp; tmp = tmp->next, index--) |
152 | if (index <= 0 && try_module_get(tmp->owner)) |
153 | break; |
154 | read_unlock(&file_systems_lock); |
155 | if (!tmp) |
156 | return -EINVAL; |
157 | |
158 | /* OK, we got the reference, so we can safely block */ |
159 | len = strlen(tmp->name) + 1; |
160 | res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0; |
161 | put_filesystem(tmp); |
162 | return res; |
163 | } |
164 | |
165 | static int fs_maxindex(void) |
166 | { |
167 | struct file_system_type * tmp; |
168 | int index; |
169 | |
170 | read_lock(&file_systems_lock); |
171 | for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++) |
172 | ; |
173 | read_unlock(&file_systems_lock); |
174 | 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 | { |
182 | int retval = -EINVAL; |
183 | |
184 | switch (option) { |
185 | case 1: |
186 | retval = fs_index((const char __user *) arg1); |
187 | break; |
188 | |
189 | case 2: |
190 | retval = fs_name(arg1, (char __user *) arg2); |
191 | break; |
192 | |
193 | case 3: |
194 | retval = fs_maxindex(); |
195 | break; |
196 | } |
197 | return retval; |
198 | } |
199 | |
200 | int get_filesystem_list(char * buf) |
201 | { |
202 | int len = 0; |
203 | struct file_system_type * tmp; |
204 | |
205 | read_lock(&file_systems_lock); |
206 | tmp = file_systems; |
207 | while (tmp && len < PAGE_SIZE - 80) { |
208 | len += sprintf(buf+len, "%s\t%s\n", |
209 | (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev", |
210 | tmp->name); |
211 | tmp = tmp->next; |
212 | } |
213 | read_unlock(&file_systems_lock); |
214 | return len; |
215 | } |
216 | |
217 | struct file_system_type *get_fs_type(const char *name) |
218 | { |
219 | struct file_system_type *fs; |
220 | |
221 | read_lock(&file_systems_lock); |
222 | fs = *(find_filesystem(name)); |
223 | if (fs && !try_module_get(fs->owner)) |
224 | fs = NULL; |
225 | read_unlock(&file_systems_lock); |
226 | if (!fs && (request_module("%s", name) == 0)) { |
227 | read_lock(&file_systems_lock); |
228 | fs = *(find_filesystem(name)); |
229 | if (fs && !try_module_get(fs->owner)) |
230 | fs = NULL; |
231 | read_unlock(&file_systems_lock); |
232 | } |
233 | return fs; |
234 | } |
235 | |
236 | EXPORT_SYMBOL(get_fs_type); |