diff options
Diffstat (limited to 'fs/configfs/mount.c')
-rw-r--r-- | fs/configfs/mount.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c new file mode 100644 index 000000000000..1a2f6f6a4d91 --- /dev/null +++ b/fs/configfs/mount.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* -*- mode: c; c-basic-offset: 8; -*- | ||
2 | * vim: noexpandtab sw=8 ts=8 sts=0: | ||
3 | * | ||
4 | * mount.c - operations for initializing and mounting configfs. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public | ||
8 | * License as published by the Free Software Foundation; either | ||
9 | * version 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public | ||
17 | * License along with this program; if not, write to the | ||
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
19 | * Boston, MA 021110-1307, USA. | ||
20 | * | ||
21 | * Based on sysfs: | ||
22 | * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel | ||
23 | * | ||
24 | * configfs Copyright (C) 2005 Oracle. All rights reserved. | ||
25 | */ | ||
26 | |||
27 | #include <linux/fs.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/mount.h> | ||
30 | #include <linux/pagemap.h> | ||
31 | #include <linux/init.h> | ||
32 | |||
33 | #include <linux/configfs.h> | ||
34 | #include "configfs_internal.h" | ||
35 | |||
36 | /* Random magic number */ | ||
37 | #define CONFIGFS_MAGIC 0x62656570 | ||
38 | |||
39 | struct vfsmount * configfs_mount = NULL; | ||
40 | struct super_block * configfs_sb = NULL; | ||
41 | static int configfs_mnt_count = 0; | ||
42 | |||
43 | static struct super_operations configfs_ops = { | ||
44 | .statfs = simple_statfs, | ||
45 | .drop_inode = generic_delete_inode, | ||
46 | }; | ||
47 | |||
48 | static struct config_group configfs_root_group = { | ||
49 | .cg_item = { | ||
50 | .ci_namebuf = "root", | ||
51 | .ci_name = configfs_root_group.cg_item.ci_namebuf, | ||
52 | }, | ||
53 | }; | ||
54 | |||
55 | int configfs_is_root(struct config_item *item) | ||
56 | { | ||
57 | return item == &configfs_root_group.cg_item; | ||
58 | } | ||
59 | |||
60 | static struct configfs_dirent configfs_root = { | ||
61 | .s_sibling = LIST_HEAD_INIT(configfs_root.s_sibling), | ||
62 | .s_children = LIST_HEAD_INIT(configfs_root.s_children), | ||
63 | .s_element = &configfs_root_group.cg_item, | ||
64 | .s_type = CONFIGFS_ROOT, | ||
65 | }; | ||
66 | |||
67 | static int configfs_fill_super(struct super_block *sb, void *data, int silent) | ||
68 | { | ||
69 | struct inode *inode; | ||
70 | struct dentry *root; | ||
71 | |||
72 | sb->s_blocksize = PAGE_CACHE_SIZE; | ||
73 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | ||
74 | sb->s_magic = CONFIGFS_MAGIC; | ||
75 | sb->s_op = &configfs_ops; | ||
76 | configfs_sb = sb; | ||
77 | |||
78 | inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); | ||
79 | if (inode) { | ||
80 | inode->i_op = &configfs_dir_inode_operations; | ||
81 | inode->i_fop = &configfs_dir_operations; | ||
82 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | ||
83 | inode->i_nlink++; | ||
84 | } else { | ||
85 | pr_debug("configfs: could not get root inode\n"); | ||
86 | return -ENOMEM; | ||
87 | } | ||
88 | |||
89 | root = d_alloc_root(inode); | ||
90 | if (!root) { | ||
91 | pr_debug("%s: could not get root dentry!\n",__FUNCTION__); | ||
92 | iput(inode); | ||
93 | return -ENOMEM; | ||
94 | } | ||
95 | config_group_init(&configfs_root_group); | ||
96 | configfs_root_group.cg_item.ci_dentry = root; | ||
97 | root->d_fsdata = &configfs_root; | ||
98 | sb->s_root = root; | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static struct super_block *configfs_get_sb(struct file_system_type *fs_type, | ||
103 | int flags, const char *dev_name, void *data) | ||
104 | { | ||
105 | return get_sb_single(fs_type, flags, data, configfs_fill_super); | ||
106 | } | ||
107 | |||
108 | static struct file_system_type configfs_fs_type = { | ||
109 | .owner = THIS_MODULE, | ||
110 | .name = "configfs", | ||
111 | .get_sb = configfs_get_sb, | ||
112 | .kill_sb = kill_litter_super, | ||
113 | }; | ||
114 | |||
115 | int configfs_pin_fs(void) | ||
116 | { | ||
117 | return simple_pin_fs("configfs", &configfs_mount, | ||
118 | &configfs_mnt_count); | ||
119 | } | ||
120 | |||
121 | void configfs_release_fs(void) | ||
122 | { | ||
123 | simple_release_fs(&configfs_mount, &configfs_mnt_count); | ||
124 | } | ||
125 | |||
126 | |||
127 | static decl_subsys(config, NULL, NULL); | ||
128 | |||
129 | static int __init configfs_init(void) | ||
130 | { | ||
131 | int err; | ||
132 | |||
133 | kset_set_kset_s(&config_subsys, kernel_subsys); | ||
134 | err = subsystem_register(&config_subsys); | ||
135 | if (err) | ||
136 | return err; | ||
137 | |||
138 | err = register_filesystem(&configfs_fs_type); | ||
139 | if (err) { | ||
140 | printk(KERN_ERR "configfs: Unable to register filesystem!\n"); | ||
141 | subsystem_unregister(&config_subsys); | ||
142 | } | ||
143 | |||
144 | return err; | ||
145 | } | ||
146 | |||
147 | static void __exit configfs_exit(void) | ||
148 | { | ||
149 | unregister_filesystem(&configfs_fs_type); | ||
150 | subsystem_unregister(&config_subsys); | ||
151 | } | ||
152 | |||
153 | MODULE_AUTHOR("Oracle"); | ||
154 | MODULE_LICENSE("GPL"); | ||
155 | MODULE_VERSION("0.0.1"); | ||
156 | MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration."); | ||
157 | |||
158 | module_init(configfs_init); | ||
159 | module_exit(configfs_exit); | ||