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