mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
This commit is contained in:
236
fs/filesystems.c
Normal file
236
fs/filesystems.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* linux/fs/filesystems.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*
|
||||
* table of configured filesystems
|
||||
*/
|
||||
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.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);
|
||||
}
|
||||
|
||||
void put_filesystem(struct file_system_type *fs)
|
||||
{
|
||||
module_put(fs->owner);
|
||||
}
|
||||
|
||||
static struct file_system_type **find_filesystem(const char *name)
|
||||
{
|
||||
struct file_system_type **p;
|
||||
for (p=&file_systems; *p; p=&(*p)->next)
|
||||
if (strcmp((*p)->name,name) == 0)
|
||||
break;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
if (!fs)
|
||||
return -EINVAL;
|
||||
if (fs->next)
|
||||
return -EBUSY;
|
||||
INIT_LIST_HEAD(&fs->fs_supers);
|
||||
write_lock(&file_systems_lock);
|
||||
p = find_filesystem(fs->name);
|
||||
if (*p)
|
||||
res = -EBUSY;
|
||||
else
|
||||
*p = fs;
|
||||
write_unlock(&file_systems_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
tmp = &(*tmp)->next;
|
||||
}
|
||||
write_unlock(&file_systems_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(unregister_filesystem);
|
||||
|
||||
static int fs_index(const char __user * __name)
|
||||
{
|
||||
struct file_system_type * tmp;
|
||||
char * 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) == 0) {
|
||||
err = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_unlock(&file_systems_lock);
|
||||
putname(name);
|
||||
return err;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Whee.. Weird sysv syscall.
|
||||
*/
|
||||
asmlinkage long sys_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;
|
||||
}
|
||||
|
||||
int 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;
|
||||
}
|
||||
|
||||
struct file_system_type *get_fs_type(const char *name)
|
||||
{
|
||||
struct file_system_type *fs;
|
||||
|
||||
read_lock(&file_systems_lock);
|
||||
fs = *(find_filesystem(name));
|
||||
if (fs && !try_module_get(fs->owner))
|
||||
fs = NULL;
|
||||
read_unlock(&file_systems_lock);
|
||||
if (!fs && (request_module("%s", name) == 0)) {
|
||||
read_lock(&file_systems_lock);
|
||||
fs = *(find_filesystem(name));
|
||||
if (fs && !try_module_get(fs->owner))
|
||||
fs = NULL;
|
||||
read_unlock(&file_systems_lock);
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(get_fs_type);
|
Reference in New Issue
Block a user