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