1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/errno.h>
30#include <linux/fs.h>
31#include <linux/file.h>
32#include <linux/stat.h>
33#include <linux/string.h>
34#include <linux/inet.h>
35#include <linux/pagemap.h>
36#include <linux/seq_file.h>
37#include <linux/mount.h>
38#include <linux/idr.h>
39#include <linux/sched.h>
40#include <net/9p/9p.h>
41#include <net/9p/client.h>
42
43#include "v9fs.h"
44#include "v9fs_vfs.h"
45#include "fid.h"
46
47static void v9fs_clear_inode(struct inode *);
48static const struct super_operations v9fs_super_ops;
49
50
51
52
53
54
55
56static void v9fs_clear_inode(struct inode *inode)
57{
58 filemap_fdatawrite(inode->i_mapping);
59}
60
61
62
63
64
65
66
67
68static int v9fs_set_super(struct super_block *s, void *data)
69{
70 s->s_fs_info = data;
71 return set_anon_super(s, data);
72}
73
74
75
76
77
78
79
80
81
82static void
83v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
84 int flags)
85{
86 sb->s_maxbytes = MAX_LFS_FILESIZE;
87 sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
88 sb->s_blocksize = 1 << sb->s_blocksize_bits;
89 sb->s_magic = V9FS_MAGIC;
90 sb->s_op = &v9fs_super_ops;
91
92 sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
93 MS_NOATIME;
94}
95
96
97
98
99
100
101
102
103
104
105
106static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
107 const char *dev_name, void *data,
108 struct vfsmount *mnt)
109{
110 struct super_block *sb = NULL;
111 struct inode *inode = NULL;
112 struct dentry *root = NULL;
113 struct v9fs_session_info *v9ses = NULL;
114 struct p9_wstat *st = NULL;
115 int mode = S_IRWXUGO | S_ISVTX;
116 uid_t uid = current->fsuid;
117 gid_t gid = current->fsgid;
118 struct p9_fid *fid;
119 int retval = 0;
120
121 P9_DPRINTK(P9_DEBUG_VFS, " \n");
122
123 st = NULL;
124 v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
125 if (!v9ses)
126 return -ENOMEM;
127
128 fid = v9fs_session_init(v9ses, dev_name, data);
129 if (IS_ERR(fid)) {
130 retval = PTR_ERR(fid);
131 goto close_session;
132 }
133
134 st = p9_client_stat(fid);
135 if (IS_ERR(st)) {
136 retval = PTR_ERR(st);
137 goto clunk_fid;
138 }
139
140 sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
141 if (IS_ERR(sb)) {
142 retval = PTR_ERR(sb);
143 goto free_stat;
144 }
145 v9fs_fill_super(sb, v9ses, flags);
146
147 inode = v9fs_get_inode(sb, S_IFDIR | mode);
148 if (IS_ERR(inode)) {
149 retval = PTR_ERR(inode);
150 goto release_sb;
151 }
152
153 inode->i_uid = uid;
154 inode->i_gid = gid;
155
156 root = d_alloc_root(inode);
157 if (!root) {
158 retval = -ENOMEM;
159 goto release_sb;
160 }
161
162 sb->s_root = root;
163 root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
164
165 v9fs_stat2inode(st, root->d_inode, sb);
166
167 v9fs_fid_add(root, fid);
168 p9stat_free(st);
169 kfree(st);
170
171P9_DPRINTK(P9_DEBUG_VFS, " return simple set mount\n");
172 return simple_set_mnt(mnt, sb);
173
174release_sb:
175 if (sb) {
176 up_write(&sb->s_umount);
177 deactivate_super(sb);
178 }
179
180free_stat:
181 kfree(st);
182
183clunk_fid:
184 p9_client_clunk(fid);
185
186close_session:
187 v9fs_session_close(v9ses);
188 kfree(v9ses);
189
190 return retval;
191}
192
193
194
195
196
197
198
199static void v9fs_kill_super(struct super_block *s)
200{
201 struct v9fs_session_info *v9ses = s->s_fs_info;
202
203 P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
204
205 v9fs_dentry_release(s->s_root);
206
207 kill_anon_super(s);
208
209 v9fs_session_close(v9ses);
210 kfree(v9ses);
211 P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n");
212}
213
214
215
216
217
218
219
220
221static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
222{
223 struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
224
225 seq_printf(m, "%s", v9ses->options);
226 return 0;
227}
228
229static void
230v9fs_umount_begin(struct super_block *sb)
231{
232 struct v9fs_session_info *v9ses = sb->s_fs_info;
233
234 v9fs_session_cancel(v9ses);
235}
236
237static const struct super_operations v9fs_super_ops = {
238 .statfs = simple_statfs,
239 .clear_inode = v9fs_clear_inode,
240 .show_options = v9fs_show_options,
241 .umount_begin = v9fs_umount_begin,
242};
243
244struct file_system_type v9fs_fs_type = {
245 .name = "9p",
246 .get_sb = v9fs_get_sb,
247 .kill_sb = v9fs_kill_super,
248 .owner = THIS_MODULE,
249};
250