diff options
Diffstat (limited to 'fs/sysfs/mount.c')
-rw-r--r-- | fs/sysfs/mount.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c new file mode 100644 index 0000000..5c805bb --- /dev/null +++ b/fs/sysfs/mount.c @@ -0,0 +1,107 @@ +/* + * mount.c - operations for initializing and mounting sysfs. + */ + +#define DEBUG + +#include <linux/fs.h> +#include <linux/mount.h> +#include <linux/pagemap.h> +#include <linux/init.h> + +#include "sysfs.h" + +/* Random magic number */ +#define SYSFS_MAGIC 0x62656572 + +struct vfsmount *sysfs_mount; +struct super_block * sysfs_sb = NULL; +kmem_cache_t *sysfs_dir_cachep; + +static struct super_operations sysfs_ops = { + .statfs = simple_statfs, + .drop_inode = generic_delete_inode, +}; + +static struct sysfs_dirent sysfs_root = { + .s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling), + .s_children = LIST_HEAD_INIT(sysfs_root.s_children), + .s_element = NULL, + .s_type = SYSFS_ROOT, +}; + +static int sysfs_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *inode; + struct dentry *root; + + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; + sb->s_magic = SYSFS_MAGIC; + sb->s_op = &sysfs_ops; + sb->s_time_gran = 1; + sysfs_sb = sb; + + inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); + if (inode) { + inode->i_op = &sysfs_dir_inode_operations; + inode->i_fop = &sysfs_dir_operations; + /* directory inodes start off with i_nlink == 2 (for "." entry) */ + inode->i_nlink++; + } else { + pr_debug("sysfs: could not get root inode\n"); + return -ENOMEM; + } + + root = d_alloc_root(inode); + if (!root) { + pr_debug("%s: could not get root dentry!\n",__FUNCTION__); + iput(inode); + return -ENOMEM; + } + root->d_fsdata = &sysfs_root; + sb->s_root = root; + return 0; +} + +static struct super_block *sysfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) +{ + return get_sb_single(fs_type, flags, data, sysfs_fill_super); +} + +static struct file_system_type sysfs_fs_type = { + .name = "sysfs", + .get_sb = sysfs_get_sb, + .kill_sb = kill_litter_super, +}; + +int __init sysfs_init(void) +{ + int err = -ENOMEM; + + sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache", + sizeof(struct sysfs_dirent), + 0, 0, NULL, NULL); + if (!sysfs_dir_cachep) + goto out; + + err = register_filesystem(&sysfs_fs_type); + if (!err) { + sysfs_mount = kern_mount(&sysfs_fs_type); + if (IS_ERR(sysfs_mount)) { + printk(KERN_ERR "sysfs: could not mount!\n"); + err = PTR_ERR(sysfs_mount); + sysfs_mount = NULL; + unregister_filesystem(&sysfs_fs_type); + goto out_err; + } + } else + goto out_err; +out: + return err; +out_err: + kmem_cache_destroy(sysfs_dir_cachep); + sysfs_dir_cachep = NULL; + goto out; +} |