1328970deSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 27063fbf2SJoel Becker /* -*- mode: c; c-basic-offset: 8; -*- 37063fbf2SJoel Becker * vim: noexpandtab sw=8 ts=8 sts=0: 47063fbf2SJoel Becker * 57063fbf2SJoel Becker * mount.c - operations for initializing and mounting configfs. 67063fbf2SJoel Becker * 77063fbf2SJoel Becker * Based on sysfs: 87063fbf2SJoel Becker * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 97063fbf2SJoel Becker * 107063fbf2SJoel Becker * configfs Copyright (C) 2005 Oracle. All rights reserved. 117063fbf2SJoel Becker */ 127063fbf2SJoel Becker 137063fbf2SJoel Becker #include <linux/fs.h> 147063fbf2SJoel Becker #include <linux/module.h> 157063fbf2SJoel Becker #include <linux/mount.h> 166bc62f20SDavid Howells #include <linux/fs_context.h> 177063fbf2SJoel Becker #include <linux/pagemap.h> 187063fbf2SJoel Becker #include <linux/init.h> 195a0e3ad6STejun Heo #include <linux/slab.h> 207063fbf2SJoel Becker 217063fbf2SJoel Becker #include <linux/configfs.h> 227063fbf2SJoel Becker #include "configfs_internal.h" 237063fbf2SJoel Becker 247063fbf2SJoel Becker /* Random magic number */ 257063fbf2SJoel Becker #define CONFIGFS_MAGIC 0x62656570 267063fbf2SJoel Becker 272a152ad3SAl Viro static struct vfsmount *configfs_mount = NULL; 28e18b890bSChristoph Lameter struct kmem_cache *configfs_dir_cachep; 297063fbf2SJoel Becker static int configfs_mnt_count = 0; 307063fbf2SJoel Becker 31e9c03af2SAl Viro 32e9c03af2SAl Viro static void configfs_free_inode(struct inode *inode) 33e9c03af2SAl Viro { 34e9c03af2SAl Viro if (S_ISLNK(inode->i_mode)) 35e9c03af2SAl Viro kfree(inode->i_link); 36e9c03af2SAl Viro free_inode_nonrcu(inode); 37e9c03af2SAl Viro } 38e9c03af2SAl Viro 39ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations configfs_ops = { 407063fbf2SJoel Becker .statfs = simple_statfs, 417063fbf2SJoel Becker .drop_inode = generic_delete_inode, 42e9c03af2SAl Viro .free_inode = configfs_free_inode, 437063fbf2SJoel Becker }; 447063fbf2SJoel Becker 457063fbf2SJoel Becker static struct config_group configfs_root_group = { 467063fbf2SJoel Becker .cg_item = { 477063fbf2SJoel Becker .ci_namebuf = "root", 487063fbf2SJoel Becker .ci_name = configfs_root_group.cg_item.ci_namebuf, 497063fbf2SJoel Becker }, 507063fbf2SJoel Becker }; 517063fbf2SJoel Becker 527063fbf2SJoel Becker int configfs_is_root(struct config_item *item) 537063fbf2SJoel Becker { 547063fbf2SJoel Becker return item == &configfs_root_group.cg_item; 557063fbf2SJoel Becker } 567063fbf2SJoel Becker 577063fbf2SJoel Becker static struct configfs_dirent configfs_root = { 587063fbf2SJoel Becker .s_sibling = LIST_HEAD_INIT(configfs_root.s_sibling), 597063fbf2SJoel Becker .s_children = LIST_HEAD_INIT(configfs_root.s_children), 607063fbf2SJoel Becker .s_element = &configfs_root_group.cg_item, 617063fbf2SJoel Becker .s_type = CONFIGFS_ROOT, 623d0f89bbSJoel Becker .s_iattr = NULL, 637063fbf2SJoel Becker }; 647063fbf2SJoel Becker 656bc62f20SDavid Howells static int configfs_fill_super(struct super_block *sb, struct fs_context *fc) 667063fbf2SJoel Becker { 677063fbf2SJoel Becker struct inode *inode; 687063fbf2SJoel Becker struct dentry *root; 697063fbf2SJoel Becker 7009cbfeafSKirill A. Shutemov sb->s_blocksize = PAGE_SIZE; 7109cbfeafSKirill A. Shutemov sb->s_blocksize_bits = PAGE_SHIFT; 727063fbf2SJoel Becker sb->s_magic = CONFIGFS_MAGIC; 737063fbf2SJoel Becker sb->s_op = &configfs_ops; 743d0f89bbSJoel Becker sb->s_time_gran = 1; 757063fbf2SJoel Becker 763d0f89bbSJoel Becker inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, 77b7c177fcSAl Viro &configfs_root, sb); 787063fbf2SJoel Becker if (inode) { 7981d44ed1SAl Viro inode->i_op = &configfs_root_inode_operations; 807063fbf2SJoel Becker inode->i_fop = &configfs_dir_operations; 817063fbf2SJoel Becker /* directory inodes start off with i_nlink == 2 (for "." entry) */ 82d8c76e6fSDave Hansen inc_nlink(inode); 837063fbf2SJoel Becker } else { 841d88aa44SFabian Frederick pr_debug("could not get root inode\n"); 857063fbf2SJoel Becker return -ENOMEM; 867063fbf2SJoel Becker } 877063fbf2SJoel Becker 8848fde701SAl Viro root = d_make_root(inode); 897063fbf2SJoel Becker if (!root) { 908e24eea7SHarvey Harrison pr_debug("%s: could not get root dentry!\n",__func__); 917063fbf2SJoel Becker return -ENOMEM; 927063fbf2SJoel Becker } 937063fbf2SJoel Becker config_group_init(&configfs_root_group); 947063fbf2SJoel Becker configfs_root_group.cg_item.ci_dentry = root; 957063fbf2SJoel Becker root->d_fsdata = &configfs_root; 967063fbf2SJoel Becker sb->s_root = root; 97d463a0c4SAl Viro sb->s_d_op = &configfs_dentry_ops; /* the rest get that */ 987063fbf2SJoel Becker return 0; 997063fbf2SJoel Becker } 1007063fbf2SJoel Becker 1016bc62f20SDavid Howells static int configfs_get_tree(struct fs_context *fc) 1027063fbf2SJoel Becker { 1036bc62f20SDavid Howells return get_tree_single(fc, configfs_fill_super); 1046bc62f20SDavid Howells } 1056bc62f20SDavid Howells 1066bc62f20SDavid Howells static const struct fs_context_operations configfs_context_ops = { 1076bc62f20SDavid Howells .get_tree = configfs_get_tree, 1086bc62f20SDavid Howells }; 1096bc62f20SDavid Howells 1106bc62f20SDavid Howells static int configfs_init_fs_context(struct fs_context *fc) 1116bc62f20SDavid Howells { 1126bc62f20SDavid Howells fc->ops = &configfs_context_ops; 1136bc62f20SDavid Howells return 0; 1147063fbf2SJoel Becker } 1157063fbf2SJoel Becker 1167063fbf2SJoel Becker static struct file_system_type configfs_fs_type = { 1177063fbf2SJoel Becker .owner = THIS_MODULE, 1187063fbf2SJoel Becker .name = "configfs", 1196bc62f20SDavid Howells .init_fs_context = configfs_init_fs_context, 1207063fbf2SJoel Becker .kill_sb = kill_litter_super, 1217063fbf2SJoel Becker }; 1227f78e035SEric W. Biederman MODULE_ALIAS_FS("configfs"); 1237063fbf2SJoel Becker 1242a152ad3SAl Viro struct dentry *configfs_pin_fs(void) 1257063fbf2SJoel Becker { 1262a152ad3SAl Viro int err = simple_pin_fs(&configfs_fs_type, &configfs_mount, 1277063fbf2SJoel Becker &configfs_mnt_count); 1282a152ad3SAl Viro return err ? ERR_PTR(err) : configfs_mount->mnt_root; 1297063fbf2SJoel Becker } 1307063fbf2SJoel Becker 1317063fbf2SJoel Becker void configfs_release_fs(void) 1327063fbf2SJoel Becker { 1337063fbf2SJoel Becker simple_release_fs(&configfs_mount, &configfs_mnt_count); 1347063fbf2SJoel Becker } 1357063fbf2SJoel Becker 1367063fbf2SJoel Becker 1377063fbf2SJoel Becker static int __init configfs_init(void) 1387063fbf2SJoel Becker { 1393d0f89bbSJoel Becker int err = -ENOMEM; 1403d0f89bbSJoel Becker 1413d0f89bbSJoel Becker configfs_dir_cachep = kmem_cache_create("configfs_dir_cache", 1423d0f89bbSJoel Becker sizeof(struct configfs_dirent), 14320c2df83SPaul Mundt 0, 0, NULL); 1443d0f89bbSJoel Becker if (!configfs_dir_cachep) 1453d0f89bbSJoel Becker goto out; 1467063fbf2SJoel Becker 147f9bb4882SEric W. Biederman err = sysfs_create_mount_point(kernel_kobj, "config"); 148f9bb4882SEric W. Biederman if (err) 1497c6455e3SAl Viro goto out2; 1507063fbf2SJoel Becker 151b4caecd4SChristoph Hellwig err = register_filesystem(&configfs_fs_type); 1527c6455e3SAl Viro if (err) 1537c6455e3SAl Viro goto out3; 1547c6455e3SAl Viro 1557c6455e3SAl Viro return 0; 1567c6455e3SAl Viro out3: 157b4caecd4SChristoph Hellwig pr_err("Unable to register filesystem!\n"); 158f9bb4882SEric W. Biederman sysfs_remove_mount_point(kernel_kobj, "config"); 1597c6455e3SAl Viro out2: 160e0bf68ddSPeter Zijlstra kmem_cache_destroy(configfs_dir_cachep); 161e0bf68ddSPeter Zijlstra configfs_dir_cachep = NULL; 1623d0f89bbSJoel Becker out: 1637063fbf2SJoel Becker return err; 1647063fbf2SJoel Becker } 1657063fbf2SJoel Becker 1667063fbf2SJoel Becker static void __exit configfs_exit(void) 1677063fbf2SJoel Becker { 1687063fbf2SJoel Becker unregister_filesystem(&configfs_fs_type); 169f9bb4882SEric W. Biederman sysfs_remove_mount_point(kernel_kobj, "config"); 1703d0f89bbSJoel Becker kmem_cache_destroy(configfs_dir_cachep); 1713d0f89bbSJoel Becker configfs_dir_cachep = NULL; 1727063fbf2SJoel Becker } 1737063fbf2SJoel Becker 1747063fbf2SJoel Becker MODULE_AUTHOR("Oracle"); 1757063fbf2SJoel Becker MODULE_LICENSE("GPL"); 1763d0f89bbSJoel Becker MODULE_VERSION("0.0.2"); 1777063fbf2SJoel Becker MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration."); 1787063fbf2SJoel Becker 179f5b69770SDaniel Baluta core_initcall(configfs_init); 1807063fbf2SJoel Becker module_exit(configfs_exit); 181