aboutsummaryrefslogtreecommitdiffstats
path: root/fs/kernfs
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-11-28 14:54:44 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-29 21:16:08 -0500
commitfa736a951e456b996a76826ba78ff974414c3b55 (patch)
tree2ba6b9289163b684e41f5efb95c92144b12e2c86 /fs/kernfs
parent4b93dc9b1c684d0587fe44d36bbfdf45bd3bea9d (diff)
sysfs, kernfs: move mount core code to fs/kernfs/mount.c
Move core mount code to fs/kernfs/mount.c. The respective declarations in fs/sysfs/sysfs.h are moved to fs/kernfs/kernfs-internal.h. This is pure relocation. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/kernfs')
-rw-r--r--fs/kernfs/kernfs-internal.h22
-rw-r--r--fs/kernfs/mount.c156
2 files changed, 178 insertions, 0 deletions
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index 0d949885389d..ced0d6dadc7d 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -134,6 +134,28 @@ struct sysfs_addrm_cxt {
134#include "../sysfs/sysfs.h" 134#include "../sysfs/sysfs.h"
135 135
136/* 136/*
137 * mount.c
138 */
139struct sysfs_super_info {
140 /*
141 * The root associated with this super_block. Each super_block is
142 * identified by the root and ns it's associated with.
143 */
144 struct kernfs_root *root;
145
146 /*
147 * Each sb is associated with one namespace tag, currently the network
148 * namespace of the task which mounted this sysfs instance. If multiple
149 * tags become necessary, make the following an array and compare
150 * sysfs_dirent tag against every entry.
151 */
152 const void *ns;
153};
154#define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info))
155
156extern struct kmem_cache *sysfs_dir_cachep;
157
158/*
137 * inode.c 159 * inode.c
138 */ 160 */
139struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); 161struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd);
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index 872e262e5166..84c83e24bf25 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -7,3 +7,159 @@
7 * 7 *
8 * This file is released under the GPLv2. 8 * This file is released under the GPLv2.
9 */ 9 */
10
11#include <linux/fs.h>
12#include <linux/mount.h>
13#include <linux/init.h>
14#include <linux/magic.h>
15#include <linux/slab.h>
16#include <linux/pagemap.h>
17
18#include "kernfs-internal.h"
19
20struct kmem_cache *sysfs_dir_cachep;
21
22static const struct super_operations sysfs_ops = {
23 .statfs = simple_statfs,
24 .drop_inode = generic_delete_inode,
25 .evict_inode = sysfs_evict_inode,
26};
27
28static int sysfs_fill_super(struct super_block *sb)
29{
30 struct sysfs_super_info *info = sysfs_info(sb);
31 struct inode *inode;
32 struct dentry *root;
33
34 sb->s_blocksize = PAGE_CACHE_SIZE;
35 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
36 sb->s_magic = SYSFS_MAGIC;
37 sb->s_op = &sysfs_ops;
38 sb->s_time_gran = 1;
39
40 /* get root inode, initialize and unlock it */
41 mutex_lock(&sysfs_mutex);
42 inode = sysfs_get_inode(sb, info->root->sd);
43 mutex_unlock(&sysfs_mutex);
44 if (!inode) {
45 pr_debug("sysfs: could not get root inode\n");
46 return -ENOMEM;
47 }
48
49 /* instantiate and link root dentry */
50 root = d_make_root(inode);
51 if (!root) {
52 pr_debug("%s: could not get root dentry!\n", __func__);
53 return -ENOMEM;
54 }
55 kernfs_get(info->root->sd);
56 root->d_fsdata = info->root->sd;
57 sb->s_root = root;
58 sb->s_d_op = &sysfs_dentry_ops;
59 return 0;
60}
61
62static int sysfs_test_super(struct super_block *sb, void *data)
63{
64 struct sysfs_super_info *sb_info = sysfs_info(sb);
65 struct sysfs_super_info *info = data;
66
67 return sb_info->root == info->root && sb_info->ns == info->ns;
68}
69
70static int sysfs_set_super(struct super_block *sb, void *data)
71{
72 int error;
73 error = set_anon_super(sb, data);
74 if (!error)
75 sb->s_fs_info = data;
76 return error;
77}
78
79/**
80 * kernfs_super_ns - determine the namespace tag of a kernfs super_block
81 * @sb: super_block of interest
82 *
83 * Return the namespace tag associated with kernfs super_block @sb.
84 */
85const void *kernfs_super_ns(struct super_block *sb)
86{
87 struct sysfs_super_info *info = sysfs_info(sb);
88
89 return info->ns;
90}
91
92/**
93 * kernfs_mount_ns - kernfs mount helper
94 * @fs_type: file_system_type of the fs being mounted
95 * @flags: mount flags specified for the mount
96 * @root: kernfs_root of the hierarchy being mounted
97 * @ns: optional namespace tag of the mount
98 *
99 * This is to be called from each kernfs user's file_system_type->mount()
100 * implementation, which should pass through the specified @fs_type and
101 * @flags, and specify the hierarchy and namespace tag to mount via @root
102 * and @ns, respectively.
103 *
104 * The return value can be passed to the vfs layer verbatim.
105 */
106struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
107 struct kernfs_root *root, const void *ns)
108{
109 struct super_block *sb;
110 struct sysfs_super_info *info;
111 int error;
112
113 info = kzalloc(sizeof(*info), GFP_KERNEL);
114 if (!info)
115 return ERR_PTR(-ENOMEM);
116
117 info->root = root;
118 info->ns = ns;
119
120 sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info);
121 if (IS_ERR(sb) || sb->s_fs_info != info)
122 kfree(info);
123 if (IS_ERR(sb))
124 return ERR_CAST(sb);
125 if (!sb->s_root) {
126 error = sysfs_fill_super(sb);
127 if (error) {
128 deactivate_locked_super(sb);
129 return ERR_PTR(error);
130 }
131 sb->s_flags |= MS_ACTIVE;
132 }
133
134 return dget(sb->s_root);
135}
136
137/**
138 * kernfs_kill_sb - kill_sb for kernfs
139 * @sb: super_block being killed
140 *
141 * This can be used directly for file_system_type->kill_sb(). If a kernfs
142 * user needs extra cleanup, it can implement its own kill_sb() and call
143 * this function at the end.
144 */
145void kernfs_kill_sb(struct super_block *sb)
146{
147 struct sysfs_super_info *info = sysfs_info(sb);
148 struct sysfs_dirent *root_sd = sb->s_root->d_fsdata;
149
150 /*
151 * Remove the superblock from fs_supers/s_instances
152 * so we can't find it, before freeing sysfs_super_info.
153 */
154 kill_anon_super(sb);
155 kfree(info);
156 kernfs_put(root_sd);
157}
158
159void __init kernfs_init(void)
160{
161 sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache",
162 sizeof(struct sysfs_dirent),
163 0, SLAB_PANIC, NULL);
164 sysfs_inode_init();
165}