kernfs: add kernfs_open_file->priv
[linux-2.6-block.git] / fs / kernfs / mount.c
CommitLineData
b8441ed2
TH
1/*
2 * fs/kernfs/mount.c - kernfs mount implementation
3 *
4 * Copyright (c) 2001-3 Patrick Mochel
5 * Copyright (c) 2007 SUSE Linux Products GmbH
6 * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org>
7 *
8 * This file is released under the GPLv2.
9 */
fa736a95
TH
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
a797bfc3 20struct kmem_cache *kernfs_node_cache;
fa736a95 21
6a7fed4e
TH
22static int kernfs_sop_remount_fs(struct super_block *sb, int *flags, char *data)
23{
24 struct kernfs_root *root = kernfs_info(sb)->root;
25 struct kernfs_syscall_ops *scops = root->syscall_ops;
26
27 if (scops && scops->remount_fs)
28 return scops->remount_fs(root, flags, data);
29 return 0;
30}
31
32static int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry)
33{
34 struct kernfs_root *root = kernfs_root(dentry->d_fsdata);
35 struct kernfs_syscall_ops *scops = root->syscall_ops;
36
37 if (scops && scops->show_options)
38 return scops->show_options(sf, root);
39 return 0;
40}
41
a797bfc3 42static const struct super_operations kernfs_sops = {
fa736a95
TH
43 .statfs = simple_statfs,
44 .drop_inode = generic_delete_inode,
c637b8ac 45 .evict_inode = kernfs_evict_inode,
6a7fed4e
TH
46
47 .remount_fs = kernfs_sop_remount_fs,
48 .show_options = kernfs_sop_show_options,
fa736a95
TH
49};
50
c637b8ac 51static int kernfs_fill_super(struct super_block *sb)
fa736a95 52{
c525aadd 53 struct kernfs_super_info *info = kernfs_info(sb);
fa736a95
TH
54 struct inode *inode;
55 struct dentry *root;
56
57 sb->s_blocksize = PAGE_CACHE_SIZE;
58 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
59 sb->s_magic = SYSFS_MAGIC;
a797bfc3 60 sb->s_op = &kernfs_sops;
fa736a95
TH
61 sb->s_time_gran = 1;
62
63 /* get root inode, initialize and unlock it */
a797bfc3 64 mutex_lock(&kernfs_mutex);
c637b8ac 65 inode = kernfs_get_inode(sb, info->root->kn);
a797bfc3 66 mutex_unlock(&kernfs_mutex);
fa736a95 67 if (!inode) {
c637b8ac 68 pr_debug("kernfs: could not get root inode\n");
fa736a95
TH
69 return -ENOMEM;
70 }
71
72 /* instantiate and link root dentry */
73 root = d_make_root(inode);
74 if (!root) {
75 pr_debug("%s: could not get root dentry!\n", __func__);
76 return -ENOMEM;
77 }
324a56e1
TH
78 kernfs_get(info->root->kn);
79 root->d_fsdata = info->root->kn;
fa736a95 80 sb->s_root = root;
a797bfc3 81 sb->s_d_op = &kernfs_dops;
fa736a95
TH
82 return 0;
83}
84
c637b8ac 85static int kernfs_test_super(struct super_block *sb, void *data)
fa736a95 86{
c525aadd
TH
87 struct kernfs_super_info *sb_info = kernfs_info(sb);
88 struct kernfs_super_info *info = data;
fa736a95
TH
89
90 return sb_info->root == info->root && sb_info->ns == info->ns;
91}
92
c637b8ac 93static int kernfs_set_super(struct super_block *sb, void *data)
fa736a95
TH
94{
95 int error;
96 error = set_anon_super(sb, data);
97 if (!error)
98 sb->s_fs_info = data;
99 return error;
100}
101
102/**
103 * kernfs_super_ns - determine the namespace tag of a kernfs super_block
104 * @sb: super_block of interest
105 *
106 * Return the namespace tag associated with kernfs super_block @sb.
107 */
108const void *kernfs_super_ns(struct super_block *sb)
109{
c525aadd 110 struct kernfs_super_info *info = kernfs_info(sb);
fa736a95
TH
111
112 return info->ns;
113}
114
115/**
116 * kernfs_mount_ns - kernfs mount helper
117 * @fs_type: file_system_type of the fs being mounted
118 * @flags: mount flags specified for the mount
119 * @root: kernfs_root of the hierarchy being mounted
120 * @ns: optional namespace tag of the mount
121 *
122 * This is to be called from each kernfs user's file_system_type->mount()
123 * implementation, which should pass through the specified @fs_type and
124 * @flags, and specify the hierarchy and namespace tag to mount via @root
125 * and @ns, respectively.
126 *
127 * The return value can be passed to the vfs layer verbatim.
128 */
129struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
130 struct kernfs_root *root, const void *ns)
131{
132 struct super_block *sb;
c525aadd 133 struct kernfs_super_info *info;
fa736a95
TH
134 int error;
135
136 info = kzalloc(sizeof(*info), GFP_KERNEL);
137 if (!info)
138 return ERR_PTR(-ENOMEM);
139
140 info->root = root;
141 info->ns = ns;
142
c637b8ac 143 sb = sget(fs_type, kernfs_test_super, kernfs_set_super, flags, info);
fa736a95
TH
144 if (IS_ERR(sb) || sb->s_fs_info != info)
145 kfree(info);
146 if (IS_ERR(sb))
147 return ERR_CAST(sb);
148 if (!sb->s_root) {
c637b8ac 149 error = kernfs_fill_super(sb);
fa736a95
TH
150 if (error) {
151 deactivate_locked_super(sb);
152 return ERR_PTR(error);
153 }
154 sb->s_flags |= MS_ACTIVE;
155 }
156
157 return dget(sb->s_root);
158}
159
160/**
161 * kernfs_kill_sb - kill_sb for kernfs
162 * @sb: super_block being killed
163 *
164 * This can be used directly for file_system_type->kill_sb(). If a kernfs
165 * user needs extra cleanup, it can implement its own kill_sb() and call
166 * this function at the end.
167 */
168void kernfs_kill_sb(struct super_block *sb)
169{
c525aadd 170 struct kernfs_super_info *info = kernfs_info(sb);
324a56e1 171 struct kernfs_node *root_kn = sb->s_root->d_fsdata;
fa736a95
TH
172
173 /*
174 * Remove the superblock from fs_supers/s_instances
c525aadd 175 * so we can't find it, before freeing kernfs_super_info.
fa736a95
TH
176 */
177 kill_anon_super(sb);
178 kfree(info);
324a56e1 179 kernfs_put(root_kn);
fa736a95
TH
180}
181
182void __init kernfs_init(void)
183{
a797bfc3 184 kernfs_node_cache = kmem_cache_create("kernfs_node_cache",
324a56e1 185 sizeof(struct kernfs_node),
fa736a95 186 0, SLAB_PANIC, NULL);
c637b8ac 187 kernfs_inode_init();
fa736a95 188}