Commit 8811d235 authored by Patrick Mochel's avatar Patrick Mochel

sysfs: Register filesystems with sysfs.

Originally from Nikita Danliov. 

- Add struct subsystem to struct file_system_type. 
- Add fs_subsys_init() to explicitly call sysfs_init() very early.
- Register base fs subsystem then, too.
- Register filesystems' embedded subsystem when registered with fs core.

Resulting tree looks like:

# tree /sys/fs/
/sys/fs/
|-- bdev
|-- devpts
|-- eventpollfs
|-- ext2
|-- ext3
|-- futexfs
|-- iso9660
|-- pipefs
|-- proc
|-- ramfs
|-- rootfs
|-- sockfs
|-- sysfs
`-- tmpfs
parent 3795b173
......@@ -9,6 +9,7 @@
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/uaccess.h>
......@@ -58,6 +59,38 @@ static struct file_system_type **find_filesystem(const char *name)
return p;
}
/* define fs_subsys */
static decl_subsys(fs, NULL);
static int register_fs_subsys(struct file_system_type * fs)
{
struct subsystem *sub = &fs->subsys;
snprintf(sub->kset.kobj.name, KOBJ_NAME_LEN, "%s", fs->name);
subsys_set_kset(fs, fs_subsys);
return subsystem_register(sub);
}
static int unlink_fs(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;
}
/**
* register_filesystem - register a new filesystem
* @fs: the file system structure
......@@ -88,6 +121,14 @@ int register_filesystem(struct file_system_type * fs)
else
*p = fs;
write_unlock(&file_systems_lock);
if (!res) {
/* we implicitly possess reference to @fs during registration,
* so it cannot be unregister from under us. */
if (register_fs_subsys(fs))
printk(KERN_WARNING "Failed to register '%s' in sysfs\n",
fs->name);
}
return res;
}
......@@ -105,21 +146,44 @@ int register_filesystem(struct file_system_type * fs)
int unregister_filesystem(struct file_system_type * fs)
{
struct file_system_type ** tmp;
int res;
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;
res = unlink_fs(fs);
if (!res)
subsystem_unregister(&fs->subsys);
return res;
}
extern int sysfs_init(void);
/**
* fs_subsys_init - initialize sysfs and fs subsystem.
*
* In order to register filesystems in sysfs, it has to be
* initialized. Also, we need the base fs filesystem, so the
* registered filesystems have a home.
*
* During sysfs_init(), the registration of sysfs into itself
* will fail, since it's not mounted yet. To make sure that
* sysfs does show up, we re-register sysfs's embedded subsystem,
* which will get added, since sysfs is now mounted.
*/
void __init fs_subsys_init(void)
{
struct file_system_type ** p;
/* make sure sysfs is up and running */
sysfs_init();
/* register fs_subsys */
subsystem_register(&fs_subsys);
p = find_filesystem("sysfs");
if (p)
/* make sure it's registered */
register_fs_subsys(*p);
}
static int fs_index(const char * __name)
......
......@@ -26,7 +26,7 @@
extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
extern int do_remount_sb(struct super_block *sb, int flags, void * data);
extern int __init init_rootfs(void);
extern int __init sysfs_init(void);
extern int __init fs_subsys_init(void);
static struct list_head *mount_hashtable;
static int hash_mask, hash_bits;
......@@ -1133,7 +1133,7 @@ void __init mnt_init(unsigned long mempages)
d++;
i--;
} while (i);
sysfs_init();
fs_subsys_init();
init_rootfs();
init_mount_tree();
}
......@@ -18,6 +18,7 @@
#include <linux/stat.h>
#include <linux/cache.h>
#include <linux/radix-tree.h>
#include <linux/kobject.h>
#include <asm/atomic.h>
struct iovec;
......@@ -610,6 +611,7 @@ struct super_block {
char s_id[32]; /* Informational name */
struct kobject kobj; /* anchor for sysfs */
void *s_fs_info; /* Filesystem private info */
/*
......@@ -913,6 +915,7 @@ struct export_operations {
struct file_system_type {
const char *name;
struct subsystem subsys;
int fs_flags;
struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *);
void (*kill_sb) (struct super_block *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment