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