1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* -*- mode: c; c-basic-offset: 8; -*- 3 * vim: noexpandtab sw=8 ts=8 sts=0: 4 * 5 * mount.c - operations for initializing and mounting configfs. 6 * 7 * Based on sysfs: 8 * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 9 * 10 * configfs Copyright (C) 2005 Oracle. All rights reserved. 11 */ 12 13 #include <linux/fs.h> 14 #include <linux/module.h> 15 #include <linux/mount.h> 16 #include <linux/fs_context.h> 17 #include <linux/pagemap.h> 18 #include <linux/init.h> 19 #include <linux/slab.h> 20 21 #include <linux/configfs.h> 22 #include "configfs_internal.h" 23 24 /* Random magic number */ 25 #define CONFIGFS_MAGIC 0x62656570 26 27 static struct vfsmount *configfs_mount = NULL; 28 struct kmem_cache *configfs_dir_cachep; 29 static int configfs_mnt_count = 0; 30 31 static const struct super_operations configfs_ops = { 32 .statfs = simple_statfs, 33 .drop_inode = generic_delete_inode, 34 }; 35 36 static struct config_group configfs_root_group = { 37 .cg_item = { 38 .ci_namebuf = "root", 39 .ci_name = configfs_root_group.cg_item.ci_namebuf, 40 }, 41 }; 42 43 int configfs_is_root(struct config_item *item) 44 { 45 return item == &configfs_root_group.cg_item; 46 } 47 48 static struct configfs_dirent configfs_root = { 49 .s_sibling = LIST_HEAD_INIT(configfs_root.s_sibling), 50 .s_children = LIST_HEAD_INIT(configfs_root.s_children), 51 .s_element = &configfs_root_group.cg_item, 52 .s_type = CONFIGFS_ROOT, 53 .s_iattr = NULL, 54 }; 55 56 static int configfs_fill_super(struct super_block *sb, struct fs_context *fc) 57 { 58 struct inode *inode; 59 struct dentry *root; 60 61 sb->s_blocksize = PAGE_SIZE; 62 sb->s_blocksize_bits = PAGE_SHIFT; 63 sb->s_magic = CONFIGFS_MAGIC; 64 sb->s_op = &configfs_ops; 65 sb->s_time_gran = 1; 66 67 inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, 68 &configfs_root, sb); 69 if (inode) { 70 inode->i_op = &configfs_root_inode_operations; 71 inode->i_fop = &configfs_dir_operations; 72 /* directory inodes start off with i_nlink == 2 (for "." entry) */ 73 inc_nlink(inode); 74 } else { 75 pr_debug("could not get root inode\n"); 76 return -ENOMEM; 77 } 78 79 root = d_make_root(inode); 80 if (!root) { 81 pr_debug("%s: could not get root dentry!\n",__func__); 82 return -ENOMEM; 83 } 84 config_group_init(&configfs_root_group); 85 configfs_root_group.cg_item.ci_dentry = root; 86 root->d_fsdata = &configfs_root; 87 sb->s_root = root; 88 sb->s_d_op = &configfs_dentry_ops; /* the rest get that */ 89 return 0; 90 } 91 92 static int configfs_get_tree(struct fs_context *fc) 93 { 94 return get_tree_single(fc, configfs_fill_super); 95 } 96 97 static const struct fs_context_operations configfs_context_ops = { 98 .get_tree = configfs_get_tree, 99 }; 100 101 static int configfs_init_fs_context(struct fs_context *fc) 102 { 103 fc->ops = &configfs_context_ops; 104 return 0; 105 } 106 107 static struct file_system_type configfs_fs_type = { 108 .owner = THIS_MODULE, 109 .name = "configfs", 110 .init_fs_context = configfs_init_fs_context, 111 .kill_sb = kill_litter_super, 112 }; 113 MODULE_ALIAS_FS("configfs"); 114 115 struct dentry *configfs_pin_fs(void) 116 { 117 int err = simple_pin_fs(&configfs_fs_type, &configfs_mount, 118 &configfs_mnt_count); 119 return err ? ERR_PTR(err) : configfs_mount->mnt_root; 120 } 121 122 void configfs_release_fs(void) 123 { 124 simple_release_fs(&configfs_mount, &configfs_mnt_count); 125 } 126 127 128 static int __init configfs_init(void) 129 { 130 int err = -ENOMEM; 131 132 configfs_dir_cachep = kmem_cache_create("configfs_dir_cache", 133 sizeof(struct configfs_dirent), 134 0, 0, NULL); 135 if (!configfs_dir_cachep) 136 goto out; 137 138 err = sysfs_create_mount_point(kernel_kobj, "config"); 139 if (err) 140 goto out2; 141 142 err = register_filesystem(&configfs_fs_type); 143 if (err) 144 goto out3; 145 146 return 0; 147 out3: 148 pr_err("Unable to register filesystem!\n"); 149 sysfs_remove_mount_point(kernel_kobj, "config"); 150 out2: 151 kmem_cache_destroy(configfs_dir_cachep); 152 configfs_dir_cachep = NULL; 153 out: 154 return err; 155 } 156 157 static void __exit configfs_exit(void) 158 { 159 unregister_filesystem(&configfs_fs_type); 160 sysfs_remove_mount_point(kernel_kobj, "config"); 161 kmem_cache_destroy(configfs_dir_cachep); 162 configfs_dir_cachep = NULL; 163 } 164 165 MODULE_AUTHOR("Oracle"); 166 MODULE_LICENSE("GPL"); 167 MODULE_VERSION("0.0.2"); 168 MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration."); 169 170 core_initcall(configfs_init); 171 module_exit(configfs_exit); 172