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