cregit-Linux how code gets into the kernel

Release 4.15 fs/filesystems.c

Directory: fs
// SPDX-License-Identifier: GPL-2.0
/*
 *  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 <linux/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 */

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

Contributors

PersonTokensPropCommitsCommitProp
Al Viro1359.09%125.00%
David Howells627.27%125.00%
Rusty Russell313.64%250.00%
Total22100.00%4100.00%


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

Contributors

PersonTokensPropCommitsCommitProp
Al Viro1694.12%150.00%
Rusty 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 Viro6281.58%266.67%
Miklos 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 Viro7178.89%150.00%
Miklos 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 Mochel5562.50%133.33%
Al Viro3034.09%133.33%
Milton D. Miller II33.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 Viro11695.87%133.33%
Jeff Layton43.31%133.33%
Linus 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 Viro11398.26%133.33%
Linus Torvalds10.87%133.33%
Christoph Hellwig10.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 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 Viro8398.81%150.00%
Tetsuo 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 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 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 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 Viro5382.81%125.00%
Li Zefan812.50%125.00%
Miklos Szeredi23.12%125.00%
Christoph 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); WARN_ONCE(!fs, "request_module fs-%.*s succeeded, but still no fs?\n", len, name); } if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) { put_filesystem(fs); fs = NULL; } return fs; }

Contributors

PersonTokensPropCommitsCommitProp
Li Zefan5141.80%120.00%
Miklos Szeredi3024.59%120.00%
Al Viro2621.31%120.00%
Luis R. Rodriguez1411.48%120.00%
Eric W. Biedermann10.82%120.00%
Total122100.00%5100.00%

EXPORT_SYMBOL(get_fs_type);

Overall Contributors

PersonTokensPropCommitsCommitProp
Al Viro71862.06%311.11%
Alexey Dobriyan16814.52%13.70%
Miklos Szeredi655.62%13.70%
Li Zefan595.10%13.70%
Patrick Mochel574.93%27.41%
Heiko Carstens161.38%13.70%
Arnaldo Carvalho de Melo151.30%13.70%
Luis R. Rodriguez141.21%13.70%
David Howells60.52%13.70%
Linus Torvalds60.52%311.11%
Fabian Frederick50.43%13.70%
Rusty Russell40.35%27.41%
Jeff Layton40.35%13.70%
Tejun Heo40.35%13.70%
Thomas Gleixner40.35%13.70%
Christoph Hellwig30.26%13.70%
Milton D. Miller II30.26%13.70%
Arnd Bergmann30.26%13.70%
Greg Kroah-Hartman10.09%13.70%
Eric W. Biedermann10.09%13.70%
Tetsuo Handa10.09%13.70%
Total1157100.00%27100.00%
Directory: fs
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.