]> git.hungrycats.org Git - linux/commitdiff
sysfs: Register filesystems with sysfs.
authorPatrick Mochel <mochel@osdl.org>
Tue, 4 Mar 2003 06:13:14 +0000 (00:13 -0600)
committerPatrick Mochel <mochel@osdl.org>
Tue, 4 Mar 2003 06:13:14 +0000 (00:13 -0600)
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

fs/filesystems.c
fs/namespace.c
include/linux/fs.h

index 824b04137c3a59e6d301df2f7f598e339da7a7e3..72ec9ee219788b86f37be71e36bdf21202bf01ba 100644 (file)
@@ -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)
index 3bbf98e4b460cd66fdfd2e899477ecf36433de7e..2d8e6cfabdbd30225aa6a9f070e8e899114c4b6f 100644 (file)
@@ -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();
 }
index 51d5ab2c19a5251af778bc39e3ecb388c6578878..a0fb7a7fe440306affc2a06c0b3e9f726e2f4196 100644 (file)
@@ -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 *);