cregit-Linux how code gets into the kernel

Release 4.7 fs/filesystems.c

Directory: fs
/*
 *  linux/fs/filesystems.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  table of configured filesystems
 */

#include <linux/syscalls.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <asm/uaccess.h>

/*
 * 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 */

void get_filesystem(struct file_system_type *fs) { __module_get(fs->owner); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro1482.35%133.33%
rusty russellrusty russell317.65%266.67%
Total17100.00%3100.00%


void put_filesystem(struct file_system_type *fs) { module_put(fs->owner); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro1694.12%150.00%
rusty russellrusty russell15.88%150.00%
Total17100.00%2100.00%


static struct file_system_type **find_filesystem(const char *name, unsigned len) { struct file_system_type **p; for (p = &file_systems; *p; p = &(*p)->next) if (strncmp((*p)->name, name, len) == 0 && !(*p)->name[len]) break; return p; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro6281.58%266.67%
miklos szeredimiklos szeredi1418.42%133.33%
Total76100.00%3100.00%

/** * 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; BUG_ON(strchr(fs->name, '.')); if (fs->next) return -EBUSY; write_lock(&file_systems_lock); p = find_filesystem(fs->name, strlen(fs->name)); if (*p) res = -EBUSY; else *p = fs; write_unlock(&file_systems_lock); return res; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro7178.89%150.00%
miklos szeredimiklos szeredi1921.11%150.00%
Total90100.00%2100.00%

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); synchronize_rcu(); return 0; } tmp = &(*tmp)->next; } write_unlock(&file_systems_lock); return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
patrick mochelpatrick mochel5562.50%133.33%
al viroal viro3034.09%133.33%
milton d. millermilton d. miller33.41%133.33%
Total88100.00%3100.00%

EXPORT_SYMBOL(unregister_filesystem); #ifdef CONFIG_SYSFS_SYSCALL
static int fs_index(const char __user * __name) { struct file_system_type * tmp; struct filename *name; 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++) { if (strcmp(tmp->name, name->name) == 0) { err = index; break; } } read_unlock(&file_systems_lock); putname(name); return err; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro11695.87%133.33%
jeff laytonjeff layton43.31%133.33%
linus torvaldslinus torvalds10.83%133.33%
Total121100.00%3100.00%


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; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro11398.26%133.33%
christoph hellwigchristoph hellwig10.87%133.33%
linus torvaldslinus torvalds10.87%133.33%
Total115100.00%3100.00%


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; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro53100.00%1100.00%
Total53100.00%1100.00%

/* * Whee.. Weird sysv syscall. */ SYSCALL_DEFINE3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2) { 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; } #endif
int __init get_filesystem_list(char *buf) { 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\n", (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev", tmp->name); tmp = tmp->next; } read_unlock(&file_systems_lock); return len; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro8398.81%150.00%
tetsuo handatetsuo handa11.19%150.00%
Total84100.00%2100.00%

#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\n", (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev", tmp->name); tmp = tmp->next; } read_unlock(&file_systems_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
alexey dobriyanalexey dobriyan74100.00%1100.00%
Total74100.00%1100.00%


static int filesystems_proc_open(struct inode *inode, struct file *file) { return single_open(file, filesystems_proc_show, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
alexey dobriyanalexey dobriyan26100.00%1100.00%
Total26100.00%1100.00%

static const struct file_operations filesystems_proc_fops = { .open = filesystems_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, };
static int __init proc_filesystems_init(void) { proc_create("filesystems", 0, NULL, &filesystems_proc_fops); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
alexey dobriyanalexey dobriyan24100.00%1100.00%
Total24100.00%1100.00%

module_init(proc_filesystems_init); #endif
static struct file_system_type *__get_fs_type(const char *name, int len) { struct file_system_type *fs; read_lock(&file_systems_lock); fs = *(find_filesystem(name, len)); if (fs && !try_module_get(fs->owner)) fs = NULL; read_unlock(&file_systems_lock); return fs; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro5382.81%125.00%
li zefanli zefan812.50%125.00%
miklos szeredimiklos szeredi23.12%125.00%
christoph hellwigchristoph hellwig11.56%125.00%
Total64100.00%4100.00%


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); if (!fs && (request_module("fs-%.*s", len, name) == 0)) fs = __get_fs_type(name, len); if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) { put_filesystem(fs); fs = NULL; } return fs; }

Contributors

PersonTokensPropCommitsCommitProp
li zefanli zefan5147.22%125.00%
miklos szeredimiklos szeredi3027.78%125.00%
al viroal viro2624.07%125.00%
eric w. biedermaneric w. biederman10.93%125.00%
Total108100.00%4100.00%

EXPORT_SYMBOL(get_fs_type);

Overall Contributors

PersonTokensPropCommitsCommitProp
al viroal viro72063.32%313.04%
alexey dobriyanalexey dobriyan16814.78%14.35%
miklos szeredimiklos szeredi655.72%14.35%
li zefanli zefan595.19%14.35%
patrick mochelpatrick mochel575.01%28.70%
heiko carstensheiko carstens161.41%14.35%
arnaldo carvalho de meloarnaldo carvalho de melo151.32%14.35%
linus torvaldslinus torvalds50.44%28.70%
fabian frederickfabian frederick50.44%14.35%
tejun heotejun heo40.35%14.35%
thomas gleixnerthomas gleixner40.35%14.35%
rusty russellrusty russell40.35%28.70%
jeff laytonjeff layton40.35%14.35%
milton d. millermilton d. miller30.26%14.35%
christoph hellwigchristoph hellwig30.26%14.35%
arnd bergmannarnd bergmann30.26%14.35%
eric w. biedermaneric w. biederman10.09%14.35%
tetsuo handatetsuo handa10.09%14.35%
Total1137100.00%23100.00%
Directory: fs
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}