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