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