17063fbf2SJoel Becker /* -*- mode: c; c-basic-offset: 8; -*- 27063fbf2SJoel Becker * vim: noexpandtab sw=8 ts=8 sts=0: 37063fbf2SJoel Becker * 47063fbf2SJoel Becker * mount.c - operations for initializing and mounting configfs. 57063fbf2SJoel Becker * 67063fbf2SJoel Becker * This program is free software; you can redistribute it and/or 77063fbf2SJoel Becker * modify it under the terms of the GNU General Public 87063fbf2SJoel Becker * License as published by the Free Software Foundation; either 97063fbf2SJoel Becker * version 2 of the License, or (at your option) any later version. 107063fbf2SJoel Becker * 117063fbf2SJoel Becker * This program is distributed in the hope that it will be useful, 127063fbf2SJoel Becker * but WITHOUT ANY WARRANTY; without even the implied warranty of 137063fbf2SJoel Becker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 147063fbf2SJoel Becker * General Public License for more details. 157063fbf2SJoel Becker * 167063fbf2SJoel Becker * You should have received a copy of the GNU General Public 177063fbf2SJoel Becker * License along with this program; if not, write to the 187063fbf2SJoel Becker * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 197063fbf2SJoel Becker * Boston, MA 021110-1307, USA. 207063fbf2SJoel Becker * 217063fbf2SJoel Becker * Based on sysfs: 227063fbf2SJoel Becker * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 237063fbf2SJoel Becker * 247063fbf2SJoel Becker * configfs Copyright (C) 2005 Oracle. All rights reserved. 257063fbf2SJoel Becker */ 267063fbf2SJoel Becker 277063fbf2SJoel Becker #include <linux/fs.h> 287063fbf2SJoel Becker #include <linux/module.h> 297063fbf2SJoel Becker #include <linux/mount.h> 307063fbf2SJoel Becker #include <linux/pagemap.h> 317063fbf2SJoel Becker #include <linux/init.h> 327063fbf2SJoel Becker 337063fbf2SJoel Becker #include <linux/configfs.h> 347063fbf2SJoel Becker #include "configfs_internal.h" 357063fbf2SJoel Becker 367063fbf2SJoel Becker /* Random magic number */ 377063fbf2SJoel Becker #define CONFIGFS_MAGIC 0x62656570 387063fbf2SJoel Becker 397063fbf2SJoel Becker struct vfsmount * configfs_mount = NULL; 407063fbf2SJoel Becker struct super_block * configfs_sb = NULL; 413d0f89bbSJoel Becker kmem_cache_t *configfs_dir_cachep; 427063fbf2SJoel Becker static int configfs_mnt_count = 0; 437063fbf2SJoel Becker 447063fbf2SJoel Becker static struct super_operations configfs_ops = { 457063fbf2SJoel Becker .statfs = simple_statfs, 467063fbf2SJoel Becker .drop_inode = generic_delete_inode, 477063fbf2SJoel Becker }; 487063fbf2SJoel Becker 497063fbf2SJoel Becker static struct config_group configfs_root_group = { 507063fbf2SJoel Becker .cg_item = { 517063fbf2SJoel Becker .ci_namebuf = "root", 527063fbf2SJoel Becker .ci_name = configfs_root_group.cg_item.ci_namebuf, 537063fbf2SJoel Becker }, 547063fbf2SJoel Becker }; 557063fbf2SJoel Becker 567063fbf2SJoel Becker int configfs_is_root(struct config_item *item) 577063fbf2SJoel Becker { 587063fbf2SJoel Becker return item == &configfs_root_group.cg_item; 597063fbf2SJoel Becker } 607063fbf2SJoel Becker 617063fbf2SJoel Becker static struct configfs_dirent configfs_root = { 627063fbf2SJoel Becker .s_sibling = LIST_HEAD_INIT(configfs_root.s_sibling), 637063fbf2SJoel Becker .s_children = LIST_HEAD_INIT(configfs_root.s_children), 647063fbf2SJoel Becker .s_element = &configfs_root_group.cg_item, 657063fbf2SJoel Becker .s_type = CONFIGFS_ROOT, 663d0f89bbSJoel Becker .s_iattr = NULL, 677063fbf2SJoel Becker }; 687063fbf2SJoel Becker 697063fbf2SJoel Becker static int configfs_fill_super(struct super_block *sb, void *data, int silent) 707063fbf2SJoel Becker { 717063fbf2SJoel Becker struct inode *inode; 727063fbf2SJoel Becker struct dentry *root; 737063fbf2SJoel Becker 747063fbf2SJoel Becker sb->s_blocksize = PAGE_CACHE_SIZE; 757063fbf2SJoel Becker sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 767063fbf2SJoel Becker sb->s_magic = CONFIGFS_MAGIC; 777063fbf2SJoel Becker sb->s_op = &configfs_ops; 783d0f89bbSJoel Becker sb->s_time_gran = 1; 797063fbf2SJoel Becker configfs_sb = sb; 807063fbf2SJoel Becker 813d0f89bbSJoel Becker inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, 823d0f89bbSJoel Becker &configfs_root); 837063fbf2SJoel Becker if (inode) { 847063fbf2SJoel Becker inode->i_op = &configfs_dir_inode_operations; 857063fbf2SJoel Becker inode->i_fop = &configfs_dir_operations; 867063fbf2SJoel Becker /* directory inodes start off with i_nlink == 2 (for "." entry) */ 877063fbf2SJoel Becker inode->i_nlink++; 887063fbf2SJoel Becker } else { 897063fbf2SJoel Becker pr_debug("configfs: could not get root inode\n"); 907063fbf2SJoel Becker return -ENOMEM; 917063fbf2SJoel Becker } 927063fbf2SJoel Becker 937063fbf2SJoel Becker root = d_alloc_root(inode); 947063fbf2SJoel Becker if (!root) { 957063fbf2SJoel Becker pr_debug("%s: could not get root dentry!\n",__FUNCTION__); 967063fbf2SJoel Becker iput(inode); 977063fbf2SJoel Becker return -ENOMEM; 987063fbf2SJoel Becker } 997063fbf2SJoel Becker config_group_init(&configfs_root_group); 1007063fbf2SJoel Becker configfs_root_group.cg_item.ci_dentry = root; 1017063fbf2SJoel Becker root->d_fsdata = &configfs_root; 1027063fbf2SJoel Becker sb->s_root = root; 1037063fbf2SJoel Becker return 0; 1047063fbf2SJoel Becker } 1057063fbf2SJoel Becker 1067063fbf2SJoel Becker static struct super_block *configfs_get_sb(struct file_system_type *fs_type, 1077063fbf2SJoel Becker int flags, const char *dev_name, void *data) 1087063fbf2SJoel Becker { 1097063fbf2SJoel Becker return get_sb_single(fs_type, flags, data, configfs_fill_super); 1107063fbf2SJoel Becker } 1117063fbf2SJoel Becker 1127063fbf2SJoel Becker static struct file_system_type configfs_fs_type = { 1137063fbf2SJoel Becker .owner = THIS_MODULE, 1147063fbf2SJoel Becker .name = "configfs", 1157063fbf2SJoel Becker .get_sb = configfs_get_sb, 1167063fbf2SJoel Becker .kill_sb = kill_litter_super, 1177063fbf2SJoel Becker }; 1187063fbf2SJoel Becker 1197063fbf2SJoel Becker int configfs_pin_fs(void) 1207063fbf2SJoel Becker { 1217063fbf2SJoel Becker return simple_pin_fs("configfs", &configfs_mount, 1227063fbf2SJoel Becker &configfs_mnt_count); 1237063fbf2SJoel Becker } 1247063fbf2SJoel Becker 1257063fbf2SJoel Becker void configfs_release_fs(void) 1267063fbf2SJoel Becker { 1277063fbf2SJoel Becker simple_release_fs(&configfs_mount, &configfs_mnt_count); 1287063fbf2SJoel Becker } 1297063fbf2SJoel Becker 1307063fbf2SJoel Becker 1317063fbf2SJoel Becker static decl_subsys(config, NULL, NULL); 1327063fbf2SJoel Becker 1337063fbf2SJoel Becker static int __init configfs_init(void) 1347063fbf2SJoel Becker { 1353d0f89bbSJoel Becker int err = -ENOMEM; 1363d0f89bbSJoel Becker 1373d0f89bbSJoel Becker configfs_dir_cachep = kmem_cache_create("configfs_dir_cache", 1383d0f89bbSJoel Becker sizeof(struct configfs_dirent), 1393d0f89bbSJoel Becker 0, 0, NULL, NULL); 1403d0f89bbSJoel Becker if (!configfs_dir_cachep) 1413d0f89bbSJoel Becker goto out; 1427063fbf2SJoel Becker 1437063fbf2SJoel Becker kset_set_kset_s(&config_subsys, kernel_subsys); 1447063fbf2SJoel Becker err = subsystem_register(&config_subsys); 1453d0f89bbSJoel Becker if (err) { 1463d0f89bbSJoel Becker kmem_cache_destroy(configfs_dir_cachep); 1473d0f89bbSJoel Becker configfs_dir_cachep = NULL; 1483d0f89bbSJoel Becker goto out; 1493d0f89bbSJoel Becker } 1507063fbf2SJoel Becker 1517063fbf2SJoel Becker err = register_filesystem(&configfs_fs_type); 1527063fbf2SJoel Becker if (err) { 1537063fbf2SJoel Becker printk(KERN_ERR "configfs: Unable to register filesystem!\n"); 1547063fbf2SJoel Becker subsystem_unregister(&config_subsys); 1553d0f89bbSJoel Becker kmem_cache_destroy(configfs_dir_cachep); 1563d0f89bbSJoel Becker configfs_dir_cachep = NULL; 1577063fbf2SJoel Becker } 1587063fbf2SJoel Becker 1593d0f89bbSJoel Becker out: 1607063fbf2SJoel Becker return err; 1617063fbf2SJoel Becker } 1627063fbf2SJoel Becker 1637063fbf2SJoel Becker static void __exit configfs_exit(void) 1647063fbf2SJoel Becker { 1657063fbf2SJoel Becker unregister_filesystem(&configfs_fs_type); 1667063fbf2SJoel Becker subsystem_unregister(&config_subsys); 1673d0f89bbSJoel Becker kmem_cache_destroy(configfs_dir_cachep); 1683d0f89bbSJoel Becker configfs_dir_cachep = NULL; 1697063fbf2SJoel Becker } 1707063fbf2SJoel Becker 1717063fbf2SJoel Becker MODULE_AUTHOR("Oracle"); 1727063fbf2SJoel Becker MODULE_LICENSE("GPL"); 1733d0f89bbSJoel Becker MODULE_VERSION("0.0.2"); 1747063fbf2SJoel Becker MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration."); 1757063fbf2SJoel Becker 1767063fbf2SJoel Becker module_init(configfs_init); 1777063fbf2SJoel Becker module_exit(configfs_exit); 178