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 402a152ad3SAl Viro static struct vfsmount *configfs_mount = NULL; 41e18b890bSChristoph Lameter struct kmem_cache *configfs_dir_cachep; 427063fbf2SJoel Becker static int configfs_mnt_count = 0; 437063fbf2SJoel Becker 44ee9b6d61SJosef 'Jeff' Sipek static const 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 803d0f89bbSJoel Becker inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, 81b7c177fcSAl Viro &configfs_root, sb); 827063fbf2SJoel Becker if (inode) { 8381d44ed1SAl Viro inode->i_op = &configfs_root_inode_operations; 847063fbf2SJoel Becker inode->i_fop = &configfs_dir_operations; 857063fbf2SJoel Becker /* directory inodes start off with i_nlink == 2 (for "." entry) */ 86d8c76e6fSDave Hansen inc_nlink(inode); 877063fbf2SJoel Becker } else { 887063fbf2SJoel Becker pr_debug("configfs: could not get root inode\n"); 897063fbf2SJoel Becker return -ENOMEM; 907063fbf2SJoel Becker } 917063fbf2SJoel Becker 9248fde701SAl Viro root = d_make_root(inode); 937063fbf2SJoel Becker if (!root) { 948e24eea7SHarvey Harrison pr_debug("%s: could not get root dentry!\n",__func__); 957063fbf2SJoel Becker return -ENOMEM; 967063fbf2SJoel Becker } 977063fbf2SJoel Becker config_group_init(&configfs_root_group); 987063fbf2SJoel Becker configfs_root_group.cg_item.ci_dentry = root; 997063fbf2SJoel Becker root->d_fsdata = &configfs_root; 1007063fbf2SJoel Becker sb->s_root = root; 101d463a0c4SAl Viro sb->s_d_op = &configfs_dentry_ops; /* the rest get that */ 1027063fbf2SJoel Becker return 0; 1037063fbf2SJoel Becker } 1047063fbf2SJoel Becker 105fc14f2feSAl Viro static struct dentry *configfs_do_mount(struct file_system_type *fs_type, 106fc14f2feSAl Viro int flags, const char *dev_name, void *data) 1077063fbf2SJoel Becker { 108fc14f2feSAl Viro return mount_single(fs_type, flags, data, configfs_fill_super); 1097063fbf2SJoel Becker } 1107063fbf2SJoel Becker 1117063fbf2SJoel Becker static struct file_system_type configfs_fs_type = { 1127063fbf2SJoel Becker .owner = THIS_MODULE, 1137063fbf2SJoel Becker .name = "configfs", 114fc14f2feSAl Viro .mount = configfs_do_mount, 1157063fbf2SJoel Becker .kill_sb = kill_litter_super, 1167063fbf2SJoel Becker }; 1177f78e035SEric W. Biederman MODULE_ALIAS_FS("configfs"); 1187063fbf2SJoel Becker 1192a152ad3SAl Viro struct dentry *configfs_pin_fs(void) 1207063fbf2SJoel Becker { 1212a152ad3SAl Viro int err = simple_pin_fs(&configfs_fs_type, &configfs_mount, 1227063fbf2SJoel Becker &configfs_mnt_count); 1232a152ad3SAl Viro return err ? ERR_PTR(err) : configfs_mount->mnt_root; 1247063fbf2SJoel Becker } 1257063fbf2SJoel Becker 1267063fbf2SJoel Becker void configfs_release_fs(void) 1277063fbf2SJoel Becker { 1287063fbf2SJoel Becker simple_release_fs(&configfs_mount, &configfs_mnt_count); 1297063fbf2SJoel Becker } 1307063fbf2SJoel Becker 1317063fbf2SJoel Becker 1323794491dSGreg Kroah-Hartman static struct kobject *config_kobj; 1337063fbf2SJoel Becker 1347063fbf2SJoel Becker static int __init configfs_init(void) 1357063fbf2SJoel Becker { 1363d0f89bbSJoel Becker int err = -ENOMEM; 1373d0f89bbSJoel Becker 1383d0f89bbSJoel Becker configfs_dir_cachep = kmem_cache_create("configfs_dir_cache", 1393d0f89bbSJoel Becker sizeof(struct configfs_dirent), 14020c2df83SPaul Mundt 0, 0, NULL); 1413d0f89bbSJoel Becker if (!configfs_dir_cachep) 1423d0f89bbSJoel Becker goto out; 1437063fbf2SJoel Becker 1440ff21e46SGreg Kroah-Hartman config_kobj = kobject_create_and_add("config", kernel_kobj); 1457c6455e3SAl Viro if (!config_kobj) 1467c6455e3SAl Viro goto out2; 1477063fbf2SJoel Becker 148e0bf68ddSPeter Zijlstra err = configfs_inode_init(); 1497c6455e3SAl Viro if (err) 1507c6455e3SAl Viro goto out3; 1517c6455e3SAl Viro 1527c6455e3SAl Viro err = register_filesystem(&configfs_fs_type); 1537c6455e3SAl Viro if (err) 1547c6455e3SAl Viro goto out4; 1557c6455e3SAl Viro 1567c6455e3SAl Viro return 0; 1577c6455e3SAl Viro out4: 1587c6455e3SAl Viro printk(KERN_ERR "configfs: Unable to register filesystem!\n"); 1597c6455e3SAl Viro configfs_inode_exit(); 1607c6455e3SAl Viro out3: 161197b12d6SGreg Kroah-Hartman kobject_put(config_kobj); 1627c6455e3SAl Viro out2: 163e0bf68ddSPeter Zijlstra kmem_cache_destroy(configfs_dir_cachep); 164e0bf68ddSPeter Zijlstra configfs_dir_cachep = NULL; 1653d0f89bbSJoel Becker out: 1667063fbf2SJoel Becker return err; 1677063fbf2SJoel Becker } 1687063fbf2SJoel Becker 1697063fbf2SJoel Becker static void __exit configfs_exit(void) 1707063fbf2SJoel Becker { 1717063fbf2SJoel Becker unregister_filesystem(&configfs_fs_type); 172197b12d6SGreg Kroah-Hartman kobject_put(config_kobj); 1733d0f89bbSJoel Becker kmem_cache_destroy(configfs_dir_cachep); 1743d0f89bbSJoel Becker configfs_dir_cachep = NULL; 175e0bf68ddSPeter Zijlstra configfs_inode_exit(); 1767063fbf2SJoel Becker } 1777063fbf2SJoel Becker 1787063fbf2SJoel Becker MODULE_AUTHOR("Oracle"); 1797063fbf2SJoel Becker MODULE_LICENSE("GPL"); 1803d0f89bbSJoel Becker MODULE_VERSION("0.0.2"); 1817063fbf2SJoel Becker MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration."); 1827063fbf2SJoel Becker 1837063fbf2SJoel Becker module_init(configfs_init); 1847063fbf2SJoel Becker module_exit(configfs_exit); 185