Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/configfs/mount.c
26282 views
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
set_default_d_op(sb, &configfs_dentry_ops); /* the rest get that */
96
sb->s_d_flags |= DCACHE_DONTCACHE;
97
return 0;
98
}
99
100
static int configfs_get_tree(struct fs_context *fc)
101
{
102
return get_tree_single(fc, configfs_fill_super);
103
}
104
105
static const struct fs_context_operations configfs_context_ops = {
106
.get_tree = configfs_get_tree,
107
};
108
109
static int configfs_init_fs_context(struct fs_context *fc)
110
{
111
fc->ops = &configfs_context_ops;
112
return 0;
113
}
114
115
static struct file_system_type configfs_fs_type = {
116
.owner = THIS_MODULE,
117
.name = "configfs",
118
.init_fs_context = configfs_init_fs_context,
119
.kill_sb = kill_litter_super,
120
};
121
MODULE_ALIAS_FS("configfs");
122
123
struct dentry *configfs_pin_fs(void)
124
{
125
int err = simple_pin_fs(&configfs_fs_type, &configfs_mount,
126
&configfs_mnt_count);
127
return err ? ERR_PTR(err) : configfs_mount->mnt_root;
128
}
129
130
void configfs_release_fs(void)
131
{
132
simple_release_fs(&configfs_mount, &configfs_mnt_count);
133
}
134
135
136
static int __init configfs_init(void)
137
{
138
int err = -ENOMEM;
139
140
configfs_dir_cachep = kmem_cache_create("configfs_dir_cache",
141
sizeof(struct configfs_dirent),
142
0, 0, NULL);
143
if (!configfs_dir_cachep)
144
goto out;
145
146
err = sysfs_create_mount_point(kernel_kobj, "config");
147
if (err)
148
goto out2;
149
150
err = register_filesystem(&configfs_fs_type);
151
if (err)
152
goto out3;
153
154
return 0;
155
out3:
156
pr_err("Unable to register filesystem!\n");
157
sysfs_remove_mount_point(kernel_kobj, "config");
158
out2:
159
kmem_cache_destroy(configfs_dir_cachep);
160
configfs_dir_cachep = NULL;
161
out:
162
return err;
163
}
164
165
static void __exit configfs_exit(void)
166
{
167
unregister_filesystem(&configfs_fs_type);
168
sysfs_remove_mount_point(kernel_kobj, "config");
169
kmem_cache_destroy(configfs_dir_cachep);
170
configfs_dir_cachep = NULL;
171
}
172
173
MODULE_AUTHOR("Oracle");
174
MODULE_LICENSE("GPL");
175
MODULE_VERSION("0.0.2");
176
MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration.");
177
178
core_initcall(configfs_init);
179
module_exit(configfs_exit);
180
181