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, unsigned len) 45 { 46 struct file_system_type **p; 47 for (p=&file_systems; *p; p=&(*p)->next) 48 if (strlen((*p)->name) == len && 49 strncmp((*p)->name, name, len) == 0) 50 break; 51 return p; 52 } 53 54 /** 55 * register_filesystem - register a new filesystem 56 * @fs: the file system structure 57 * 58 * Adds the file system passed to the list of file systems the kernel 59 * is aware of for mount and other syscalls. Returns 0 on success, 60 * or a negative errno code on an error. 61 * 62 * The &struct file_system_type that is passed is linked into the kernel 63 * structures and must not be freed until the file system has been 64 * unregistered. 65 */ 66 67 int register_filesystem(struct file_system_type * fs) 68 { 69 int res = 0; 70 struct file_system_type ** p; 71 72 BUG_ON(strchr(fs->name, '.')); 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, strlen(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 const char *dot = strchr(name, '.'); 221 unsigned len = dot ? dot - name : strlen(name); 222 223 read_lock(&file_systems_lock); 224 fs = *(find_filesystem(name, len)); 225 if (fs && !try_module_get(fs->owner)) 226 fs = NULL; 227 read_unlock(&file_systems_lock); 228 if (!fs && (request_module("%.*s", len, name) == 0)) { 229 read_lock(&file_systems_lock); 230 fs = *(find_filesystem(name, len)); 231 if (fs && !try_module_get(fs->owner)) 232 fs = NULL; 233 read_unlock(&file_systems_lock); 234 } 235 236 if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) { 237 put_filesystem(fs); 238 fs = NULL; 239 } 240 return fs; 241 } 242 243 EXPORT_SYMBOL(get_fs_type); 244