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> 325a0e3ad6STejun Heo #include <linux/slab.h> 337063fbf2SJoel Becker 347063fbf2SJoel Becker #include <linux/configfs.h> 357063fbf2SJoel Becker #include "configfs_internal.h" 367063fbf2SJoel Becker 377063fbf2SJoel Becker /* Random magic number */ 387063fbf2SJoel Becker #define CONFIGFS_MAGIC 0x62656570 397063fbf2SJoel Becker 407063fbf2SJoel Becker struct vfsmount * configfs_mount = NULL; 417063fbf2SJoel Becker struct super_block * configfs_sb = NULL; 42e18b890bSChristoph Lameter struct kmem_cache *configfs_dir_cachep; 437063fbf2SJoel Becker static int configfs_mnt_count = 0; 447063fbf2SJoel Becker 45ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations configfs_ops = { 467063fbf2SJoel Becker .statfs = simple_statfs, 477063fbf2SJoel Becker .drop_inode = generic_delete_inode, 487063fbf2SJoel Becker }; 497063fbf2SJoel Becker 507063fbf2SJoel Becker static struct config_group configfs_root_group = { 517063fbf2SJoel Becker .cg_item = { 527063fbf2SJoel Becker .ci_namebuf = "root", 537063fbf2SJoel Becker .ci_name = configfs_root_group.cg_item.ci_namebuf, 547063fbf2SJoel Becker }, 557063fbf2SJoel Becker }; 567063fbf2SJoel Becker 577063fbf2SJoel Becker int configfs_is_root(struct config_item *item) 587063fbf2SJoel Becker { 597063fbf2SJoel Becker return item == &configfs_root_group.cg_item; 607063fbf2SJoel Becker } 617063fbf2SJoel Becker 627063fbf2SJoel Becker static struct configfs_dirent configfs_root = { 637063fbf2SJoel Becker .s_sibling = LIST_HEAD_INIT(configfs_root.s_sibling), 647063fbf2SJoel Becker .s_children = LIST_HEAD_INIT(configfs_root.s_children), 657063fbf2SJoel Becker .s_element = &configfs_root_group.cg_item, 667063fbf2SJoel Becker .s_type = CONFIGFS_ROOT, 673d0f89bbSJoel Becker .s_iattr = NULL, 687063fbf2SJoel Becker }; 697063fbf2SJoel Becker 707063fbf2SJoel Becker static int configfs_fill_super(struct super_block *sb, void *data, int silent) 717063fbf2SJoel Becker { 727063fbf2SJoel Becker struct inode *inode; 737063fbf2SJoel Becker struct dentry *root; 747063fbf2SJoel Becker 757063fbf2SJoel Becker sb->s_blocksize = PAGE_CACHE_SIZE; 767063fbf2SJoel Becker sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 777063fbf2SJoel Becker sb->s_magic = CONFIGFS_MAGIC; 787063fbf2SJoel Becker sb->s_op = &configfs_ops; 793d0f89bbSJoel Becker sb->s_time_gran = 1; 807063fbf2SJoel Becker configfs_sb = sb; 817063fbf2SJoel Becker 823d0f89bbSJoel Becker inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, 833d0f89bbSJoel Becker &configfs_root); 847063fbf2SJoel Becker if (inode) { 857063fbf2SJoel Becker inode->i_op = &configfs_dir_inode_operations; 867063fbf2SJoel Becker inode->i_fop = &configfs_dir_operations; 877063fbf2SJoel Becker /* directory inodes start off with i_nlink == 2 (for "." entry) */ 88d8c76e6fSDave Hansen inc_nlink(inode); 897063fbf2SJoel Becker } else { 907063fbf2SJoel Becker pr_debug("configfs: could not get root inode\n"); 917063fbf2SJoel Becker return -ENOMEM; 927063fbf2SJoel Becker } 937063fbf2SJoel Becker 947063fbf2SJoel Becker root = d_alloc_root(inode); 957063fbf2SJoel Becker if (!root) { 968e24eea7SHarvey Harrison pr_debug("%s: could not get root dentry!\n",__func__); 977063fbf2SJoel Becker iput(inode); 987063fbf2SJoel Becker return -ENOMEM; 997063fbf2SJoel Becker } 1007063fbf2SJoel Becker config_group_init(&configfs_root_group); 1017063fbf2SJoel Becker configfs_root_group.cg_item.ci_dentry = root; 1027063fbf2SJoel Becker root->d_fsdata = &configfs_root; 1037063fbf2SJoel Becker sb->s_root = root; 104d463a0c4SAl Viro sb->s_d_op = &configfs_dentry_ops; /* the rest get that */ 1057063fbf2SJoel Becker return 0; 1067063fbf2SJoel Becker } 1077063fbf2SJoel Becker 108fc14f2feSAl Viro static struct dentry *configfs_do_mount(struct file_system_type *fs_type, 109fc14f2feSAl Viro int flags, const char *dev_name, void *data) 1107063fbf2SJoel Becker { 111fc14f2feSAl Viro return mount_single(fs_type, flags, data, configfs_fill_super); 1127063fbf2SJoel Becker } 1137063fbf2SJoel Becker 1147063fbf2SJoel Becker static struct file_system_type configfs_fs_type = { 1157063fbf2SJoel Becker .owner = THIS_MODULE, 1167063fbf2SJoel Becker .name = "configfs", 117fc14f2feSAl Viro .mount = configfs_do_mount, 1187063fbf2SJoel Becker .kill_sb = kill_litter_super, 1197063fbf2SJoel Becker }; 1207063fbf2SJoel Becker 1217063fbf2SJoel Becker int configfs_pin_fs(void) 1227063fbf2SJoel Becker { 1231f5ce9e9STrond Myklebust return simple_pin_fs(&configfs_fs_type, &configfs_mount, 1247063fbf2SJoel Becker &configfs_mnt_count); 1257063fbf2SJoel Becker } 1267063fbf2SJoel Becker 1277063fbf2SJoel Becker void configfs_release_fs(void) 1287063fbf2SJoel Becker { 1297063fbf2SJoel Becker simple_release_fs(&configfs_mount, &configfs_mnt_count); 1307063fbf2SJoel Becker } 1317063fbf2SJoel Becker 1327063fbf2SJoel Becker 1333794491dSGreg Kroah-Hartman static struct kobject *config_kobj; 1347063fbf2SJoel Becker 1357063fbf2SJoel Becker static int __init configfs_init(void) 1367063fbf2SJoel Becker { 1373d0f89bbSJoel Becker int err = -ENOMEM; 1383d0f89bbSJoel Becker 1393d0f89bbSJoel Becker configfs_dir_cachep = kmem_cache_create("configfs_dir_cache", 1403d0f89bbSJoel Becker sizeof(struct configfs_dirent), 14120c2df83SPaul Mundt 0, 0, NULL); 1423d0f89bbSJoel Becker if (!configfs_dir_cachep) 1433d0f89bbSJoel Becker goto out; 1447063fbf2SJoel Becker 1450ff21e46SGreg Kroah-Hartman config_kobj = kobject_create_and_add("config", kernel_kobj); 1463794491dSGreg Kroah-Hartman if (!config_kobj) { 1473d0f89bbSJoel Becker kmem_cache_destroy(configfs_dir_cachep); 1483d0f89bbSJoel Becker configfs_dir_cachep = NULL; 1493d0f89bbSJoel Becker goto out; 1503d0f89bbSJoel Becker } 1517063fbf2SJoel Becker 1527063fbf2SJoel Becker err = register_filesystem(&configfs_fs_type); 1537063fbf2SJoel Becker if (err) { 1547063fbf2SJoel Becker printk(KERN_ERR "configfs: Unable to register filesystem!\n"); 155197b12d6SGreg Kroah-Hartman kobject_put(config_kobj); 1563d0f89bbSJoel Becker kmem_cache_destroy(configfs_dir_cachep); 1573d0f89bbSJoel Becker configfs_dir_cachep = NULL; 158e0bf68ddSPeter Zijlstra goto out; 1597063fbf2SJoel Becker } 1607063fbf2SJoel Becker 161e0bf68ddSPeter Zijlstra err = configfs_inode_init(); 162e0bf68ddSPeter Zijlstra if (err) { 163e0bf68ddSPeter Zijlstra unregister_filesystem(&configfs_fs_type); 164197b12d6SGreg Kroah-Hartman kobject_put(config_kobj); 165e0bf68ddSPeter Zijlstra kmem_cache_destroy(configfs_dir_cachep); 166e0bf68ddSPeter Zijlstra configfs_dir_cachep = NULL; 167e0bf68ddSPeter Zijlstra } 1683d0f89bbSJoel Becker out: 1697063fbf2SJoel Becker return err; 1707063fbf2SJoel Becker } 1717063fbf2SJoel Becker 1727063fbf2SJoel Becker static void __exit configfs_exit(void) 1737063fbf2SJoel Becker { 1747063fbf2SJoel Becker unregister_filesystem(&configfs_fs_type); 175197b12d6SGreg Kroah-Hartman kobject_put(config_kobj); 1763d0f89bbSJoel Becker kmem_cache_destroy(configfs_dir_cachep); 1773d0f89bbSJoel Becker configfs_dir_cachep = NULL; 178e0bf68ddSPeter Zijlstra configfs_inode_exit(); 1797063fbf2SJoel Becker } 1807063fbf2SJoel Becker 1817063fbf2SJoel Becker MODULE_AUTHOR("Oracle"); 1827063fbf2SJoel Becker MODULE_LICENSE("GPL"); 1833d0f89bbSJoel Becker MODULE_VERSION("0.0.2"); 1847063fbf2SJoel Becker MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration."); 1857063fbf2SJoel Becker 1867063fbf2SJoel Becker module_init(configfs_init); 1877063fbf2SJoel Becker module_exit(configfs_exit); 188