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 @@ ...@@ -9,6 +9,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -58,6 +59,38 @@ static struct file_system_type **find_filesystem(const char *name) ...@@ -58,6 +59,38 @@ static struct file_system_type **find_filesystem(const char *name)
return p; 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 * register_filesystem - register a new filesystem
* @fs: the file system structure * @fs: the file system structure
...@@ -88,6 +121,14 @@ int register_filesystem(struct file_system_type * fs) ...@@ -88,6 +121,14 @@ int register_filesystem(struct file_system_type * fs)
else else
*p = fs; *p = fs;
write_unlock(&file_systems_lock); 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; return res;
} }
...@@ -105,21 +146,44 @@ int register_filesystem(struct file_system_type * fs) ...@@ -105,21 +146,44 @@ int register_filesystem(struct file_system_type * fs)
int unregister_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); res = unlink_fs(fs);
tmp = &file_systems; if (!res)
while (*tmp) { subsystem_unregister(&fs->subsys);
if (fs == *tmp) { return res;
*tmp = fs->next; }
fs->next = NULL;
write_unlock(&file_systems_lock); extern int sysfs_init(void);
return 0;
} /**
tmp = &(*tmp)->next; * fs_subsys_init - initialize sysfs and fs subsystem.
} *
write_unlock(&file_systems_lock); * In order to register filesystems in sysfs, it has to be
return -EINVAL; * 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) static int fs_index(const char * __name)
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); 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 do_remount_sb(struct super_block *sb, int flags, void * data);
extern int __init init_rootfs(void); 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 struct list_head *mount_hashtable;
static int hash_mask, hash_bits; static int hash_mask, hash_bits;
...@@ -1133,7 +1133,7 @@ void __init mnt_init(unsigned long mempages) ...@@ -1133,7 +1133,7 @@ void __init mnt_init(unsigned long mempages)
d++; d++;
i--; i--;
} while (i); } while (i);
sysfs_init(); fs_subsys_init();
init_rootfs(); init_rootfs();
init_mount_tree(); init_mount_tree();
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/radix-tree.h> #include <linux/radix-tree.h>
#include <linux/kobject.h>
#include <asm/atomic.h> #include <asm/atomic.h>
struct iovec; struct iovec;
...@@ -610,6 +611,7 @@ struct super_block { ...@@ -610,6 +611,7 @@ struct super_block {
char s_id[32]; /* Informational name */ char s_id[32]; /* Informational name */
struct kobject kobj; /* anchor for sysfs */
void *s_fs_info; /* Filesystem private info */ void *s_fs_info; /* Filesystem private info */
/* /*
...@@ -913,6 +915,7 @@ struct export_operations { ...@@ -913,6 +915,7 @@ struct export_operations {
struct file_system_type { struct file_system_type {
const char *name; const char *name;
struct subsystem subsys;
int fs_flags; int fs_flags;
struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *); struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *);
void (*kill_sb) (struct super_block *); 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