diff options
author | Latchesar Ionkov <lucho@ionkov.net> | 2006-01-08 04:05:00 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-08 23:14:06 -0500 |
commit | 531b1094b74365dcc55fa464d28a9a2497ae825d (patch) | |
tree | a0384dabe3be1c844166d028b3ef7c21c3dfe5fc | |
parent | d8da097afb765654c866062148fd98b11db9003e (diff) |
[PATCH] v9fs: zero copy implementation
Performance enhancement reducing the number of copies in the data and
stat paths.
Signed-off-by: Latchesar Ionkov <lucho@ionkov.net>
Cc: Eric Van Hensbergen <ericvh@ericvh.myip.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/9p/9p.c | 302 | ||||
-rw-r--r-- | fs/9p/9p.h | 75 | ||||
-rw-r--r-- | fs/9p/Makefile | 10 | ||||
-rw-r--r-- | fs/9p/conv.c | 895 | ||||
-rw-r--r-- | fs/9p/conv.h | 28 | ||||
-rw-r--r-- | fs/9p/debug.h | 23 | ||||
-rw-r--r-- | fs/9p/error.c | 10 | ||||
-rw-r--r-- | fs/9p/error.h | 3 | ||||
-rw-r--r-- | fs/9p/fid.c | 3 | ||||
-rw-r--r-- | fs/9p/mux.c | 157 | ||||
-rw-r--r-- | fs/9p/trans_sock.c | 1 | ||||
-rw-r--r-- | fs/9p/v9fs.c | 3 | ||||
-rw-r--r-- | fs/9p/v9fs_vfs.h | 5 | ||||
-rw-r--r-- | fs/9p/vfs_dentry.c | 4 | ||||
-rw-r--r-- | fs/9p/vfs_dir.c | 31 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 25 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 545 | ||||
-rw-r--r-- | fs/9p/vfs_super.c | 10 |
18 files changed, 1083 insertions, 1047 deletions
diff --git a/fs/9p/9p.c b/fs/9p/9p.c index a3a1ac610723..dc3ce44ec836 100644 --- a/fs/9p/9p.c +++ b/fs/9p/9p.c | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * linux/fs/9p/9p.c | 2 | * linux/fs/9p/9p.c |
3 | * | 3 | * |
4 | * This file contains functions 9P2000 functions | 4 | * This file contains functions to perform synchronous 9P calls |
5 | * | 5 | * |
6 | * Copyright (C) 2004 by Latchesar Ionkov <lucho@ionkov.net> | ||
6 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | 7 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> |
7 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> | 8 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> |
8 | * | 9 | * |
@@ -33,6 +34,7 @@ | |||
33 | #include "debug.h" | 34 | #include "debug.h" |
34 | #include "v9fs.h" | 35 | #include "v9fs.h" |
35 | #include "9p.h" | 36 | #include "9p.h" |
37 | #include "conv.h" | ||
36 | #include "mux.h" | 38 | #include "mux.h" |
37 | 39 | ||
38 | /** | 40 | /** |
@@ -46,17 +48,21 @@ | |||
46 | 48 | ||
47 | int | 49 | int |
48 | v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize, | 50 | v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize, |
49 | char *version, struct v9fs_fcall **fcall) | 51 | char *version, struct v9fs_fcall **rcp) |
50 | { | 52 | { |
51 | struct v9fs_fcall msg; | 53 | int ret; |
54 | struct v9fs_fcall *tc; | ||
52 | 55 | ||
53 | dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version); | 56 | dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version); |
54 | msg.id = TVERSION; | 57 | tc = v9fs_create_tversion(msize, version); |
55 | msg.tag = ~0; | ||
56 | msg.params.tversion.msize = msize; | ||
57 | msg.params.tversion.version = version; | ||
58 | 58 | ||
59 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); | 59 | if (!IS_ERR(tc)) { |
60 | ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); | ||
61 | kfree(tc); | ||
62 | } else | ||
63 | ret = PTR_ERR(tc); | ||
64 | |||
65 | return ret; | ||
60 | } | 66 | } |
61 | 67 | ||
62 | /** | 68 | /** |
@@ -72,19 +78,23 @@ v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize, | |||
72 | 78 | ||
73 | int | 79 | int |
74 | v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname, | 80 | v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname, |
75 | u32 fid, u32 afid, struct v9fs_fcall **fcall) | 81 | u32 fid, u32 afid, struct v9fs_fcall **rcp) |
76 | { | 82 | { |
77 | struct v9fs_fcall msg; | 83 | int ret; |
84 | struct v9fs_fcall* tc; | ||
78 | 85 | ||
79 | dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname, | 86 | dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname, |
80 | aname, fid, afid); | 87 | aname, fid, afid); |
81 | msg.id = TATTACH; | ||
82 | msg.params.tattach.fid = fid; | ||
83 | msg.params.tattach.afid = afid; | ||
84 | msg.params.tattach.uname = uname; | ||
85 | msg.params.tattach.aname = aname; | ||
86 | 88 | ||
87 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); | 89 | ret = -ENOMEM; |
90 | tc = v9fs_create_tattach(fid, afid, uname, aname); | ||
91 | if (!IS_ERR(tc)) { | ||
92 | ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); | ||
93 | kfree(tc); | ||
94 | } else | ||
95 | ret = PTR_ERR(tc); | ||
96 | |||
97 | return ret; | ||
88 | } | 98 | } |
89 | 99 | ||
90 | static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc, | 100 | static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc, |
@@ -117,24 +127,28 @@ static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc, | |||
117 | * @fcall: pointer to response fcall pointer | 127 | * @fcall: pointer to response fcall pointer |
118 | * | 128 | * |
119 | */ | 129 | */ |
130 | |||
120 | int | 131 | int |
121 | v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid) | 132 | v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid) |
122 | { | 133 | { |
123 | int err; | 134 | int ret; |
124 | struct v9fs_fcall *tc, *rc; | 135 | struct v9fs_fcall *tc, *rc; |
125 | 136 | ||
126 | tc = kmalloc(sizeof(struct v9fs_fcall), GFP_KERNEL); | ||
127 | |||
128 | dprintk(DEBUG_9P, "fid %d\n", fid); | 137 | dprintk(DEBUG_9P, "fid %d\n", fid); |
129 | tc->id = TCLUNK; | ||
130 | tc->params.tclunk.fid = fid; | ||
131 | 138 | ||
132 | err = v9fs_mux_rpc(v9ses->mux, tc, &rc); | 139 | ret = -ENOMEM; |
133 | if (err >= 0) { | 140 | rc = NULL; |
134 | v9fs_t_clunk_cb(v9ses, tc, rc, 0); | 141 | tc = v9fs_create_tclunk(fid); |
135 | } | 142 | if (!IS_ERR(tc)) |
143 | ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); | ||
144 | else | ||
145 | ret = PTR_ERR(tc); | ||
146 | |||
147 | if (ret) | ||
148 | dprintk(DEBUG_ERROR, "failed fid %d err %d\n", fid, ret); | ||
136 | 149 | ||
137 | return err; | 150 | v9fs_t_clunk_cb(v9ses, tc, rc, ret); |
151 | return ret; | ||
138 | } | 152 | } |
139 | 153 | ||
140 | /** | 154 | /** |
@@ -144,14 +158,22 @@ v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid) | |||
144 | * | 158 | * |
145 | */ | 159 | */ |
146 | 160 | ||
147 | int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag) | 161 | int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag) |
148 | { | 162 | { |
149 | struct v9fs_fcall msg; | 163 | int ret; |
164 | struct v9fs_fcall *tc; | ||
150 | 165 | ||
151 | dprintk(DEBUG_9P, "oldtag %d\n", tag); | 166 | dprintk(DEBUG_9P, "oldtag %d\n", oldtag); |
152 | msg.id = TFLUSH; | 167 | |
153 | msg.params.tflush.oldtag = tag; | 168 | ret = -ENOMEM; |
154 | return v9fs_mux_rpc(v9ses->mux, &msg, NULL); | 169 | tc = v9fs_create_tflush(oldtag); |
170 | if (!IS_ERR(tc)) { | ||
171 | ret = v9fs_mux_rpc(v9ses->mux, tc, NULL); | ||
172 | kfree(tc); | ||
173 | } else | ||
174 | ret = PTR_ERR(tc); | ||
175 | |||
176 | return ret; | ||
155 | } | 177 | } |
156 | 178 | ||
157 | /** | 179 | /** |
@@ -163,17 +185,22 @@ int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag) | |||
163 | */ | 185 | */ |
164 | 186 | ||
165 | int | 187 | int |
166 | v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall) | 188 | v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **rcp) |
167 | { | 189 | { |
168 | struct v9fs_fcall msg; | 190 | int ret; |
191 | struct v9fs_fcall *tc; | ||
169 | 192 | ||
170 | dprintk(DEBUG_9P, "fid %d\n", fid); | 193 | dprintk(DEBUG_9P, "fid %d\n", fid); |
171 | if (fcall) | ||
172 | *fcall = NULL; | ||
173 | 194 | ||
174 | msg.id = TSTAT; | 195 | ret = -ENOMEM; |
175 | msg.params.tstat.fid = fid; | 196 | tc = v9fs_create_tstat(fid); |
176 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); | 197 | if (!IS_ERR(tc)) { |
198 | ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); | ||
199 | kfree(tc); | ||
200 | } else | ||
201 | ret = PTR_ERR(tc); | ||
202 | |||
203 | return ret; | ||
177 | } | 204 | } |
178 | 205 | ||
179 | /** | 206 | /** |
@@ -187,16 +214,22 @@ v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall) | |||
187 | 214 | ||
188 | int | 215 | int |
189 | v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, | 216 | v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, |
190 | struct v9fs_stat *stat, struct v9fs_fcall **fcall) | 217 | struct v9fs_wstat *wstat, struct v9fs_fcall **rcp) |
191 | { | 218 | { |
192 | struct v9fs_fcall msg; | 219 | int ret; |
220 | struct v9fs_fcall *tc; | ||
193 | 221 | ||
194 | dprintk(DEBUG_9P, "fid %d length %d\n", fid, (int)stat->length); | 222 | dprintk(DEBUG_9P, "fid %d\n", fid); |
195 | msg.id = TWSTAT; | 223 | |
196 | msg.params.twstat.fid = fid; | 224 | ret = -ENOMEM; |
197 | msg.params.twstat.stat = stat; | 225 | tc = v9fs_create_twstat(fid, wstat, v9ses->extended); |
226 | if (!IS_ERR(tc)) { | ||
227 | ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); | ||
228 | kfree(tc); | ||
229 | } else | ||
230 | ret = PTR_ERR(tc); | ||
198 | 231 | ||
199 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); | 232 | return ret; |
200 | } | 233 | } |
201 | 234 | ||
202 | /** | 235 | /** |
@@ -213,23 +246,28 @@ v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, | |||
213 | 246 | ||
214 | int | 247 | int |
215 | v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, | 248 | v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, |
216 | char *name, struct v9fs_fcall **fcall) | 249 | char *name, struct v9fs_fcall **rcp) |
217 | { | 250 | { |
218 | struct v9fs_fcall msg; | 251 | int ret; |
252 | struct v9fs_fcall *tc; | ||
253 | int nwname; | ||
219 | 254 | ||
220 | dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name); | 255 | dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name); |
221 | msg.id = TWALK; | 256 | |
222 | msg.params.twalk.fid = fid; | 257 | if (name) |
223 | msg.params.twalk.newfid = newfid; | 258 | nwname = 1; |
224 | 259 | else | |
225 | if (name) { | 260 | nwname = 0; |
226 | msg.params.twalk.nwname = 1; | 261 | |
227 | msg.params.twalk.wnames = &name; | 262 | ret = -ENOMEM; |
228 | } else { | 263 | tc = v9fs_create_twalk(fid, newfid, nwname, &name); |
229 | msg.params.twalk.nwname = 0; | 264 | if (!IS_ERR(tc)) { |
230 | } | 265 | ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); |
231 | 266 | kfree(tc); | |
232 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); | 267 | } else |
268 | ret = PTR_ERR(tc); | ||
269 | |||
270 | return ret; | ||
233 | } | 271 | } |
234 | 272 | ||
235 | /** | 273 | /** |
@@ -244,19 +282,22 @@ v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, | |||
244 | 282 | ||
245 | int | 283 | int |
246 | v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode, | 284 | v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode, |
247 | struct v9fs_fcall **fcall) | 285 | struct v9fs_fcall **rcp) |
248 | { | 286 | { |
249 | struct v9fs_fcall msg; | 287 | int ret; |
250 | int errorno = -1; | 288 | struct v9fs_fcall *tc; |
251 | 289 | ||
252 | dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode); | 290 | dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode); |
253 | msg.id = TOPEN; | ||
254 | msg.params.topen.fid = fid; | ||
255 | msg.params.topen.mode = mode; | ||
256 | 291 | ||
257 | errorno = v9fs_mux_rpc(v9ses->mux, &msg, fcall); | 292 | ret = -ENOMEM; |
293 | tc = v9fs_create_topen(fid, mode); | ||
294 | if (!IS_ERR(tc)) { | ||
295 | ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); | ||
296 | kfree(tc); | ||
297 | } else | ||
298 | ret = PTR_ERR(tc); | ||
258 | 299 | ||
259 | return errorno; | 300 | return ret; |
260 | } | 301 | } |
261 | 302 | ||
262 | /** | 303 | /** |
@@ -269,14 +310,22 @@ v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode, | |||
269 | 310 | ||
270 | int | 311 | int |
271 | v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid, | 312 | v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid, |
272 | struct v9fs_fcall **fcall) | 313 | struct v9fs_fcall **rcp) |
273 | { | 314 | { |
274 | struct v9fs_fcall msg; | 315 | int ret; |
316 | struct v9fs_fcall *tc; | ||
275 | 317 | ||
276 | dprintk(DEBUG_9P, "fid %d\n", fid); | 318 | dprintk(DEBUG_9P, "fid %d\n", fid); |
277 | msg.id = TREMOVE; | 319 | |
278 | msg.params.tremove.fid = fid; | 320 | ret = -ENOMEM; |
279 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); | 321 | tc = v9fs_create_tremove(fid); |
322 | if (!IS_ERR(tc)) { | ||
323 | ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); | ||
324 | kfree(tc); | ||
325 | } else | ||
326 | ret = PTR_ERR(tc); | ||
327 | |||
328 | return ret; | ||
280 | } | 329 | } |
281 | 330 | ||
282 | /** | 331 | /** |
@@ -292,20 +341,23 @@ v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid, | |||
292 | 341 | ||
293 | int | 342 | int |
294 | v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, | 343 | v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, |
295 | u32 perm, u8 mode, struct v9fs_fcall **fcall) | 344 | u32 perm, u8 mode, struct v9fs_fcall **rcp) |
296 | { | 345 | { |
297 | struct v9fs_fcall msg; | 346 | int ret; |
347 | struct v9fs_fcall *tc; | ||
298 | 348 | ||
299 | dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n", | 349 | dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n", |
300 | fid, name, perm, mode); | 350 | fid, name, perm, mode); |
301 | 351 | ||
302 | msg.id = TCREATE; | 352 | ret = -ENOMEM; |
303 | msg.params.tcreate.fid = fid; | 353 | tc = v9fs_create_tcreate(fid, name, perm, mode); |
304 | msg.params.tcreate.name = name; | 354 | if (!IS_ERR(tc)) { |
305 | msg.params.tcreate.perm = perm; | 355 | ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); |
306 | msg.params.tcreate.mode = mode; | 356 | kfree(tc); |
357 | } else | ||
358 | ret = PTR_ERR(tc); | ||
307 | 359 | ||
308 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); | 360 | return ret; |
309 | } | 361 | } |
310 | 362 | ||
311 | /** | 363 | /** |
@@ -320,31 +372,30 @@ v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, | |||
320 | 372 | ||
321 | int | 373 | int |
322 | v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset, | 374 | v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset, |
323 | u32 count, struct v9fs_fcall **fcall) | 375 | u32 count, struct v9fs_fcall **rcp) |
324 | { | 376 | { |
325 | struct v9fs_fcall msg; | 377 | int ret; |
326 | struct v9fs_fcall *rc = NULL; | 378 | struct v9fs_fcall *tc, *rc; |
327 | long errorno = -1; | ||
328 | |||
329 | dprintk(DEBUG_9P, "fid %d offset 0x%lx count 0x%x\n", fid, | ||
330 | (long unsigned int)offset, count); | ||
331 | msg.id = TREAD; | ||
332 | msg.params.tread.fid = fid; | ||
333 | msg.params.tread.offset = offset; | ||
334 | msg.params.tread.count = count; | ||
335 | errorno = v9fs_mux_rpc(v9ses->mux, &msg, &rc); | ||
336 | |||
337 | if (!errorno) { | ||
338 | errorno = rc->params.rread.count; | ||
339 | dump_data(rc->params.rread.data, rc->params.rread.count); | ||
340 | } | ||
341 | |||
342 | if (fcall) | ||
343 | *fcall = rc; | ||
344 | else | ||
345 | kfree(rc); | ||
346 | 379 | ||
347 | return errorno; | 380 | dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid, |
381 | (long long unsigned) offset, count); | ||
382 | |||
383 | ret = -ENOMEM; | ||
384 | tc = v9fs_create_tread(fid, offset, count); | ||
385 | if (!IS_ERR(tc)) { | ||
386 | ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); | ||
387 | if (!ret) | ||
388 | ret = rc->params.rread.count; | ||
389 | if (rcp) | ||
390 | *rcp = rc; | ||
391 | else | ||
392 | kfree(rc); | ||
393 | |||
394 | kfree(tc); | ||
395 | } else | ||
396 | ret = PTR_ERR(tc); | ||
397 | |||
398 | return ret; | ||
348 | } | 399 | } |
349 | 400 | ||
350 | /** | 401 | /** |
@@ -358,32 +409,31 @@ v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset, | |||
358 | */ | 409 | */ |
359 | 410 | ||
360 | int | 411 | int |
361 | v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, | 412 | v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count, |
362 | u64 offset, u32 count, void *data, struct v9fs_fcall **fcall) | 413 | const char __user *data, struct v9fs_fcall **rcp) |
363 | { | 414 | { |
364 | struct v9fs_fcall msg; | 415 | int ret; |
365 | struct v9fs_fcall *rc = NULL; | 416 | struct v9fs_fcall *tc, *rc; |
366 | long errorno = -1; | ||
367 | 417 | ||
368 | dprintk(DEBUG_9P, "fid %d offset 0x%llx count 0x%x\n", fid, | 418 | dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid, |
369 | (unsigned long long)offset, count); | 419 | (long long unsigned) offset, count); |
370 | dump_data(data, count); | ||
371 | 420 | ||
372 | msg.id = TWRITE; | 421 | ret = -ENOMEM; |
373 | msg.params.twrite.fid = fid; | 422 | tc = v9fs_create_twrite(fid, offset, count, data); |
374 | msg.params.twrite.offset = offset; | 423 | if (!IS_ERR(tc)) { |
375 | msg.params.twrite.count = count; | 424 | ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); |
376 | msg.params.twrite.data = data; | ||
377 | 425 | ||
378 | errorno = v9fs_mux_rpc(v9ses->mux, &msg, &rc); | 426 | if (!ret) |
427 | ret = rc->params.rwrite.count; | ||
428 | if (rcp) | ||
429 | *rcp = rc; | ||
430 | else | ||
431 | kfree(rc); | ||
379 | 432 | ||
380 | if (!errorno) | 433 | kfree(tc); |
381 | errorno = rc->params.rwrite.count; | 434 | } else |
435 | ret = PTR_ERR(tc); | ||
382 | 436 | ||
383 | if (fcall) | 437 | return ret; |
384 | *fcall = rc; | ||
385 | else | ||
386 | kfree(rc); | ||
387 | |||
388 | return errorno; | ||
389 | } | 438 | } |
439 | |||
diff --git a/fs/9p/9p.h b/fs/9p/9p.h index 6355392786e2..007ff639777d 100644 --- a/fs/9p/9p.h +++ b/fs/9p/9p.h | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * 9P protocol definitions. | 4 | * 9P protocol definitions. |
5 | * | 5 | * |
6 | * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> | ||
6 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | 7 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> |
7 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> | 8 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> |
8 | * | 9 | * |
@@ -102,10 +103,16 @@ enum { | |||
102 | 103 | ||
103 | #define V9FS_NOTAG (u16)(~0) | 104 | #define V9FS_NOTAG (u16)(~0) |
104 | #define V9FS_NOFID (u32)(~0) | 105 | #define V9FS_NOFID (u32)(~0) |
106 | #define V9FS_MAXWELEM 16 | ||
105 | 107 | ||
106 | /* ample room for Twrite/Rread header (iounit) */ | 108 | /* ample room for Twrite/Rread header (iounit) */ |
107 | #define V9FS_IOHDRSZ 24 | 109 | #define V9FS_IOHDRSZ 24 |
108 | 110 | ||
111 | struct v9fs_str { | ||
112 | u16 len; | ||
113 | char *str; | ||
114 | }; | ||
115 | |||
109 | /* qids are the unique ID for a file (like an inode */ | 116 | /* qids are the unique ID for a file (like an inode */ |
110 | struct v9fs_qid { | 117 | struct v9fs_qid { |
111 | u8 type; | 118 | u8 type; |
@@ -123,6 +130,29 @@ struct v9fs_stat { | |||
123 | u32 atime; | 130 | u32 atime; |
124 | u32 mtime; | 131 | u32 mtime; |
125 | u64 length; | 132 | u64 length; |
133 | struct v9fs_str name; | ||
134 | struct v9fs_str uid; | ||
135 | struct v9fs_str gid; | ||
136 | struct v9fs_str muid; | ||
137 | struct v9fs_str extension; /* 9p2000.u extensions */ | ||
138 | u32 n_uid; /* 9p2000.u extensions */ | ||
139 | u32 n_gid; /* 9p2000.u extensions */ | ||
140 | u32 n_muid; /* 9p2000.u extensions */ | ||
141 | }; | ||
142 | |||
143 | /* file metadata (stat) structure used to create Twstat message | ||
144 | The is similar to v9fs_stat, but the strings don't point to | ||
145 | the same memory block and should be freed separately | ||
146 | */ | ||
147 | struct v9fs_wstat { | ||
148 | u16 size; | ||
149 | u16 type; | ||
150 | u32 dev; | ||
151 | struct v9fs_qid qid; | ||
152 | u32 mode; | ||
153 | u32 atime; | ||
154 | u32 mtime; | ||
155 | u64 length; | ||
126 | char *name; | 156 | char *name; |
127 | char *uid; | 157 | char *uid; |
128 | char *gid; | 158 | char *gid; |
@@ -131,25 +161,24 @@ struct v9fs_stat { | |||
131 | u32 n_uid; /* 9p2000.u extensions */ | 161 | u32 n_uid; /* 9p2000.u extensions */ |
132 | u32 n_gid; /* 9p2000.u extensions */ | 162 | u32 n_gid; /* 9p2000.u extensions */ |
133 | u32 n_muid; /* 9p2000.u extensions */ | 163 | u32 n_muid; /* 9p2000.u extensions */ |
134 | char data[0]; | ||
135 | }; | 164 | }; |
136 | 165 | ||
137 | /* Structures for Protocol Operations */ | 166 | /* Structures for Protocol Operations */ |
138 | 167 | ||
139 | struct Tversion { | 168 | struct Tversion { |
140 | u32 msize; | 169 | u32 msize; |
141 | char *version; | 170 | struct v9fs_str version; |
142 | }; | 171 | }; |
143 | 172 | ||
144 | struct Rversion { | 173 | struct Rversion { |
145 | u32 msize; | 174 | u32 msize; |
146 | char *version; | 175 | struct v9fs_str version; |
147 | }; | 176 | }; |
148 | 177 | ||
149 | struct Tauth { | 178 | struct Tauth { |
150 | u32 afid; | 179 | u32 afid; |
151 | char *uname; | 180 | struct v9fs_str uname; |
152 | char *aname; | 181 | struct v9fs_str aname; |
153 | }; | 182 | }; |
154 | 183 | ||
155 | struct Rauth { | 184 | struct Rauth { |
@@ -157,12 +186,12 @@ struct Rauth { | |||
157 | }; | 186 | }; |
158 | 187 | ||
159 | struct Rerror { | 188 | struct Rerror { |
160 | char *error; | 189 | struct v9fs_str error; |
161 | u32 errno; /* 9p2000.u extension */ | 190 | u32 errno; /* 9p2000.u extension */ |
162 | }; | 191 | }; |
163 | 192 | ||
164 | struct Tflush { | 193 | struct Tflush { |
165 | u32 oldtag; | 194 | u16 oldtag; |
166 | }; | 195 | }; |
167 | 196 | ||
168 | struct Rflush { | 197 | struct Rflush { |
@@ -171,8 +200,8 @@ struct Rflush { | |||
171 | struct Tattach { | 200 | struct Tattach { |
172 | u32 fid; | 201 | u32 fid; |
173 | u32 afid; | 202 | u32 afid; |
174 | char *uname; | 203 | struct v9fs_str uname; |
175 | char *aname; | 204 | struct v9fs_str aname; |
176 | }; | 205 | }; |
177 | 206 | ||
178 | struct Rattach { | 207 | struct Rattach { |
@@ -182,13 +211,13 @@ struct Rattach { | |||
182 | struct Twalk { | 211 | struct Twalk { |
183 | u32 fid; | 212 | u32 fid; |
184 | u32 newfid; | 213 | u32 newfid; |
185 | u32 nwname; | 214 | u16 nwname; |
186 | char **wnames; | 215 | struct v9fs_str wnames[16]; |
187 | }; | 216 | }; |
188 | 217 | ||
189 | struct Rwalk { | 218 | struct Rwalk { |
190 | u32 nwqid; | 219 | u16 nwqid; |
191 | struct v9fs_qid *wqids; | 220 | struct v9fs_qid wqids[16]; |
192 | }; | 221 | }; |
193 | 222 | ||
194 | struct Topen { | 223 | struct Topen { |
@@ -203,7 +232,7 @@ struct Ropen { | |||
203 | 232 | ||
204 | struct Tcreate { | 233 | struct Tcreate { |
205 | u32 fid; | 234 | u32 fid; |
206 | char *name; | 235 | struct v9fs_str name; |
207 | u32 perm; | 236 | u32 perm; |
208 | u8 mode; | 237 | u8 mode; |
209 | }; | 238 | }; |
@@ -254,12 +283,12 @@ struct Tstat { | |||
254 | }; | 283 | }; |
255 | 284 | ||
256 | struct Rstat { | 285 | struct Rstat { |
257 | struct v9fs_stat *stat; | 286 | struct v9fs_stat stat; |
258 | }; | 287 | }; |
259 | 288 | ||
260 | struct Twstat { | 289 | struct Twstat { |
261 | u32 fid; | 290 | u32 fid; |
262 | struct v9fs_stat *stat; | 291 | struct v9fs_stat stat; |
263 | }; | 292 | }; |
264 | 293 | ||
265 | struct Rwstat { | 294 | struct Rwstat { |
@@ -274,6 +303,7 @@ struct v9fs_fcall { | |||
274 | u32 size; | 303 | u32 size; |
275 | u8 id; | 304 | u8 id; |
276 | u16 tag; | 305 | u16 tag; |
306 | void *sdata; | ||
277 | 307 | ||
278 | union { | 308 | union { |
279 | struct Tversion tversion; | 309 | struct Tversion tversion; |
@@ -306,10 +336,12 @@ struct v9fs_fcall { | |||
306 | } params; | 336 | } params; |
307 | }; | 337 | }; |
308 | 338 | ||
309 | #define V9FS_FCALLHDRSZ (sizeof(struct v9fs_fcall) + \ | 339 | #define PRINT_FCALL_ERROR(s, fcall) dprintk(DEBUG_ERROR, "%s: %.*s\n", s, \ |
310 | sizeof(struct v9fs_stat) + 16*sizeof(struct v9fs_qid) + 16) | 340 | fcall?fcall->params.rerror.error.len:0, \ |
341 | fcall?fcall->params.rerror.error.str:""); | ||
311 | 342 | ||
312 | #define FCALL_ERROR(fcall) (fcall ? fcall->params.rerror.error : "") | 343 | char *v9fs_str_copy(char *buf, int buflen, struct v9fs_str *str); |
344 | int v9fs_str_compare(char *buf, struct v9fs_str *str); | ||
313 | 345 | ||
314 | int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize, | 346 | int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize, |
315 | char *version, struct v9fs_fcall **rcall); | 347 | char *version, struct v9fs_fcall **rcall); |
@@ -325,7 +357,7 @@ int v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, | |||
325 | struct v9fs_fcall **rcall); | 357 | struct v9fs_fcall **rcall); |
326 | 358 | ||
327 | int v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, | 359 | int v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, |
328 | struct v9fs_stat *stat, struct v9fs_fcall **rcall); | 360 | struct v9fs_wstat *wstat, struct v9fs_fcall **rcall); |
329 | 361 | ||
330 | int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, | 362 | int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, |
331 | char *name, struct v9fs_fcall **rcall); | 363 | char *name, struct v9fs_fcall **rcall); |
@@ -343,4 +375,5 @@ int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, | |||
343 | u64 offset, u32 count, struct v9fs_fcall **rcall); | 375 | u64 offset, u32 count, struct v9fs_fcall **rcall); |
344 | 376 | ||
345 | int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, | 377 | int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, |
346 | u32 count, void *data, struct v9fs_fcall **rcall); | 378 | u32 count, const char __user * data, |
379 | struct v9fs_fcall **rcall); | ||
diff --git a/fs/9p/Makefile b/fs/9p/Makefile index e4e4ffe5a7dc..3d023089707e 100644 --- a/fs/9p/Makefile +++ b/fs/9p/Makefile | |||
@@ -1,17 +1,17 @@ | |||
1 | obj-$(CONFIG_9P_FS) := 9p2000.o | 1 | obj-$(CONFIG_9P_FS) := 9p2000.o |
2 | 2 | ||
3 | 9p2000-objs := \ | 3 | 9p2000-objs := \ |
4 | trans_fd.o \ | ||
5 | trans_sock.o \ | ||
6 | mux.o \ | ||
7 | 9p.o \ | ||
8 | conv.o \ | ||
4 | vfs_super.o \ | 9 | vfs_super.o \ |
5 | vfs_inode.o \ | 10 | vfs_inode.o \ |
6 | vfs_file.o \ | 11 | vfs_file.o \ |
7 | vfs_dir.o \ | 12 | vfs_dir.o \ |
8 | vfs_dentry.o \ | 13 | vfs_dentry.o \ |
9 | error.o \ | 14 | error.o \ |
10 | mux.o \ | ||
11 | trans_fd.o \ | ||
12 | trans_sock.o \ | ||
13 | 9p.o \ | ||
14 | conv.o \ | ||
15 | v9fs.o \ | 15 | v9fs.o \ |
16 | fid.o | 16 | fid.o |
17 | 17 | ||
diff --git a/fs/9p/conv.c b/fs/9p/conv.c index 1b9b15dfeaf0..f62434d435b3 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/errno.h> | 30 | #include <linux/errno.h> |
31 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
32 | #include <linux/idr.h> | 32 | #include <linux/idr.h> |
33 | 33 | #include <asm/uaccess.h> | |
34 | #include "debug.h" | 34 | #include "debug.h" |
35 | #include "v9fs.h" | 35 | #include "v9fs.h" |
36 | #include "9p.h" | 36 | #include "9p.h" |
@@ -45,6 +45,37 @@ struct cbuf { | |||
45 | unsigned char *ep; | 45 | unsigned char *ep; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | char *v9fs_str_copy(char *buf, int buflen, struct v9fs_str *str) | ||
49 | { | ||
50 | int n; | ||
51 | |||
52 | if (buflen < str->len) | ||
53 | n = buflen; | ||
54 | else | ||
55 | n = str->len; | ||
56 | |||
57 | memmove(buf, str->str, n - 1); | ||
58 | |||
59 | return buf; | ||
60 | } | ||
61 | |||
62 | int v9fs_str_compare(char *buf, struct v9fs_str *str) | ||
63 | { | ||
64 | int n, ret; | ||
65 | |||
66 | ret = strncmp(buf, str->str, str->len); | ||
67 | |||
68 | if (!ret) { | ||
69 | n = strlen(buf); | ||
70 | if (n < str->len) | ||
71 | ret = -1; | ||
72 | else if (n > str->len) | ||
73 | ret = 1; | ||
74 | } | ||
75 | |||
76 | return ret; | ||
77 | } | ||
78 | |||
48 | static inline void buf_init(struct cbuf *buf, void *data, int datalen) | 79 | static inline void buf_init(struct cbuf *buf, void *data, int datalen) |
49 | { | 80 | { |
50 | buf->sp = buf->p = data; | 81 | buf->sp = buf->p = data; |
@@ -58,12 +89,12 @@ static inline int buf_check_overflow(struct cbuf *buf) | |||
58 | 89 | ||
59 | static inline int buf_check_size(struct cbuf *buf, int len) | 90 | static inline int buf_check_size(struct cbuf *buf, int len) |
60 | { | 91 | { |
61 | if (buf->p+len > buf->ep) { | 92 | if (buf->p + len > buf->ep && buf->p < buf->ep) { |
62 | if (buf->p < buf->ep) { | 93 | eprintk(KERN_ERR, "buffer overflow: want %d has %d\n", |
63 | eprintk(KERN_ERR, "buffer overflow\n"); | 94 | len, (int)(buf->ep - buf->p)); |
64 | buf->p = buf->ep + 1; | 95 | dump_stack(); |
65 | return 0; | 96 | buf->p = buf->ep + 1; |
66 | } | 97 | return 0; |
67 | } | 98 | } |
68 | 99 | ||
69 | return 1; | 100 | return 1; |
@@ -127,14 +158,6 @@ static inline void buf_put_string(struct cbuf *buf, const char *s) | |||
127 | buf_put_stringn(buf, s, strlen(s)); | 158 | buf_put_stringn(buf, s, strlen(s)); |
128 | } | 159 | } |
129 | 160 | ||
130 | static inline void buf_put_data(struct cbuf *buf, void *data, u32 datalen) | ||
131 | { | ||
132 | if (buf_check_size(buf, datalen)) { | ||
133 | memcpy(buf->p, data, datalen); | ||
134 | buf->p += datalen; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | static inline u8 buf_get_int8(struct cbuf *buf) | 161 | static inline u8 buf_get_int8(struct cbuf *buf) |
139 | { | 162 | { |
140 | u8 ret = 0; | 163 | u8 ret = 0; |
@@ -183,85 +206,37 @@ static inline u64 buf_get_int64(struct cbuf *buf) | |||
183 | return ret; | 206 | return ret; |
184 | } | 207 | } |
185 | 208 | ||
186 | static inline int | 209 | static inline void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) |
187 | buf_get_string(struct cbuf *buf, char *data, unsigned int datalen) | ||
188 | { | ||
189 | u16 len = 0; | ||
190 | |||
191 | len = buf_get_int16(buf); | ||
192 | if (!buf_check_overflow(buf) && buf_check_size(buf, len) && len+1>datalen) { | ||
193 | memcpy(data, buf->p, len); | ||
194 | data[len] = 0; | ||
195 | buf->p += len; | ||
196 | len++; | ||
197 | } | ||
198 | |||
199 | return len; | ||
200 | } | ||
201 | |||
202 | static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf) | ||
203 | { | ||
204 | char *ret; | ||
205 | u16 len; | ||
206 | |||
207 | ret = NULL; | ||
208 | len = buf_get_int16(buf); | ||
209 | |||
210 | if (!buf_check_overflow(buf) && buf_check_size(buf, len) && | ||
211 | buf_check_size(sbuf, len + 1)) { | ||
212 | |||
213 | memcpy(sbuf->p, buf->p, len); | ||
214 | sbuf->p[len] = 0; | ||
215 | ret = sbuf->p; | ||
216 | buf->p += len; | ||
217 | sbuf->p += len + 1; | ||
218 | } | ||
219 | |||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | static inline int buf_get_data(struct cbuf *buf, void *data, int datalen) | ||
224 | { | 210 | { |
225 | int ret = 0; | 211 | vstr->len = buf_get_int16(buf); |
226 | 212 | if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { | |
227 | if (buf_check_size(buf, datalen)) { | 213 | vstr->str = buf->p; |
228 | memcpy(data, buf->p, datalen); | 214 | buf->p += vstr->len; |
229 | buf->p += datalen; | 215 | } else { |
230 | ret = datalen; | 216 | vstr->len = 0; |
217 | vstr->str = NULL; | ||
231 | } | 218 | } |
232 | |||
233 | return ret; | ||
234 | } | 219 | } |
235 | 220 | ||
236 | static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf, | 221 | static inline void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid) |
237 | int datalen) | ||
238 | { | 222 | { |
239 | char *ret = NULL; | 223 | qid->type = buf_get_int8(bufp); |
240 | int n = 0; | 224 | qid->version = buf_get_int32(bufp); |
241 | 225 | qid->path = buf_get_int64(bufp); | |
242 | if (buf_check_size(dbuf, datalen)) { | ||
243 | n = buf_get_data(buf, dbuf->p, datalen); | ||
244 | if (n > 0) { | ||
245 | ret = dbuf->p; | ||
246 | dbuf->p += n; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | return ret; | ||
251 | } | 226 | } |
252 | 227 | ||
253 | /** | 228 | /** |
254 | * v9fs_size_stat - calculate the size of a variable length stat struct | 229 | * v9fs_size_wstat - calculate the size of a variable length stat struct |
255 | * @stat: metadata (stat) structure | 230 | * @stat: metadata (stat) structure |
256 | * @extended: non-zero if 9P2000.u | 231 | * @extended: non-zero if 9P2000.u |
257 | * | 232 | * |
258 | */ | 233 | */ |
259 | 234 | ||
260 | static int v9fs_size_stat(struct v9fs_stat *stat, int extended) | 235 | static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended) |
261 | { | 236 | { |
262 | int size = 0; | 237 | int size = 0; |
263 | 238 | ||
264 | if (stat == NULL) { | 239 | if (wstat == NULL) { |
265 | eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n"); | 240 | eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n"); |
266 | return 0; | 241 | return 0; |
267 | } | 242 | } |
@@ -278,81 +253,38 @@ static int v9fs_size_stat(struct v9fs_stat *stat, int extended) | |||
278 | 8 + /* length[8] */ | 253 | 8 + /* length[8] */ |
279 | 8; /* minimum sum of string lengths */ | 254 | 8; /* minimum sum of string lengths */ |
280 | 255 | ||
281 | if (stat->name) | 256 | if (wstat->name) |
282 | size += strlen(stat->name); | 257 | size += strlen(wstat->name); |
283 | if (stat->uid) | 258 | if (wstat->uid) |
284 | size += strlen(stat->uid); | 259 | size += strlen(wstat->uid); |
285 | if (stat->gid) | 260 | if (wstat->gid) |
286 | size += strlen(stat->gid); | 261 | size += strlen(wstat->gid); |
287 | if (stat->muid) | 262 | if (wstat->muid) |
288 | size += strlen(stat->muid); | 263 | size += strlen(wstat->muid); |
289 | 264 | ||
290 | if (extended) { | 265 | if (extended) { |
291 | size += 4 + /* n_uid[4] */ | 266 | size += 4 + /* n_uid[4] */ |
292 | 4 + /* n_gid[4] */ | 267 | 4 + /* n_gid[4] */ |
293 | 4 + /* n_muid[4] */ | 268 | 4 + /* n_muid[4] */ |
294 | 2; /* string length of extension[4] */ | 269 | 2; /* string length of extension[4] */ |
295 | if (stat->extension) | 270 | if (wstat->extension) |
296 | size += strlen(stat->extension); | 271 | size += strlen(wstat->extension); |
297 | } | 272 | } |
298 | 273 | ||
299 | return size; | 274 | return size; |
300 | } | 275 | } |
301 | 276 | ||
302 | /** | 277 | /** |
303 | * serialize_stat - safely format a stat structure for transmission | 278 | * buf_get_stat - safely decode a recieved metadata (stat) structure |
304 | * @stat: metadata (stat) structure | ||
305 | * @bufp: buffer to serialize structure into | ||
306 | * @extended: non-zero if 9P2000.u | ||
307 | * | ||
308 | */ | ||
309 | |||
310 | static int | ||
311 | serialize_stat(struct v9fs_stat *stat, struct cbuf *bufp, int extended) | ||
312 | { | ||
313 | buf_put_int16(bufp, stat->size); | ||
314 | buf_put_int16(bufp, stat->type); | ||
315 | buf_put_int32(bufp, stat->dev); | ||
316 | buf_put_int8(bufp, stat->qid.type); | ||
317 | buf_put_int32(bufp, stat->qid.version); | ||
318 | buf_put_int64(bufp, stat->qid.path); | ||
319 | buf_put_int32(bufp, stat->mode); | ||
320 | buf_put_int32(bufp, stat->atime); | ||
321 | buf_put_int32(bufp, stat->mtime); | ||
322 | buf_put_int64(bufp, stat->length); | ||
323 | |||
324 | buf_put_string(bufp, stat->name); | ||
325 | buf_put_string(bufp, stat->uid); | ||
326 | buf_put_string(bufp, stat->gid); | ||
327 | buf_put_string(bufp, stat->muid); | ||
328 | |||
329 | if (extended) { | ||
330 | buf_put_string(bufp, stat->extension); | ||
331 | buf_put_int32(bufp, stat->n_uid); | ||
332 | buf_put_int32(bufp, stat->n_gid); | ||
333 | buf_put_int32(bufp, stat->n_muid); | ||
334 | } | ||
335 | |||
336 | if (buf_check_overflow(bufp)) | ||
337 | return 0; | ||
338 | |||
339 | return stat->size; | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * deserialize_stat - safely decode a recieved metadata (stat) structure | ||
344 | * @bufp: buffer to deserialize | 279 | * @bufp: buffer to deserialize |
345 | * @stat: metadata (stat) structure | 280 | * @stat: metadata (stat) structure |
346 | * @dbufp: buffer to deserialize variable strings into | ||
347 | * @extended: non-zero if 9P2000.u | 281 | * @extended: non-zero if 9P2000.u |
348 | * | 282 | * |
349 | */ | 283 | */ |
350 | 284 | ||
351 | static inline int | 285 | static inline void |
352 | deserialize_stat(struct cbuf *bufp, struct v9fs_stat *stat, | 286 | buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended) |
353 | struct cbuf *dbufp, int extended) | ||
354 | { | 287 | { |
355 | |||
356 | stat->size = buf_get_int16(bufp); | 288 | stat->size = buf_get_int16(bufp); |
357 | stat->type = buf_get_int16(bufp); | 289 | stat->type = buf_get_int16(bufp); |
358 | stat->dev = buf_get_int32(bufp); | 290 | stat->dev = buf_get_int32(bufp); |
@@ -363,45 +295,17 @@ deserialize_stat(struct cbuf *bufp, struct v9fs_stat *stat, | |||
363 | stat->atime = buf_get_int32(bufp); | 295 | stat->atime = buf_get_int32(bufp); |
364 | stat->mtime = buf_get_int32(bufp); | 296 | stat->mtime = buf_get_int32(bufp); |
365 | stat->length = buf_get_int64(bufp); | 297 | stat->length = buf_get_int64(bufp); |
366 | stat->name = buf_get_stringb(bufp, dbufp); | 298 | buf_get_str(bufp, &stat->name); |
367 | stat->uid = buf_get_stringb(bufp, dbufp); | 299 | buf_get_str(bufp, &stat->uid); |
368 | stat->gid = buf_get_stringb(bufp, dbufp); | 300 | buf_get_str(bufp, &stat->gid); |
369 | stat->muid = buf_get_stringb(bufp, dbufp); | 301 | buf_get_str(bufp, &stat->muid); |
370 | 302 | ||
371 | if (extended) { | 303 | if (extended) { |
372 | stat->extension = buf_get_stringb(bufp, dbufp); | 304 | buf_get_str(bufp, &stat->extension); |
373 | stat->n_uid = buf_get_int32(bufp); | 305 | stat->n_uid = buf_get_int32(bufp); |
374 | stat->n_gid = buf_get_int32(bufp); | 306 | stat->n_gid = buf_get_int32(bufp); |
375 | stat->n_muid = buf_get_int32(bufp); | 307 | stat->n_muid = buf_get_int32(bufp); |
376 | } | 308 | } |
377 | |||
378 | if (buf_check_overflow(bufp) || buf_check_overflow(dbufp)) | ||
379 | return 0; | ||
380 | |||
381 | return stat->size + 2; | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * deserialize_statb - wrapper for decoding a received metadata structure | ||
386 | * @bufp: buffer to deserialize | ||
387 | * @dbufp: buffer to deserialize variable strings into | ||
388 | * @extended: non-zero if 9P2000.u | ||
389 | * | ||
390 | */ | ||
391 | |||
392 | static inline struct v9fs_stat *deserialize_statb(struct cbuf *bufp, | ||
393 | struct cbuf *dbufp, | ||
394 | int extended) | ||
395 | { | ||
396 | struct v9fs_stat *ret = buf_alloc(dbufp, sizeof(struct v9fs_stat)); | ||
397 | |||
398 | if (ret) { | ||
399 | int n = deserialize_stat(bufp, ret, dbufp, extended); | ||
400 | if (n <= 0) | ||
401 | return NULL; | ||
402 | } | ||
403 | |||
404 | return ret; | ||
405 | } | 309 | } |
406 | 310 | ||
407 | /** | 311 | /** |
@@ -409,194 +313,27 @@ static inline struct v9fs_stat *deserialize_statb(struct cbuf *bufp, | |||
409 | * @buf: buffer to deserialize | 313 | * @buf: buffer to deserialize |
410 | * @buflen: length of received buffer | 314 | * @buflen: length of received buffer |
411 | * @stat: metadata structure to decode into | 315 | * @stat: metadata structure to decode into |
412 | * @statlen: length of destination metadata structure | ||
413 | * @extended: non-zero if 9P2000.u | 316 | * @extended: non-zero if 9P2000.u |
414 | * | 317 | * |
318 | * Note: stat will point to the buf region. | ||
415 | */ | 319 | */ |
416 | 320 | ||
417 | int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat, | 321 | int |
418 | u32 statlen, int extended) | 322 | v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat, |
323 | int extended) | ||
419 | { | 324 | { |
420 | struct cbuf buffer; | 325 | struct cbuf buffer; |
421 | struct cbuf *bufp = &buffer; | 326 | struct cbuf *bufp = &buffer; |
422 | struct cbuf dbuffer; | 327 | unsigned char *p; |
423 | struct cbuf *dbufp = &dbuffer; | ||
424 | 328 | ||
425 | buf_init(bufp, buf, buflen); | 329 | buf_init(bufp, buf, buflen); |
426 | buf_init(dbufp, (char *)stat + sizeof(struct v9fs_stat), | 330 | p = bufp->p; |
427 | statlen - sizeof(struct v9fs_stat)); | 331 | buf_get_stat(bufp, stat, extended); |
428 | |||
429 | return deserialize_stat(bufp, stat, dbufp, extended); | ||
430 | } | ||
431 | |||
432 | static inline int v9fs_size_fcall(struct v9fs_fcall *fcall, int extended) | ||
433 | { | ||
434 | int size = 4 + 1 + 2; /* size[4] msg[1] tag[2] */ | ||
435 | int i = 0; | ||
436 | 332 | ||
437 | switch (fcall->id) { | 333 | if (buf_check_overflow(bufp)) |
438 | default: | ||
439 | eprintk(KERN_ERR, "bad msg type %d\n", fcall->id); | ||
440 | return 0; | 334 | return 0; |
441 | case TVERSION: /* msize[4] version[s] */ | 335 | else |
442 | size += 4 + 2 + strlen(fcall->params.tversion.version); | 336 | return bufp->p - p; |
443 | break; | ||
444 | case TAUTH: /* afid[4] uname[s] aname[s] */ | ||
445 | size += 4 + 2 + strlen(fcall->params.tauth.uname) + | ||
446 | 2 + strlen(fcall->params.tauth.aname); | ||
447 | break; | ||
448 | case TFLUSH: /* oldtag[2] */ | ||
449 | size += 2; | ||
450 | break; | ||
451 | case TATTACH: /* fid[4] afid[4] uname[s] aname[s] */ | ||
452 | size += 4 + 4 + 2 + strlen(fcall->params.tattach.uname) + | ||
453 | 2 + strlen(fcall->params.tattach.aname); | ||
454 | break; | ||
455 | case TWALK: /* fid[4] newfid[4] nwname[2] nwname*(wname[s]) */ | ||
456 | size += 4 + 4 + 2; | ||
457 | /* now compute total for the array of names */ | ||
458 | for (i = 0; i < fcall->params.twalk.nwname; i++) | ||
459 | size += 2 + strlen(fcall->params.twalk.wnames[i]); | ||
460 | break; | ||
461 | case TOPEN: /* fid[4] mode[1] */ | ||
462 | size += 4 + 1; | ||
463 | break; | ||
464 | case TCREATE: /* fid[4] name[s] perm[4] mode[1] */ | ||
465 | size += 4 + 2 + strlen(fcall->params.tcreate.name) + 4 + 1; | ||
466 | break; | ||
467 | case TREAD: /* fid[4] offset[8] count[4] */ | ||
468 | size += 4 + 8 + 4; | ||
469 | break; | ||
470 | case TWRITE: /* fid[4] offset[8] count[4] data[count] */ | ||
471 | size += 4 + 8 + 4 + fcall->params.twrite.count; | ||
472 | break; | ||
473 | case TCLUNK: /* fid[4] */ | ||
474 | size += 4; | ||
475 | break; | ||
476 | case TREMOVE: /* fid[4] */ | ||
477 | size += 4; | ||
478 | break; | ||
479 | case TSTAT: /* fid[4] */ | ||
480 | size += 4; | ||
481 | break; | ||
482 | case TWSTAT: /* fid[4] stat[n] */ | ||
483 | fcall->params.twstat.stat->size = | ||
484 | v9fs_size_stat(fcall->params.twstat.stat, extended); | ||
485 | size += 4 + 2 + 2 + fcall->params.twstat.stat->size; | ||
486 | } | ||
487 | return size; | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * v9fs_serialize_fcall - marshall fcall struct into a packet | ||
492 | * @fcall: structure to convert | ||
493 | * @data: buffer to serialize fcall into | ||
494 | * @datalen: length of buffer to serialize fcall into | ||
495 | * @extended: non-zero if 9P2000.u | ||
496 | * | ||
497 | */ | ||
498 | |||
499 | int | ||
500 | v9fs_serialize_fcall(struct v9fs_fcall *fcall, void *data, u32 datalen, | ||
501 | int extended) | ||
502 | { | ||
503 | int i = 0; | ||
504 | struct v9fs_stat *stat = NULL; | ||
505 | struct cbuf buffer; | ||
506 | struct cbuf *bufp = &buffer; | ||
507 | |||
508 | buf_init(bufp, data, datalen); | ||
509 | |||
510 | if (!fcall) { | ||
511 | eprintk(KERN_ERR, "no fcall\n"); | ||
512 | return -EINVAL; | ||
513 | } | ||
514 | |||
515 | fcall->size = v9fs_size_fcall(fcall, extended); | ||
516 | |||
517 | buf_put_int32(bufp, fcall->size); | ||
518 | buf_put_int8(bufp, fcall->id); | ||
519 | buf_put_int16(bufp, fcall->tag); | ||
520 | |||
521 | dprintk(DEBUG_CONV, "size %d id %d tag %d\n", fcall->size, fcall->id, | ||
522 | fcall->tag); | ||
523 | |||
524 | /* now encode it */ | ||
525 | switch (fcall->id) { | ||
526 | default: | ||
527 | eprintk(KERN_ERR, "bad msg type: %d\n", fcall->id); | ||
528 | return -EPROTO; | ||
529 | case TVERSION: | ||
530 | buf_put_int32(bufp, fcall->params.tversion.msize); | ||
531 | buf_put_string(bufp, fcall->params.tversion.version); | ||
532 | break; | ||
533 | case TAUTH: | ||
534 | buf_put_int32(bufp, fcall->params.tauth.afid); | ||
535 | buf_put_string(bufp, fcall->params.tauth.uname); | ||
536 | buf_put_string(bufp, fcall->params.tauth.aname); | ||
537 | break; | ||
538 | case TFLUSH: | ||
539 | buf_put_int16(bufp, fcall->params.tflush.oldtag); | ||
540 | break; | ||
541 | case TATTACH: | ||
542 | buf_put_int32(bufp, fcall->params.tattach.fid); | ||
543 | buf_put_int32(bufp, fcall->params.tattach.afid); | ||
544 | buf_put_string(bufp, fcall->params.tattach.uname); | ||
545 | buf_put_string(bufp, fcall->params.tattach.aname); | ||
546 | break; | ||
547 | case TWALK: | ||
548 | buf_put_int32(bufp, fcall->params.twalk.fid); | ||
549 | buf_put_int32(bufp, fcall->params.twalk.newfid); | ||
550 | buf_put_int16(bufp, fcall->params.twalk.nwname); | ||
551 | for (i = 0; i < fcall->params.twalk.nwname; i++) | ||
552 | buf_put_string(bufp, fcall->params.twalk.wnames[i]); | ||
553 | break; | ||
554 | case TOPEN: | ||
555 | buf_put_int32(bufp, fcall->params.topen.fid); | ||
556 | buf_put_int8(bufp, fcall->params.topen.mode); | ||
557 | break; | ||
558 | case TCREATE: | ||
559 | buf_put_int32(bufp, fcall->params.tcreate.fid); | ||
560 | buf_put_string(bufp, fcall->params.tcreate.name); | ||
561 | buf_put_int32(bufp, fcall->params.tcreate.perm); | ||
562 | buf_put_int8(bufp, fcall->params.tcreate.mode); | ||
563 | break; | ||
564 | case TREAD: | ||
565 | buf_put_int32(bufp, fcall->params.tread.fid); | ||
566 | buf_put_int64(bufp, fcall->params.tread.offset); | ||
567 | buf_put_int32(bufp, fcall->params.tread.count); | ||
568 | break; | ||
569 | case TWRITE: | ||
570 | buf_put_int32(bufp, fcall->params.twrite.fid); | ||
571 | buf_put_int64(bufp, fcall->params.twrite.offset); | ||
572 | buf_put_int32(bufp, fcall->params.twrite.count); | ||
573 | buf_put_data(bufp, fcall->params.twrite.data, | ||
574 | fcall->params.twrite.count); | ||
575 | break; | ||
576 | case TCLUNK: | ||
577 | buf_put_int32(bufp, fcall->params.tclunk.fid); | ||
578 | break; | ||
579 | case TREMOVE: | ||
580 | buf_put_int32(bufp, fcall->params.tremove.fid); | ||
581 | break; | ||
582 | case TSTAT: | ||
583 | buf_put_int32(bufp, fcall->params.tstat.fid); | ||
584 | break; | ||
585 | case TWSTAT: | ||
586 | buf_put_int32(bufp, fcall->params.twstat.fid); | ||
587 | stat = fcall->params.twstat.stat; | ||
588 | |||
589 | buf_put_int16(bufp, stat->size + 2); | ||
590 | serialize_stat(stat, bufp, extended); | ||
591 | break; | ||
592 | } | ||
593 | |||
594 | if (buf_check_overflow(bufp)) { | ||
595 | dprintk(DEBUG_ERROR, "buffer overflow\n"); | ||
596 | return -EIO; | ||
597 | } | ||
598 | |||
599 | return fcall->size; | ||
600 | } | 337 | } |
601 | 338 | ||
602 | /** | 339 | /** |
@@ -611,18 +348,14 @@ v9fs_serialize_fcall(struct v9fs_fcall *fcall, void *data, u32 datalen, | |||
611 | 348 | ||
612 | int | 349 | int |
613 | v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, | 350 | v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, |
614 | int rcalllen, int extended) | 351 | int extended) |
615 | { | 352 | { |
616 | 353 | ||
617 | struct cbuf buffer; | 354 | struct cbuf buffer; |
618 | struct cbuf *bufp = &buffer; | 355 | struct cbuf *bufp = &buffer; |
619 | struct cbuf dbuffer; | ||
620 | struct cbuf *dbufp = &dbuffer; | ||
621 | int i = 0; | 356 | int i = 0; |
622 | 357 | ||
623 | buf_init(bufp, buf, buflen); | 358 | buf_init(bufp, buf, buflen); |
624 | buf_init(dbufp, (char *)rcall + sizeof(struct v9fs_fcall), | ||
625 | rcalllen - sizeof(struct v9fs_fcall)); | ||
626 | 359 | ||
627 | rcall->size = buf_get_int32(bufp); | 360 | rcall->size = buf_get_int32(bufp); |
628 | rcall->id = buf_get_int8(bufp); | 361 | rcall->id = buf_get_int8(bufp); |
@@ -630,13 +363,14 @@ v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, | |||
630 | 363 | ||
631 | dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id, | 364 | dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id, |
632 | rcall->tag); | 365 | rcall->tag); |
366 | |||
633 | switch (rcall->id) { | 367 | switch (rcall->id) { |
634 | default: | 368 | default: |
635 | eprintk(KERN_ERR, "unknown message type: %d\n", rcall->id); | 369 | eprintk(KERN_ERR, "unknown message type: %d\n", rcall->id); |
636 | return -EPROTO; | 370 | return -EPROTO; |
637 | case RVERSION: | 371 | case RVERSION: |
638 | rcall->params.rversion.msize = buf_get_int32(bufp); | 372 | rcall->params.rversion.msize = buf_get_int32(bufp); |
639 | rcall->params.rversion.version = buf_get_stringb(bufp, dbufp); | 373 | buf_get_str(bufp, &rcall->params.rversion.version); |
640 | break; | 374 | break; |
641 | case RFLUSH: | 375 | case RFLUSH: |
642 | break; | 376 | break; |
@@ -647,40 +381,27 @@ v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, | |||
647 | break; | 381 | break; |
648 | case RWALK: | 382 | case RWALK: |
649 | rcall->params.rwalk.nwqid = buf_get_int16(bufp); | 383 | rcall->params.rwalk.nwqid = buf_get_int16(bufp); |
650 | if (rcall->params.rwalk.nwqid > 16) { | 384 | if (rcall->params.rwalk.nwqid > V9FS_MAXWELEM) { |
651 | eprintk(KERN_ERR, "Rwalk with more than 16 qids: %d\n", | 385 | eprintk(KERN_ERR, "Rwalk with more than %d qids: %d\n", |
652 | rcall->params.rwalk.nwqid); | 386 | V9FS_MAXWELEM, rcall->params.rwalk.nwqid); |
653 | return -EPROTO; | 387 | return -EPROTO; |
654 | } | 388 | } |
655 | 389 | ||
656 | rcall->params.rwalk.wqids = buf_alloc(dbufp, | 390 | for (i = 0; i < rcall->params.rwalk.nwqid; i++) |
657 | rcall->params.rwalk.nwqid * sizeof(struct v9fs_qid)); | 391 | buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]); |
658 | if (rcall->params.rwalk.wqids) | ||
659 | for (i = 0; i < rcall->params.rwalk.nwqid; i++) { | ||
660 | rcall->params.rwalk.wqids[i].type = | ||
661 | buf_get_int8(bufp); | ||
662 | rcall->params.rwalk.wqids[i].version = | ||
663 | buf_get_int16(bufp); | ||
664 | rcall->params.rwalk.wqids[i].path = | ||
665 | buf_get_int64(bufp); | ||
666 | } | ||
667 | break; | 392 | break; |
668 | case ROPEN: | 393 | case ROPEN: |
669 | rcall->params.ropen.qid.type = buf_get_int8(bufp); | 394 | buf_get_qid(bufp, &rcall->params.ropen.qid); |
670 | rcall->params.ropen.qid.version = buf_get_int32(bufp); | ||
671 | rcall->params.ropen.qid.path = buf_get_int64(bufp); | ||
672 | rcall->params.ropen.iounit = buf_get_int32(bufp); | 395 | rcall->params.ropen.iounit = buf_get_int32(bufp); |
673 | break; | 396 | break; |
674 | case RCREATE: | 397 | case RCREATE: |
675 | rcall->params.rcreate.qid.type = buf_get_int8(bufp); | 398 | buf_get_qid(bufp, &rcall->params.rcreate.qid); |
676 | rcall->params.rcreate.qid.version = buf_get_int32(bufp); | ||
677 | rcall->params.rcreate.qid.path = buf_get_int64(bufp); | ||
678 | rcall->params.rcreate.iounit = buf_get_int32(bufp); | 399 | rcall->params.rcreate.iounit = buf_get_int32(bufp); |
679 | break; | 400 | break; |
680 | case RREAD: | 401 | case RREAD: |
681 | rcall->params.rread.count = buf_get_int32(bufp); | 402 | rcall->params.rread.count = buf_get_int32(bufp); |
682 | rcall->params.rread.data = buf_get_datab(bufp, dbufp, | 403 | rcall->params.rread.data = bufp->p; |
683 | rcall->params.rread.count); | 404 | buf_check_size(bufp, rcall->params.rread.count); |
684 | break; | 405 | break; |
685 | case RWRITE: | 406 | case RWRITE: |
686 | rcall->params.rwrite.count = buf_get_int32(bufp); | 407 | rcall->params.rwrite.count = buf_get_int32(bufp); |
@@ -691,22 +412,442 @@ v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, | |||
691 | break; | 412 | break; |
692 | case RSTAT: | 413 | case RSTAT: |
693 | buf_get_int16(bufp); | 414 | buf_get_int16(bufp); |
694 | rcall->params.rstat.stat = | 415 | buf_get_stat(bufp, &rcall->params.rstat.stat, extended); |
695 | deserialize_statb(bufp, dbufp, extended); | ||
696 | break; | 416 | break; |
697 | case RWSTAT: | 417 | case RWSTAT: |
698 | break; | 418 | break; |
699 | case RERROR: | 419 | case RERROR: |
700 | rcall->params.rerror.error = buf_get_stringb(bufp, dbufp); | 420 | buf_get_str(bufp, &rcall->params.rerror.error); |
701 | if (extended) | 421 | if (extended) |
702 | rcall->params.rerror.errno = buf_get_int16(bufp); | 422 | rcall->params.rerror.errno = buf_get_int16(bufp); |
703 | break; | 423 | break; |
704 | } | 424 | } |
705 | 425 | ||
706 | if (buf_check_overflow(bufp) || buf_check_overflow(dbufp)) { | 426 | if (buf_check_overflow(bufp)) { |
707 | dprintk(DEBUG_ERROR, "buffer overflow\n"); | 427 | dprintk(DEBUG_ERROR, "buffer overflow\n"); |
708 | return -EIO; | 428 | return -EIO; |
709 | } | 429 | } |
710 | 430 | ||
711 | return rcall->size; | 431 | return bufp->p - bufp->sp; |
432 | } | ||
433 | |||
434 | static inline void v9fs_put_int8(struct cbuf *bufp, u8 val, u8 * p) | ||
435 | { | ||
436 | *p = val; | ||
437 | buf_put_int8(bufp, val); | ||
438 | } | ||
439 | |||
440 | static inline void v9fs_put_int16(struct cbuf *bufp, u16 val, u16 * p) | ||
441 | { | ||
442 | *p = val; | ||
443 | buf_put_int16(bufp, val); | ||
444 | } | ||
445 | |||
446 | static inline void v9fs_put_int32(struct cbuf *bufp, u32 val, u32 * p) | ||
447 | { | ||
448 | *p = val; | ||
449 | buf_put_int32(bufp, val); | ||
450 | } | ||
451 | |||
452 | static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p) | ||
453 | { | ||
454 | *p = val; | ||
455 | buf_put_int64(bufp, val); | ||
456 | } | ||
457 | |||
458 | static inline void | ||
459 | v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) | ||
460 | { | ||
461 | if (data) { | ||
462 | str->len = strlen(data); | ||
463 | str->str = bufp->p; | ||
464 | } else { | ||
465 | str->len = 0; | ||
466 | str->str = NULL; | ||
467 | } | ||
468 | |||
469 | buf_put_stringn(bufp, data, str->len); | ||
470 | } | ||
471 | |||
472 | static inline int | ||
473 | v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count, | ||
474 | unsigned char **pdata) | ||
475 | { | ||
476 | *pdata = buf_alloc(bufp, count); | ||
477 | return copy_from_user(*pdata, data, count); | ||
478 | } | ||
479 | |||
480 | static void | ||
481 | v9fs_put_wstat(struct cbuf *bufp, struct v9fs_wstat *wstat, | ||
482 | struct v9fs_stat *stat, int statsz, int extended) | ||
483 | { | ||
484 | v9fs_put_int16(bufp, statsz, &stat->size); | ||
485 | v9fs_put_int16(bufp, wstat->type, &stat->type); | ||
486 | v9fs_put_int32(bufp, wstat->dev, &stat->dev); | ||
487 | v9fs_put_int8(bufp, wstat->qid.type, &stat->qid.type); | ||
488 | v9fs_put_int32(bufp, wstat->qid.version, &stat->qid.version); | ||
489 | v9fs_put_int64(bufp, wstat->qid.path, &stat->qid.path); | ||
490 | v9fs_put_int32(bufp, wstat->mode, &stat->mode); | ||
491 | v9fs_put_int32(bufp, wstat->atime, &stat->atime); | ||
492 | v9fs_put_int32(bufp, wstat->mtime, &stat->mtime); | ||
493 | v9fs_put_int64(bufp, wstat->length, &stat->length); | ||
494 | |||
495 | v9fs_put_str(bufp, wstat->name, &stat->name); | ||
496 | v9fs_put_str(bufp, wstat->uid, &stat->uid); | ||
497 | v9fs_put_str(bufp, wstat->gid, &stat->gid); | ||
498 | v9fs_put_str(bufp, wstat->muid, &stat->muid); | ||
499 | |||
500 | if (extended) { | ||
501 | v9fs_put_str(bufp, wstat->extension, &stat->extension); | ||
502 | v9fs_put_int32(bufp, wstat->n_uid, &stat->n_uid); | ||
503 | v9fs_put_int32(bufp, wstat->n_gid, &stat->n_gid); | ||
504 | v9fs_put_int32(bufp, wstat->n_muid, &stat->n_muid); | ||
505 | } | ||
506 | } | ||
507 | |||
508 | static struct v9fs_fcall * | ||
509 | v9fs_create_common(struct cbuf *bufp, u32 size, u8 id) | ||
510 | { | ||
511 | struct v9fs_fcall *fc; | ||
512 | |||
513 | size += 4 + 1 + 2; /* size[4] id[1] tag[2] */ | ||
514 | fc = kmalloc(sizeof(struct v9fs_fcall) + size, GFP_KERNEL); | ||
515 | if (!fc) | ||
516 | return ERR_PTR(-ENOMEM); | ||
517 | |||
518 | fc->sdata = (char *)fc + sizeof(*fc); | ||
519 | |||
520 | buf_init(bufp, (char *)fc->sdata, size); | ||
521 | v9fs_put_int32(bufp, size, &fc->size); | ||
522 | v9fs_put_int8(bufp, id, &fc->id); | ||
523 | v9fs_put_int16(bufp, V9FS_NOTAG, &fc->tag); | ||
524 | |||
525 | return fc; | ||
526 | } | ||
527 | |||
528 | void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag) | ||
529 | { | ||
530 | *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag); | ||
531 | } | ||
532 | |||
533 | struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version) | ||
534 | { | ||
535 | int size; | ||
536 | struct v9fs_fcall *fc; | ||
537 | struct cbuf buffer; | ||
538 | struct cbuf *bufp = &buffer; | ||
539 | |||
540 | size = 4 + 2 + strlen(version); /* msize[4] version[s] */ | ||
541 | fc = v9fs_create_common(bufp, size, TVERSION); | ||
542 | if (IS_ERR(fc)) | ||
543 | goto error; | ||
544 | |||
545 | v9fs_put_int32(bufp, msize, &fc->params.tversion.msize); | ||
546 | v9fs_put_str(bufp, version, &fc->params.tversion.version); | ||
547 | |||
548 | if (buf_check_overflow(bufp)) { | ||
549 | kfree(fc); | ||
550 | fc = ERR_PTR(-ENOMEM); | ||
551 | } | ||
552 | error: | ||
553 | return fc; | ||
554 | } | ||
555 | |||
556 | struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname) | ||
557 | { | ||
558 | int size; | ||
559 | struct v9fs_fcall *fc; | ||
560 | struct cbuf buffer; | ||
561 | struct cbuf *bufp = &buffer; | ||
562 | |||
563 | size = 4 + 2 + strlen(uname) + 2 + strlen(aname); /* afid[4] uname[s] aname[s] */ | ||
564 | fc = v9fs_create_common(bufp, size, TAUTH); | ||
565 | if (IS_ERR(fc)) | ||
566 | goto error; | ||
567 | |||
568 | v9fs_put_int32(bufp, afid, &fc->params.tauth.afid); | ||
569 | v9fs_put_str(bufp, uname, &fc->params.tauth.uname); | ||
570 | v9fs_put_str(bufp, aname, &fc->params.tauth.aname); | ||
571 | |||
572 | if (buf_check_overflow(bufp)) { | ||
573 | kfree(fc); | ||
574 | fc = ERR_PTR(-ENOMEM); | ||
575 | } | ||
576 | error: | ||
577 | return fc; | ||
578 | } | ||
579 | |||
580 | struct v9fs_fcall * | ||
581 | v9fs_create_tattach(u32 fid, u32 afid, char *uname, char *aname) | ||
582 | { | ||
583 | int size; | ||
584 | struct v9fs_fcall *fc; | ||
585 | struct cbuf buffer; | ||
586 | struct cbuf *bufp = &buffer; | ||
587 | |||
588 | size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); /* fid[4] afid[4] uname[s] aname[s] */ | ||
589 | fc = v9fs_create_common(bufp, size, TATTACH); | ||
590 | if (IS_ERR(fc)) | ||
591 | goto error; | ||
592 | |||
593 | v9fs_put_int32(bufp, fid, &fc->params.tattach.fid); | ||
594 | v9fs_put_int32(bufp, afid, &fc->params.tattach.afid); | ||
595 | v9fs_put_str(bufp, uname, &fc->params.tattach.uname); | ||
596 | v9fs_put_str(bufp, aname, &fc->params.tattach.aname); | ||
597 | |||
598 | error: | ||
599 | return fc; | ||
600 | } | ||
601 | |||
602 | struct v9fs_fcall *v9fs_create_tflush(u16 oldtag) | ||
603 | { | ||
604 | int size; | ||
605 | struct v9fs_fcall *fc; | ||
606 | struct cbuf buffer; | ||
607 | struct cbuf *bufp = &buffer; | ||
608 | |||
609 | size = 2; /* oldtag[2] */ | ||
610 | fc = v9fs_create_common(bufp, size, TFLUSH); | ||
611 | if (IS_ERR(fc)) | ||
612 | goto error; | ||
613 | |||
614 | v9fs_put_int16(bufp, oldtag, &fc->params.tflush.oldtag); | ||
615 | |||
616 | if (buf_check_overflow(bufp)) { | ||
617 | kfree(fc); | ||
618 | fc = ERR_PTR(-ENOMEM); | ||
619 | } | ||
620 | error: | ||
621 | return fc; | ||
622 | } | ||
623 | |||
624 | struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname, | ||
625 | char **wnames) | ||
626 | { | ||
627 | int i, size; | ||
628 | struct v9fs_fcall *fc; | ||
629 | struct cbuf buffer; | ||
630 | struct cbuf *bufp = &buffer; | ||
631 | |||
632 | if (nwname > V9FS_MAXWELEM) { | ||
633 | dprintk(DEBUG_ERROR, "nwname > %d\n", V9FS_MAXWELEM); | ||
634 | return NULL; | ||
635 | } | ||
636 | |||
637 | size = 4 + 4 + 2; /* fid[4] newfid[4] nwname[2] ... */ | ||
638 | for (i = 0; i < nwname; i++) { | ||
639 | size += 2 + strlen(wnames[i]); /* wname[s] */ | ||
640 | } | ||
641 | |||
642 | fc = v9fs_create_common(bufp, size, TWALK); | ||
643 | if (IS_ERR(fc)) | ||
644 | goto error; | ||
645 | |||
646 | v9fs_put_int32(bufp, fid, &fc->params.twalk.fid); | ||
647 | v9fs_put_int32(bufp, newfid, &fc->params.twalk.newfid); | ||
648 | v9fs_put_int16(bufp, nwname, &fc->params.twalk.nwname); | ||
649 | for (i = 0; i < nwname; i++) { | ||
650 | v9fs_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]); | ||
651 | } | ||
652 | |||
653 | if (buf_check_overflow(bufp)) { | ||
654 | kfree(fc); | ||
655 | fc = ERR_PTR(-ENOMEM); | ||
656 | } | ||
657 | error: | ||
658 | return fc; | ||
659 | } | ||
660 | |||
661 | struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode) | ||
662 | { | ||
663 | int size; | ||
664 | struct v9fs_fcall *fc; | ||
665 | struct cbuf buffer; | ||
666 | struct cbuf *bufp = &buffer; | ||
667 | |||
668 | size = 4 + 1; /* fid[4] mode[1] */ | ||
669 | fc = v9fs_create_common(bufp, size, TOPEN); | ||
670 | if (IS_ERR(fc)) | ||
671 | goto error; | ||
672 | |||
673 | v9fs_put_int32(bufp, fid, &fc->params.topen.fid); | ||
674 | v9fs_put_int8(bufp, mode, &fc->params.topen.mode); | ||
675 | |||
676 | if (buf_check_overflow(bufp)) { | ||
677 | kfree(fc); | ||
678 | fc = ERR_PTR(-ENOMEM); | ||
679 | } | ||
680 | error: | ||
681 | return fc; | ||
682 | } | ||
683 | |||
684 | struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode) | ||
685 | { | ||
686 | int size; | ||
687 | struct v9fs_fcall *fc; | ||
688 | struct cbuf buffer; | ||
689 | struct cbuf *bufp = &buffer; | ||
690 | |||
691 | size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */ | ||
692 | fc = v9fs_create_common(bufp, size, TCREATE); | ||
693 | if (IS_ERR(fc)) | ||
694 | goto error; | ||
695 | |||
696 | v9fs_put_int32(bufp, fid, &fc->params.tcreate.fid); | ||
697 | v9fs_put_str(bufp, name, &fc->params.tcreate.name); | ||
698 | v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm); | ||
699 | v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode); | ||
700 | |||
701 | if (buf_check_overflow(bufp)) { | ||
702 | kfree(fc); | ||
703 | fc = ERR_PTR(-ENOMEM); | ||
704 | } | ||
705 | error: | ||
706 | return fc; | ||
707 | } | ||
708 | |||
709 | struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count) | ||
710 | { | ||
711 | int size; | ||
712 | struct v9fs_fcall *fc; | ||
713 | struct cbuf buffer; | ||
714 | struct cbuf *bufp = &buffer; | ||
715 | |||
716 | size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */ | ||
717 | fc = v9fs_create_common(bufp, size, TREAD); | ||
718 | if (IS_ERR(fc)) | ||
719 | goto error; | ||
720 | |||
721 | v9fs_put_int32(bufp, fid, &fc->params.tread.fid); | ||
722 | v9fs_put_int64(bufp, offset, &fc->params.tread.offset); | ||
723 | v9fs_put_int32(bufp, count, &fc->params.tread.count); | ||
724 | |||
725 | if (buf_check_overflow(bufp)) { | ||
726 | kfree(fc); | ||
727 | fc = ERR_PTR(-ENOMEM); | ||
728 | } | ||
729 | error: | ||
730 | return fc; | ||
731 | } | ||
732 | |||
733 | struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count, | ||
734 | const char __user * data) | ||
735 | { | ||
736 | int size, err; | ||
737 | struct v9fs_fcall *fc; | ||
738 | struct cbuf buffer; | ||
739 | struct cbuf *bufp = &buffer; | ||
740 | |||
741 | size = 4 + 8 + 4 + count; /* fid[4] offset[8] count[4] data[count] */ | ||
742 | fc = v9fs_create_common(bufp, size, TWRITE); | ||
743 | if (IS_ERR(fc)) | ||
744 | goto error; | ||
745 | |||
746 | v9fs_put_int32(bufp, fid, &fc->params.twrite.fid); | ||
747 | v9fs_put_int64(bufp, offset, &fc->params.twrite.offset); | ||
748 | v9fs_put_int32(bufp, count, &fc->params.twrite.count); | ||
749 | err = v9fs_put_user_data(bufp, data, count, &fc->params.twrite.data); | ||
750 | if (err) { | ||
751 | kfree(fc); | ||
752 | fc = ERR_PTR(err); | ||
753 | } | ||
754 | |||
755 | if (buf_check_overflow(bufp)) { | ||
756 | kfree(fc); | ||
757 | fc = ERR_PTR(-ENOMEM); | ||
758 | } | ||
759 | error: | ||
760 | return fc; | ||
761 | } | ||
762 | |||
763 | struct v9fs_fcall *v9fs_create_tclunk(u32 fid) | ||
764 | { | ||
765 | int size; | ||
766 | struct v9fs_fcall *fc; | ||
767 | struct cbuf buffer; | ||
768 | struct cbuf *bufp = &buffer; | ||
769 | |||
770 | size = 4; /* fid[4] */ | ||
771 | fc = v9fs_create_common(bufp, size, TCLUNK); | ||
772 | if (IS_ERR(fc)) | ||
773 | goto error; | ||
774 | |||
775 | v9fs_put_int32(bufp, fid, &fc->params.tclunk.fid); | ||
776 | |||
777 | if (buf_check_overflow(bufp)) { | ||
778 | kfree(fc); | ||
779 | fc = ERR_PTR(-ENOMEM); | ||
780 | } | ||
781 | error: | ||
782 | return fc; | ||
783 | } | ||
784 | |||
785 | struct v9fs_fcall *v9fs_create_tremove(u32 fid) | ||
786 | { | ||
787 | int size; | ||
788 | struct v9fs_fcall *fc; | ||
789 | struct cbuf buffer; | ||
790 | struct cbuf *bufp = &buffer; | ||
791 | |||
792 | size = 4; /* fid[4] */ | ||
793 | fc = v9fs_create_common(bufp, size, TREMOVE); | ||
794 | if (IS_ERR(fc)) | ||
795 | goto error; | ||
796 | |||
797 | v9fs_put_int32(bufp, fid, &fc->params.tremove.fid); | ||
798 | |||
799 | if (buf_check_overflow(bufp)) { | ||
800 | kfree(fc); | ||
801 | fc = ERR_PTR(-ENOMEM); | ||
802 | } | ||
803 | error: | ||
804 | return fc; | ||
805 | } | ||
806 | |||
807 | struct v9fs_fcall *v9fs_create_tstat(u32 fid) | ||
808 | { | ||
809 | int size; | ||
810 | struct v9fs_fcall *fc; | ||
811 | struct cbuf buffer; | ||
812 | struct cbuf *bufp = &buffer; | ||
813 | |||
814 | size = 4; /* fid[4] */ | ||
815 | fc = v9fs_create_common(bufp, size, TSTAT); | ||
816 | if (IS_ERR(fc)) | ||
817 | goto error; | ||
818 | |||
819 | v9fs_put_int32(bufp, fid, &fc->params.tstat.fid); | ||
820 | |||
821 | if (buf_check_overflow(bufp)) { | ||
822 | kfree(fc); | ||
823 | fc = ERR_PTR(-ENOMEM); | ||
824 | } | ||
825 | error: | ||
826 | return fc; | ||
827 | } | ||
828 | |||
829 | struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat, | ||
830 | int extended) | ||
831 | { | ||
832 | int size, statsz; | ||
833 | struct v9fs_fcall *fc; | ||
834 | struct cbuf buffer; | ||
835 | struct cbuf *bufp = &buffer; | ||
836 | |||
837 | statsz = v9fs_size_wstat(wstat, extended); | ||
838 | size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */ | ||
839 | fc = v9fs_create_common(bufp, size, TWSTAT); | ||
840 | if (IS_ERR(fc)) | ||
841 | goto error; | ||
842 | |||
843 | v9fs_put_int32(bufp, fid, &fc->params.twstat.fid); | ||
844 | buf_put_int16(bufp, statsz + 2); | ||
845 | v9fs_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, extended); | ||
846 | |||
847 | if (buf_check_overflow(bufp)) { | ||
848 | kfree(fc); | ||
849 | fc = ERR_PTR(-ENOMEM); | ||
850 | } | ||
851 | error: | ||
852 | return fc; | ||
712 | } | 853 | } |
diff --git a/fs/9p/conv.h b/fs/9p/conv.h index d5e33e17a685..26a736e4a2e7 100644 --- a/fs/9p/conv.h +++ b/fs/9p/conv.h | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * linux/fs/9p/conv.h | 2 | * linux/fs/9p/conv.h |
3 | * | 3 | * |
4 | * 9P protocol conversion definitions | 4 | * 9P protocol conversion definitions. |
5 | * | 5 | * |
6 | * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> | ||
6 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | 7 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> |
7 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> | 8 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> |
8 | * | 9 | * |
@@ -25,11 +26,26 @@ | |||
25 | */ | 26 | */ |
26 | 27 | ||
27 | int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat, | 28 | int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat, |
28 | u32 statlen, int extended); | ||
29 | int v9fs_serialize_fcall(struct v9fs_fcall *tcall, void *buf, u32 buflen, | ||
30 | int extended); | 29 | int extended); |
31 | int v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, | 30 | int v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, |
32 | int rcalllen, int extended); | 31 | int extended); |
32 | |||
33 | void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag); | ||
33 | 34 | ||
34 | /* this one is actually in error.c right now */ | 35 | struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version); |
35 | int v9fs_errstr2errno(char *errstr); | 36 | struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname); |
37 | struct v9fs_fcall *v9fs_create_tattach(u32 fid, u32 afid, char *uname, | ||
38 | char *aname); | ||
39 | struct v9fs_fcall *v9fs_create_tflush(u16 oldtag); | ||
40 | struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname, | ||
41 | char **wnames); | ||
42 | struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode); | ||
43 | struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode); | ||
44 | struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count); | ||
45 | struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count, | ||
46 | const char __user *data); | ||
47 | struct v9fs_fcall *v9fs_create_tclunk(u32 fid); | ||
48 | struct v9fs_fcall *v9fs_create_tremove(u32 fid); | ||
49 | struct v9fs_fcall *v9fs_create_tstat(u32 fid); | ||
50 | struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat, | ||
51 | int extended); | ||
diff --git a/fs/9p/debug.h b/fs/9p/debug.h index 4445f06919d9..fe551032788b 100644 --- a/fs/9p/debug.h +++ b/fs/9p/debug.h | |||
@@ -51,16 +51,23 @@ do { \ | |||
51 | #if DEBUG_DUMP_PKT | 51 | #if DEBUG_DUMP_PKT |
52 | static inline void dump_data(const unsigned char *data, unsigned int datalen) | 52 | static inline void dump_data(const unsigned char *data, unsigned int datalen) |
53 | { | 53 | { |
54 | int i, j; | 54 | int i, n; |
55 | int len = datalen; | 55 | char buf[5*8]; |
56 | 56 | ||
57 | printk(KERN_DEBUG "data "); | 57 | n = 0; |
58 | for (i = 0; i < len; i += 4) { | 58 | i = 0; |
59 | for (j = 0; (j < 4) && (i + j < len); j++) | 59 | while (i < datalen) { |
60 | printk(KERN_DEBUG "%02x", data[i + j]); | 60 | n += snprintf(buf+n, sizeof(buf)-n, "%02x", data[i++]); |
61 | printk(KERN_DEBUG " "); | 61 | if (i%4 == 0) |
62 | n += snprintf(buf+n, sizeof(buf)-n, " "); | ||
63 | |||
64 | if (i%16 == 0) { | ||
65 | dprintk(DEBUG_ERROR, "%s\n", buf); | ||
66 | n = 0; | ||
67 | } | ||
62 | } | 68 | } |
63 | printk(KERN_DEBUG "\n"); | 69 | |
70 | dprintk(DEBUG_ERROR, "%s\n", buf); | ||
64 | } | 71 | } |
65 | #else /* DEBUG_DUMP_PKT */ | 72 | #else /* DEBUG_DUMP_PKT */ |
66 | static inline void dump_data(const unsigned char *data, unsigned int datalen) | 73 | static inline void dump_data(const unsigned char *data, unsigned int datalen) |
diff --git a/fs/9p/error.c b/fs/9p/error.c index 834cb179e388..e4b6f8f38b6f 100644 --- a/fs/9p/error.c +++ b/fs/9p/error.c | |||
@@ -33,7 +33,6 @@ | |||
33 | 33 | ||
34 | #include <linux/list.h> | 34 | #include <linux/list.h> |
35 | #include <linux/jhash.h> | 35 | #include <linux/jhash.h> |
36 | #include <linux/string.h> | ||
37 | 36 | ||
38 | #include "debug.h" | 37 | #include "debug.h" |
39 | #include "error.h" | 38 | #include "error.h" |
@@ -55,7 +54,8 @@ int v9fs_error_init(void) | |||
55 | 54 | ||
56 | /* load initial error map into hash table */ | 55 | /* load initial error map into hash table */ |
57 | for (c = errmap; c->name != NULL; c++) { | 56 | for (c = errmap; c->name != NULL; c++) { |
58 | bucket = jhash(c->name, strlen(c->name), 0) % ERRHASHSZ; | 57 | c->namelen = strlen(c->name); |
58 | bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; | ||
59 | INIT_HLIST_NODE(&c->list); | 59 | INIT_HLIST_NODE(&c->list); |
60 | hlist_add_head(&c->list, &hash_errmap[bucket]); | 60 | hlist_add_head(&c->list, &hash_errmap[bucket]); |
61 | } | 61 | } |
@@ -69,15 +69,15 @@ int v9fs_error_init(void) | |||
69 | * | 69 | * |
70 | */ | 70 | */ |
71 | 71 | ||
72 | int v9fs_errstr2errno(char *errstr) | 72 | int v9fs_errstr2errno(char *errstr, int len) |
73 | { | 73 | { |
74 | int errno = 0; | 74 | int errno = 0; |
75 | struct hlist_node *p = NULL; | 75 | struct hlist_node *p = NULL; |
76 | struct errormap *c = NULL; | 76 | struct errormap *c = NULL; |
77 | int bucket = jhash(errstr, strlen(errstr), 0) % ERRHASHSZ; | 77 | int bucket = jhash(errstr, len, 0) % ERRHASHSZ; |
78 | 78 | ||
79 | hlist_for_each_entry(c, p, &hash_errmap[bucket], list) { | 79 | hlist_for_each_entry(c, p, &hash_errmap[bucket], list) { |
80 | if (!strcmp(c->name, errstr)) { | 80 | if (c->namelen==len && !memcmp(c->name, errstr, len)) { |
81 | errno = c->val; | 81 | errno = c->val; |
82 | break; | 82 | break; |
83 | } | 83 | } |
diff --git a/fs/9p/error.h b/fs/9p/error.h index 78f89acf7c9a..8b3176b3f658 100644 --- a/fs/9p/error.h +++ b/fs/9p/error.h | |||
@@ -36,6 +36,7 @@ struct errormap { | |||
36 | char *name; | 36 | char *name; |
37 | int val; | 37 | int val; |
38 | 38 | ||
39 | int namelen; | ||
39 | struct hlist_node list; | 40 | struct hlist_node list; |
40 | }; | 41 | }; |
41 | 42 | ||
@@ -175,4 +176,4 @@ static struct errormap errmap[] = { | |||
175 | }; | 176 | }; |
176 | 177 | ||
177 | extern int v9fs_error_init(void); | 178 | extern int v9fs_error_init(void); |
178 | extern int v9fs_errstr2errno(char *errstr); | 179 | extern int v9fs_errstr2errno(char *errstr, int len); |
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 60ef8aba757a..eda449778fa5 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
@@ -31,9 +31,6 @@ | |||
31 | #include "v9fs.h" | 31 | #include "v9fs.h" |
32 | #include "9p.h" | 32 | #include "9p.h" |
33 | #include "v9fs_vfs.h" | 33 | #include "v9fs_vfs.h" |
34 | #include "transport.h" | ||
35 | #include "mux.h" | ||
36 | #include "conv.h" | ||
37 | #include "fid.h" | 34 | #include "fid.h" |
38 | 35 | ||
39 | /** | 36 | /** |
diff --git a/fs/9p/mux.c b/fs/9p/mux.c index 62b6ad0767e1..f21cf5083973 100644 --- a/fs/9p/mux.c +++ b/fs/9p/mux.c | |||
@@ -35,8 +35,8 @@ | |||
35 | #include "debug.h" | 35 | #include "debug.h" |
36 | #include "v9fs.h" | 36 | #include "v9fs.h" |
37 | #include "9p.h" | 37 | #include "9p.h" |
38 | #include "transport.h" | ||
39 | #include "conv.h" | 38 | #include "conv.h" |
39 | #include "transport.h" | ||
40 | #include "mux.h" | 40 | #include "mux.h" |
41 | 41 | ||
42 | #define ERREQFLUSH 1 | 42 | #define ERREQFLUSH 1 |
@@ -74,6 +74,7 @@ struct v9fs_mux_data { | |||
74 | wait_queue_head_t equeue; | 74 | wait_queue_head_t equeue; |
75 | struct list_head req_list; | 75 | struct list_head req_list; |
76 | struct list_head unsent_req_list; | 76 | struct list_head unsent_req_list; |
77 | struct v9fs_fcall *rcall; | ||
77 | int rpos; | 78 | int rpos; |
78 | char *rbuf; | 79 | char *rbuf; |
79 | int wpos; | 80 | int wpos; |
@@ -101,11 +102,15 @@ struct v9fs_mux_rpc { | |||
101 | wait_queue_head_t wqueue; | 102 | wait_queue_head_t wqueue; |
102 | }; | 103 | }; |
103 | 104 | ||
105 | extern int v9fs_errstr2errno(char *str, int len); | ||
106 | |||
104 | static int v9fs_poll_proc(void *); | 107 | static int v9fs_poll_proc(void *); |
105 | static void v9fs_read_work(void *); | 108 | static void v9fs_read_work(void *); |
106 | static void v9fs_write_work(void *); | 109 | static void v9fs_write_work(void *); |
107 | static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address, | 110 | static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address, |
108 | poll_table * p); | 111 | poll_table * p); |
112 | static u16 v9fs_mux_get_tag(struct v9fs_mux_data *); | ||
113 | static void v9fs_mux_put_tag(struct v9fs_mux_data *, u16); | ||
109 | 114 | ||
110 | static DECLARE_MUTEX(v9fs_mux_task_lock); | 115 | static DECLARE_MUTEX(v9fs_mux_task_lock); |
111 | static struct workqueue_struct *v9fs_mux_wq; | 116 | static struct workqueue_struct *v9fs_mux_wq; |
@@ -166,8 +171,9 @@ static void v9fs_mux_poll_start(struct v9fs_mux_data *m) | |||
166 | if (v9fs_mux_poll_tasks[i].task == NULL) { | 171 | if (v9fs_mux_poll_tasks[i].task == NULL) { |
167 | vpt = &v9fs_mux_poll_tasks[i]; | 172 | vpt = &v9fs_mux_poll_tasks[i]; |
168 | dprintk(DEBUG_MUX, "create proc %p\n", vpt); | 173 | dprintk(DEBUG_MUX, "create proc %p\n", vpt); |
169 | vpt->task = kthread_create(v9fs_poll_proc, | 174 | vpt->task = |
170 | vpt, "v9fs-poll"); | 175 | kthread_create(v9fs_poll_proc, vpt, |
176 | "v9fs-poll"); | ||
171 | INIT_LIST_HEAD(&vpt->mux_list); | 177 | INIT_LIST_HEAD(&vpt->mux_list); |
172 | vpt->muxnum = 0; | 178 | vpt->muxnum = 0; |
173 | v9fs_mux_poll_task_num++; | 179 | v9fs_mux_poll_task_num++; |
@@ -253,7 +259,7 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, | |||
253 | struct v9fs_mux_data *m, *mtmp; | 259 | struct v9fs_mux_data *m, *mtmp; |
254 | 260 | ||
255 | dprintk(DEBUG_MUX, "transport %p msize %d\n", trans, msize); | 261 | dprintk(DEBUG_MUX, "transport %p msize %d\n", trans, msize); |
256 | m = kmalloc(sizeof(struct v9fs_mux_data) + 2 * msize, GFP_KERNEL); | 262 | m = kmalloc(sizeof(struct v9fs_mux_data), GFP_KERNEL); |
257 | if (!m) | 263 | if (!m) |
258 | return ERR_PTR(-ENOMEM); | 264 | return ERR_PTR(-ENOMEM); |
259 | 265 | ||
@@ -268,10 +274,11 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, | |||
268 | init_waitqueue_head(&m->equeue); | 274 | init_waitqueue_head(&m->equeue); |
269 | INIT_LIST_HEAD(&m->req_list); | 275 | INIT_LIST_HEAD(&m->req_list); |
270 | INIT_LIST_HEAD(&m->unsent_req_list); | 276 | INIT_LIST_HEAD(&m->unsent_req_list); |
277 | m->rcall = NULL; | ||
271 | m->rpos = 0; | 278 | m->rpos = 0; |
272 | m->rbuf = (char *)m + sizeof(struct v9fs_mux_data); | 279 | m->rbuf = NULL; |
273 | m->wpos = m->wsize = 0; | 280 | m->wpos = m->wsize = 0; |
274 | m->wbuf = m->rbuf + msize; | 281 | m->wbuf = NULL; |
275 | INIT_WORK(&m->rq, v9fs_read_work, m); | 282 | INIT_WORK(&m->rq, v9fs_read_work, m); |
276 | INIT_WORK(&m->wq, v9fs_write_work, m); | 283 | INIT_WORK(&m->wq, v9fs_write_work, m); |
277 | m->wsched = 0; | 284 | m->wsched = 0; |
@@ -427,29 +434,6 @@ static int v9fs_poll_proc(void *a) | |||
427 | return 0; | 434 | return 0; |
428 | } | 435 | } |
429 | 436 | ||
430 | static inline int v9fs_write_req(struct v9fs_mux_data *m, struct v9fs_req *req) | ||
431 | { | ||
432 | int n; | ||
433 | |||
434 | list_move_tail(&req->req_list, &m->req_list); | ||
435 | n = v9fs_serialize_fcall(req->tcall, m->wbuf, m->msize, *m->extended); | ||
436 | if (n < 0) { | ||
437 | req->err = n; | ||
438 | list_del(&req->req_list); | ||
439 | if (req->cb) { | ||
440 | spin_unlock(&m->lock); | ||
441 | (*req->cb) (req->cba, req->tcall, req->rcall, req->err); | ||
442 | req->cb = NULL; | ||
443 | spin_lock(&m->lock); | ||
444 | } else | ||
445 | kfree(req->rcall); | ||
446 | |||
447 | kfree(req); | ||
448 | } | ||
449 | |||
450 | return n; | ||
451 | } | ||
452 | |||
453 | /** | 437 | /** |
454 | * v9fs_write_work - called when a transport can send some data | 438 | * v9fs_write_work - called when a transport can send some data |
455 | */ | 439 | */ |
@@ -457,7 +441,7 @@ static void v9fs_write_work(void *a) | |||
457 | { | 441 | { |
458 | int n, err; | 442 | int n, err; |
459 | struct v9fs_mux_data *m; | 443 | struct v9fs_mux_data *m; |
460 | struct v9fs_req *req, *rtmp; | 444 | struct v9fs_req *req; |
461 | 445 | ||
462 | m = a; | 446 | m = a; |
463 | 447 | ||
@@ -472,17 +456,15 @@ static void v9fs_write_work(void *a) | |||
472 | return; | 456 | return; |
473 | } | 457 | } |
474 | 458 | ||
475 | err = 0; | ||
476 | spin_lock(&m->lock); | 459 | spin_lock(&m->lock); |
477 | list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, | 460 | req = |
478 | req_list) { | 461 | list_entry(m->unsent_req_list.next, struct v9fs_req, |
479 | err = v9fs_write_req(m, req); | 462 | req_list); |
480 | if (err > 0) | 463 | list_move_tail(&req->req_list, &m->req_list); |
481 | break; | 464 | m->wbuf = req->tcall->sdata; |
482 | } | 465 | m->wsize = req->tcall->size; |
483 | |||
484 | m->wsize = err; | ||
485 | m->wpos = 0; | 466 | m->wpos = 0; |
467 | dump_data(m->wbuf, m->wsize); | ||
486 | spin_unlock(&m->lock); | 468 | spin_unlock(&m->lock); |
487 | } | 469 | } |
488 | 470 | ||
@@ -526,24 +508,23 @@ static void v9fs_write_work(void *a) | |||
526 | static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) | 508 | static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) |
527 | { | 509 | { |
528 | int ecode, tag; | 510 | int ecode, tag; |
529 | char *ename; | 511 | struct v9fs_str *ename; |
530 | 512 | ||
531 | tag = req->tag; | 513 | tag = req->tag; |
532 | if (req->rcall->id == RERROR && !req->err) { | 514 | if (req->rcall->id == RERROR && !req->err) { |
533 | ecode = req->rcall->params.rerror.errno; | 515 | ecode = req->rcall->params.rerror.errno; |
534 | ename = req->rcall->params.rerror.error; | 516 | ename = &req->rcall->params.rerror.error; |
535 | 517 | ||
536 | dprintk(DEBUG_MUX, "Rerror %s\n", ename); | 518 | dprintk(DEBUG_MUX, "Rerror %.*s\n", ename->len, ename->str); |
537 | 519 | ||
538 | if (*m->extended) | 520 | if (*m->extended) |
539 | req->err = -ecode; | 521 | req->err = -ecode; |
540 | 522 | ||
541 | if (!req->err) { | 523 | if (!req->err) { |
542 | req->err = v9fs_errstr2errno(ename); | 524 | req->err = v9fs_errstr2errno(ename->str, ename->len); |
543 | 525 | ||
544 | if (!req->err) { /* string match failed */ | 526 | if (!req->err) { /* string match failed */ |
545 | dprintk(DEBUG_ERROR, "unknown error: %s\n", | 527 | PRINT_FCALL_ERROR("unknown error", req->rcall); |
546 | ename); | ||
547 | } | 528 | } |
548 | 529 | ||
549 | if (!req->err) | 530 | if (!req->err) |
@@ -565,8 +546,7 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) | |||
565 | } else | 546 | } else |
566 | kfree(req->rcall); | 547 | kfree(req->rcall); |
567 | 548 | ||
568 | if (tag != V9FS_NOTAG) | 549 | v9fs_mux_put_tag(m, tag); |
569 | v9fs_put_idpool(tag, &m->tidpool); | ||
570 | 550 | ||
571 | wake_up(&m->equeue); | 551 | wake_up(&m->equeue); |
572 | kfree(req); | 552 | kfree(req); |
@@ -577,10 +557,11 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) | |||
577 | */ | 557 | */ |
578 | static void v9fs_read_work(void *a) | 558 | static void v9fs_read_work(void *a) |
579 | { | 559 | { |
580 | int n, err, rcallen; | 560 | int n, err; |
581 | struct v9fs_mux_data *m; | 561 | struct v9fs_mux_data *m; |
582 | struct v9fs_req *req, *rptr, *rreq; | 562 | struct v9fs_req *req, *rptr, *rreq; |
583 | struct v9fs_fcall *rcall; | 563 | struct v9fs_fcall *rcall; |
564 | char *rbuf; | ||
584 | 565 | ||
585 | m = a; | 566 | m = a; |
586 | 567 | ||
@@ -589,6 +570,19 @@ static void v9fs_read_work(void *a) | |||
589 | 570 | ||
590 | rcall = NULL; | 571 | rcall = NULL; |
591 | dprintk(DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos); | 572 | dprintk(DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos); |
573 | |||
574 | if (!m->rcall) { | ||
575 | m->rcall = | ||
576 | kmalloc(sizeof(struct v9fs_fcall) + m->msize, GFP_KERNEL); | ||
577 | if (!m->rcall) { | ||
578 | err = -ENOMEM; | ||
579 | goto error; | ||
580 | } | ||
581 | |||
582 | m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall); | ||
583 | m->rpos = 0; | ||
584 | } | ||
585 | |||
592 | clear_bit(Rpending, &m->wsched); | 586 | clear_bit(Rpending, &m->wsched); |
593 | err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos); | 587 | err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos); |
594 | dprintk(DEBUG_MUX, "mux %p got %d bytes\n", m, err); | 588 | dprintk(DEBUG_MUX, "mux %p got %d bytes\n", m, err); |
@@ -613,21 +607,32 @@ static void v9fs_read_work(void *a) | |||
613 | if (m->rpos < n) | 607 | if (m->rpos < n) |
614 | break; | 608 | break; |
615 | 609 | ||
616 | rcallen = n + V9FS_FCALLHDRSZ; | ||
617 | rcall = kmalloc(rcallen, GFP_KERNEL); | ||
618 | if (!rcall) { | ||
619 | err = -ENOMEM; | ||
620 | goto error; | ||
621 | } | ||
622 | |||
623 | dump_data(m->rbuf, n); | 610 | dump_data(m->rbuf, n); |
624 | err = v9fs_deserialize_fcall(m->rbuf, n, rcall, rcallen, | 611 | err = |
625 | *m->extended); | 612 | v9fs_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended); |
626 | if (err < 0) { | 613 | if (err < 0) { |
627 | kfree(rcall); | ||
628 | goto error; | 614 | goto error; |
629 | } | 615 | } |
630 | 616 | ||
617 | rcall = m->rcall; | ||
618 | rbuf = m->rbuf; | ||
619 | if (m->rpos > n) { | ||
620 | m->rcall = kmalloc(sizeof(struct v9fs_fcall) + m->msize, | ||
621 | GFP_KERNEL); | ||
622 | if (!m->rcall) { | ||
623 | err = -ENOMEM; | ||
624 | goto error; | ||
625 | } | ||
626 | |||
627 | m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall); | ||
628 | memmove(m->rbuf, rbuf + n, m->rpos - n); | ||
629 | m->rpos -= n; | ||
630 | } else { | ||
631 | m->rcall = NULL; | ||
632 | m->rbuf = NULL; | ||
633 | m->rpos = 0; | ||
634 | } | ||
635 | |||
631 | dprintk(DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, rcall->id, | 636 | dprintk(DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, rcall->id, |
632 | rcall->tag); | 637 | rcall->tag); |
633 | 638 | ||
@@ -642,6 +647,7 @@ static void v9fs_read_work(void *a) | |||
642 | process_request(m, req); | 647 | process_request(m, req); |
643 | break; | 648 | break; |
644 | } | 649 | } |
650 | |||
645 | } | 651 | } |
646 | 652 | ||
647 | if (!req) { | 653 | if (!req) { |
@@ -652,10 +658,6 @@ static void v9fs_read_work(void *a) | |||
652 | m, rcall->id, rcall->tag); | 658 | m, rcall->id, rcall->tag); |
653 | kfree(rcall); | 659 | kfree(rcall); |
654 | } | 660 | } |
655 | |||
656 | if (m->rpos > n) | ||
657 | memmove(m->rbuf, m->rbuf + n, m->rpos - n); | ||
658 | m->rpos -= n; | ||
659 | } | 661 | } |
660 | 662 | ||
661 | if (!list_empty(&m->req_list)) { | 663 | if (!list_empty(&m->req_list)) { |
@@ -710,12 +712,13 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m, | |||
710 | if (tc->id == TVERSION) | 712 | if (tc->id == TVERSION) |
711 | n = V9FS_NOTAG; | 713 | n = V9FS_NOTAG; |
712 | else | 714 | else |
713 | n = v9fs_get_idpool(&m->tidpool); | 715 | n = v9fs_mux_get_tag(m); |
714 | 716 | ||
715 | if (n < 0) | 717 | if (n < 0) |
716 | return ERR_PTR(-ENOMEM); | 718 | return ERR_PTR(-ENOMEM); |
717 | 719 | ||
718 | tc->tag = n; | 720 | v9fs_set_tag(tc, n); |
721 | |||
719 | req->tag = n; | 722 | req->tag = n; |
720 | req->tcall = tc; | 723 | req->tcall = tc; |
721 | req->rcall = NULL; | 724 | req->rcall = NULL; |
@@ -773,9 +776,7 @@ v9fs_mux_flush_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc, | |||
773 | if (!cb) | 776 | if (!cb) |
774 | spin_unlock(&m->lock); | 777 | spin_unlock(&m->lock); |
775 | 778 | ||
776 | if (v9fs_check_idpool(tag, &m->tidpool)) | 779 | v9fs_mux_put_tag(m, tag); |
777 | v9fs_put_idpool(tag, &m->tidpool); | ||
778 | |||
779 | kfree(tc); | 780 | kfree(tc); |
780 | kfree(rc); | 781 | kfree(rc); |
781 | } | 782 | } |
@@ -787,10 +788,7 @@ v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req) | |||
787 | 788 | ||
788 | dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); | 789 | dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); |
789 | 790 | ||
790 | fc = kmalloc(sizeof(struct v9fs_fcall), GFP_KERNEL); | 791 | fc = v9fs_create_tflush(req->tag); |
791 | fc->id = TFLUSH; | ||
792 | fc->params.tflush.oldtag = req->tag; | ||
793 | |||
794 | v9fs_send_request(m, fc, v9fs_mux_flush_cb, m); | 792 | v9fs_send_request(m, fc, v9fs_mux_flush_cb, m); |
795 | } | 793 | } |
796 | 794 | ||
@@ -939,3 +937,20 @@ void v9fs_mux_cancel(struct v9fs_mux_data *m, int err) | |||
939 | 937 | ||
940 | wake_up(&m->equeue); | 938 | wake_up(&m->equeue); |
941 | } | 939 | } |
940 | |||
941 | static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m) | ||
942 | { | ||
943 | int tag; | ||
944 | |||
945 | tag = v9fs_get_idpool(&m->tidpool); | ||
946 | if (tag < 0) | ||
947 | return V9FS_NOTAG; | ||
948 | else | ||
949 | return (u16) tag; | ||
950 | } | ||
951 | |||
952 | static void v9fs_mux_put_tag(struct v9fs_mux_data *m, u16 tag) | ||
953 | { | ||
954 | if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tidpool)) | ||
955 | v9fs_put_idpool(tag, &m->tidpool); | ||
956 | } | ||
diff --git a/fs/9p/trans_sock.c b/fs/9p/trans_sock.c index 9ef404c75c8f..44e830697acb 100644 --- a/fs/9p/trans_sock.c +++ b/fs/9p/trans_sock.c | |||
@@ -110,7 +110,6 @@ static int v9fs_sock_send(struct v9fs_transport *trans, void *v, int len) | |||
110 | if (!(ts->filp->f_flags & O_NONBLOCK)) | 110 | if (!(ts->filp->f_flags & O_NONBLOCK)) |
111 | dprintk(DEBUG_ERROR, "blocking write ...\n"); | 111 | dprintk(DEBUG_ERROR, "blocking write ...\n"); |
112 | 112 | ||
113 | dump_data(v, len); | ||
114 | oldfs = get_fs(); | 113 | oldfs = get_fs(); |
115 | set_fs(get_ds()); | 114 | set_fs(get_ds()); |
116 | ret = vfs_write(ts->filp, (void __user *)v, len, &ts->filp->f_pos); | 115 | ret = vfs_write(ts->filp, (void __user *)v, len, &ts->filp->f_pos); |
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 5e0f79355fdf..519b21d8b15b 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include "v9fs_vfs.h" | 37 | #include "v9fs_vfs.h" |
38 | #include "transport.h" | 38 | #include "transport.h" |
39 | #include "mux.h" | 39 | #include "mux.h" |
40 | #include "conv.h" | ||
41 | 40 | ||
42 | /* TODO: sysfs or debugfs interface */ | 41 | /* TODO: sysfs or debugfs interface */ |
43 | int v9fs_debug_level = 0; /* feature-rific global debug level */ | 42 | int v9fs_debug_level = 0; /* feature-rific global debug level */ |
@@ -353,7 +352,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses, | |||
353 | } | 352 | } |
354 | 353 | ||
355 | /* Really should check for 9P1 and report error */ | 354 | /* Really should check for 9P1 and report error */ |
356 | if (!strcmp(fcall->params.rversion.version, "9P2000.u")) { | 355 | if (!v9fs_str_compare("9P2000.u", &fcall->params.rversion.version)) { |
357 | dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n"); | 356 | dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n"); |
358 | v9ses->extended = 1; | 357 | v9ses->extended = 1; |
359 | } else { | 358 | } else { |
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 2f2cea7ee3e7..c78502ad00ed 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
@@ -45,9 +45,8 @@ extern struct dentry_operations v9fs_dentry_operations; | |||
45 | 45 | ||
46 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); | 46 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); |
47 | ino_t v9fs_qid2ino(struct v9fs_qid *qid); | 47 | ino_t v9fs_qid2ino(struct v9fs_qid *qid); |
48 | void v9fs_mistat2inode(struct v9fs_stat *, struct inode *, | 48 | void v9fs_stat2inode(struct v9fs_stat *, struct inode *, struct super_block *); |
49 | struct super_block *); | ||
50 | int v9fs_dir_release(struct inode *inode, struct file *filp); | 49 | int v9fs_dir_release(struct inode *inode, struct file *filp); |
51 | int v9fs_file_open(struct inode *inode, struct file *file); | 50 | int v9fs_file_open(struct inode *inode, struct file *file); |
52 | void v9fs_inode2mistat(struct inode *inode, struct v9fs_stat *mistat); | 51 | void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat); |
53 | void v9fs_dentry_release(struct dentry *); | 52 | void v9fs_dentry_release(struct dentry *); |
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index 4887df767394..2dd806dac9f1 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include "v9fs.h" | 40 | #include "v9fs.h" |
41 | #include "9p.h" | 41 | #include "9p.h" |
42 | #include "v9fs_vfs.h" | 42 | #include "v9fs_vfs.h" |
43 | #include "conv.h" | ||
44 | #include "fid.h" | 43 | #include "fid.h" |
45 | 44 | ||
46 | /** | 45 | /** |
@@ -108,7 +107,8 @@ void v9fs_dentry_release(struct dentry *dentry) | |||
108 | err = v9fs_t_clunk(current_fid->v9ses, current_fid->fid); | 107 | err = v9fs_t_clunk(current_fid->v9ses, current_fid->fid); |
109 | 108 | ||
110 | if (err < 0) | 109 | if (err < 0) |
111 | dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); | 110 | dprintk(DEBUG_ERROR, "clunk failed: %d name %s\n", |
111 | err, dentry->d_iname); | ||
112 | 112 | ||
113 | v9fs_fid_destroy(current_fid); | 113 | v9fs_fid_destroy(current_fid); |
114 | } | 114 | } |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 3893dd307ddb..ae6d032b9b59 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -37,8 +37,8 @@ | |||
37 | #include "debug.h" | 37 | #include "debug.h" |
38 | #include "v9fs.h" | 38 | #include "v9fs.h" |
39 | #include "9p.h" | 39 | #include "9p.h" |
40 | #include "v9fs_vfs.h" | ||
41 | #include "conv.h" | 40 | #include "conv.h" |
41 | #include "v9fs_vfs.h" | ||
42 | #include "fid.h" | 42 | #include "fid.h" |
43 | 43 | ||
44 | /** | 44 | /** |
@@ -77,17 +77,13 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
77 | unsigned int i, n, s; | 77 | unsigned int i, n, s; |
78 | int fid = -1; | 78 | int fid = -1; |
79 | int ret = 0; | 79 | int ret = 0; |
80 | struct v9fs_stat *mi = NULL; | 80 | struct v9fs_stat stat; |
81 | int over = 0; | 81 | int over = 0; |
82 | 82 | ||
83 | dprintk(DEBUG_VFS, "name %s\n", filp->f_dentry->d_name.name); | 83 | dprintk(DEBUG_VFS, "name %s\n", filp->f_dentry->d_name.name); |
84 | 84 | ||
85 | fid = file->fid; | 85 | fid = file->fid; |
86 | 86 | ||
87 | mi = kmalloc(v9ses->maxdata, GFP_KERNEL); | ||
88 | if (!mi) | ||
89 | return -ENOMEM; | ||
90 | |||
91 | if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) { | 87 | if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) { |
92 | kfree(file->rdir_fcall); | 88 | kfree(file->rdir_fcall); |
93 | file->rdir_fcall = NULL; | 89 | file->rdir_fcall = NULL; |
@@ -99,18 +95,18 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
99 | while (i < n) { | 95 | while (i < n) { |
100 | s = v9fs_deserialize_stat( | 96 | s = v9fs_deserialize_stat( |
101 | file->rdir_fcall->params.rread.data + i, | 97 | file->rdir_fcall->params.rread.data + i, |
102 | n - i, mi, v9ses->maxdata, v9ses->extended); | 98 | n - i, &stat, v9ses->extended); |
103 | 99 | ||
104 | if (s == 0) { | 100 | if (s == 0) { |
105 | dprintk(DEBUG_ERROR, | 101 | dprintk(DEBUG_ERROR, |
106 | "error while deserializing mistat\n"); | 102 | "error while deserializing stat\n"); |
107 | ret = -EIO; | 103 | ret = -EIO; |
108 | goto FreeStructs; | 104 | goto FreeStructs; |
109 | } | 105 | } |
110 | 106 | ||
111 | over = filldir(dirent, mi->name, strlen(mi->name), | 107 | over = filldir(dirent, stat.name.str, stat.name.len, |
112 | filp->f_pos, v9fs_qid2ino(&mi->qid), | 108 | filp->f_pos, v9fs_qid2ino(&stat.qid), |
113 | dt_type(mi)); | 109 | dt_type(&stat)); |
114 | 110 | ||
115 | if (over) { | 111 | if (over) { |
116 | file->rdir_fpos = i; | 112 | file->rdir_fpos = i; |
@@ -130,7 +126,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
130 | 126 | ||
131 | while (!over) { | 127 | while (!over) { |
132 | ret = v9fs_t_read(v9ses, fid, filp->f_pos, | 128 | ret = v9fs_t_read(v9ses, fid, filp->f_pos, |
133 | v9ses->maxdata-V9FS_IOHDRSZ, &fcall); | 129 | v9ses->maxdata-V9FS_IOHDRSZ, &fcall); |
134 | if (ret < 0) { | 130 | if (ret < 0) { |
135 | dprintk(DEBUG_ERROR, "error while reading: %d: %p\n", | 131 | dprintk(DEBUG_ERROR, "error while reading: %d: %p\n", |
136 | ret, fcall); | 132 | ret, fcall); |
@@ -142,17 +138,17 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
142 | i = 0; | 138 | i = 0; |
143 | while (i < n) { | 139 | while (i < n) { |
144 | s = v9fs_deserialize_stat(fcall->params.rread.data + i, | 140 | s = v9fs_deserialize_stat(fcall->params.rread.data + i, |
145 | n - i, mi, v9ses->maxdata, v9ses->extended); | 141 | n - i, &stat, v9ses->extended); |
146 | 142 | ||
147 | if (s == 0) { | 143 | if (s == 0) { |
148 | dprintk(DEBUG_ERROR, | 144 | dprintk(DEBUG_ERROR, |
149 | "error while deserializing mistat\n"); | 145 | "error while deserializing stat\n"); |
150 | return -EIO; | 146 | return -EIO; |
151 | } | 147 | } |
152 | 148 | ||
153 | over = filldir(dirent, mi->name, strlen(mi->name), | 149 | over = filldir(dirent, stat.name.str, stat.name.len, |
154 | filp->f_pos, v9fs_qid2ino(&mi->qid), | 150 | filp->f_pos, v9fs_qid2ino(&stat.qid), |
155 | dt_type(mi)); | 151 | dt_type(&stat)); |
156 | 152 | ||
157 | if (over) { | 153 | if (over) { |
158 | file->rdir_fcall = fcall; | 154 | file->rdir_fcall = fcall; |
@@ -171,7 +167,6 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
171 | 167 | ||
172 | FreeStructs: | 168 | FreeStructs: |
173 | kfree(fcall); | 169 | kfree(fcall); |
174 | kfree(mi); | ||
175 | return ret; | 170 | return ret; |
176 | } | 171 | } |
177 | 172 | ||
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index e13577da9130..6852f0eb96ed 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/string.h> | 32 | #include <linux/string.h> |
33 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
34 | #include <linux/inet.h> | 34 | #include <linux/inet.h> |
35 | #include <linux/version.h> | ||
35 | #include <linux/list.h> | 36 | #include <linux/list.h> |
36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
37 | #include <linux/idr.h> | 38 | #include <linux/idr.h> |
@@ -117,9 +118,7 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
117 | 118 | ||
118 | result = v9fs_t_open(v9ses, newfid, open_mode, &fcall); | 119 | result = v9fs_t_open(v9ses, newfid, open_mode, &fcall); |
119 | if (result < 0) { | 120 | if (result < 0) { |
120 | dprintk(DEBUG_ERROR, | 121 | PRINT_FCALL_ERROR("open failed", fcall); |
121 | "open failed, open_mode 0x%x: %s\n", open_mode, | ||
122 | FCALL_ERROR(fcall)); | ||
123 | kfree(fcall); | 122 | kfree(fcall); |
124 | return result; | 123 | return result; |
125 | } | 124 | } |
@@ -256,7 +255,6 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
256 | int result = -EIO; | 255 | int result = -EIO; |
257 | int rsize = 0; | 256 | int rsize = 0; |
258 | int total = 0; | 257 | int total = 0; |
259 | char *buf; | ||
260 | 258 | ||
261 | dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, | 259 | dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, |
262 | (int)*offset); | 260 | (int)*offset); |
@@ -264,28 +262,14 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
264 | if (v9fid->iounit != 0 && rsize > v9fid->iounit) | 262 | if (v9fid->iounit != 0 && rsize > v9fid->iounit) |
265 | rsize = v9fid->iounit; | 263 | rsize = v9fid->iounit; |
266 | 264 | ||
267 | buf = kmalloc(v9ses->maxdata - V9FS_IOHDRSZ, GFP_KERNEL); | ||
268 | if (!buf) | ||
269 | return -ENOMEM; | ||
270 | |||
271 | do { | 265 | do { |
272 | if (count < rsize) | 266 | if (count < rsize) |
273 | rsize = count; | 267 | rsize = count; |
274 | 268 | ||
275 | result = copy_from_user(buf, data, rsize); | 269 | result = v9fs_t_write(v9ses, fid, *offset, rsize, data, &fcall); |
276 | if (result) { | ||
277 | dprintk(DEBUG_ERROR, "Problem copying from user\n"); | ||
278 | kfree(buf); | ||
279 | return -EFAULT; | ||
280 | } | ||
281 | |||
282 | dump_data(buf, rsize); | ||
283 | result = v9fs_t_write(v9ses, fid, *offset, rsize, buf, &fcall); | ||
284 | if (result < 0) { | 270 | if (result < 0) { |
285 | eprintk(KERN_ERR, "error while writing: %s(%d)\n", | 271 | PRINT_FCALL_ERROR("error while writing", fcall); |
286 | FCALL_ERROR(fcall), result); | ||
287 | kfree(fcall); | 272 | kfree(fcall); |
288 | kfree(buf); | ||
289 | return result; | 273 | return result; |
290 | } else | 274 | } else |
291 | *offset += result; | 275 | *offset += result; |
@@ -305,7 +289,6 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
305 | total += result; | 289 | total += result; |
306 | } while (count); | 290 | } while (count); |
307 | 291 | ||
308 | kfree(buf); | ||
309 | return total; | 292 | return total; |
310 | } | 293 | } |
311 | 294 | ||
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index f11edde6432e..742bcd0dc4a7 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include "v9fs.h" | 40 | #include "v9fs.h" |
41 | #include "9p.h" | 41 | #include "9p.h" |
42 | #include "v9fs_vfs.h" | 42 | #include "v9fs_vfs.h" |
43 | #include "conv.h" | ||
44 | #include "fid.h" | 43 | #include "fid.h" |
45 | 44 | ||
46 | static struct inode_operations v9fs_dir_inode_operations; | 45 | static struct inode_operations v9fs_dir_inode_operations; |
@@ -127,100 +126,32 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) | |||
127 | } | 126 | } |
128 | 127 | ||
129 | /** | 128 | /** |
130 | * v9fs_blank_mistat - helper function to setup a 9P stat structure | 129 | * v9fs_blank_wstat - helper function to setup a 9P stat structure |
131 | * @v9ses: 9P session info (for determining extended mode) | 130 | * @v9ses: 9P session info (for determining extended mode) |
132 | * @mistat: structure to initialize | 131 | * @wstat: structure to initialize |
133 | * | 132 | * |
134 | */ | 133 | */ |
135 | 134 | ||
136 | static void | 135 | static void |
137 | v9fs_blank_mistat(struct v9fs_session_info *v9ses, struct v9fs_stat *mistat) | 136 | v9fs_blank_wstat(struct v9fs_wstat *wstat) |
138 | { | 137 | { |
139 | mistat->type = ~0; | 138 | wstat->type = ~0; |
140 | mistat->dev = ~0; | 139 | wstat->dev = ~0; |
141 | mistat->qid.type = ~0; | 140 | wstat->qid.type = ~0; |
142 | mistat->qid.version = ~0; | 141 | wstat->qid.version = ~0; |
143 | *((long long *)&mistat->qid.path) = ~0; | 142 | *((long long *)&wstat->qid.path) = ~0; |
144 | mistat->mode = ~0; | 143 | wstat->mode = ~0; |
145 | mistat->atime = ~0; | 144 | wstat->atime = ~0; |
146 | mistat->mtime = ~0; | 145 | wstat->mtime = ~0; |
147 | mistat->length = ~0; | 146 | wstat->length = ~0; |
148 | mistat->name = mistat->data; | 147 | wstat->name = NULL; |
149 | mistat->uid = mistat->data; | 148 | wstat->uid = NULL; |
150 | mistat->gid = mistat->data; | 149 | wstat->gid = NULL; |
151 | mistat->muid = mistat->data; | 150 | wstat->muid = NULL; |
152 | if (v9ses->extended) { | 151 | wstat->n_uid = ~0; |
153 | mistat->n_uid = ~0; | 152 | wstat->n_gid = ~0; |
154 | mistat->n_gid = ~0; | 153 | wstat->n_muid = ~0; |
155 | mistat->n_muid = ~0; | 154 | wstat->extension = NULL; |
156 | mistat->extension = mistat->data; | ||
157 | } | ||
158 | *mistat->data = 0; | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * v9fs_mistat2unix - convert mistat to unix stat | ||
163 | * @mistat: Plan 9 metadata (mistat) structure | ||
164 | * @buf: unix metadata (stat) structure to populate | ||
165 | * @sb: superblock | ||
166 | * | ||
167 | */ | ||
168 | |||
169 | static void | ||
170 | v9fs_mistat2unix(struct v9fs_stat *mistat, struct stat *buf, | ||
171 | struct super_block *sb) | ||
172 | { | ||
173 | struct v9fs_session_info *v9ses = sb ? sb->s_fs_info : NULL; | ||
174 | |||
175 | buf->st_nlink = 1; | ||
176 | |||
177 | buf->st_atime = mistat->atime; | ||
178 | buf->st_mtime = mistat->mtime; | ||
179 | buf->st_ctime = mistat->mtime; | ||
180 | |||
181 | buf->st_uid = (unsigned short)-1; | ||
182 | buf->st_gid = (unsigned short)-1; | ||
183 | |||
184 | if (v9ses && v9ses->extended) { | ||
185 | /* TODO: string to uid mapping via user-space daemon */ | ||
186 | if (mistat->n_uid != -1) | ||
187 | sscanf(mistat->uid, "%x", (unsigned int *)&buf->st_uid); | ||
188 | |||
189 | if (mistat->n_gid != -1) | ||
190 | sscanf(mistat->gid, "%x", (unsigned int *)&buf->st_gid); | ||
191 | } | ||
192 | |||
193 | if (buf->st_uid == (unsigned short)-1) | ||
194 | buf->st_uid = v9ses->uid; | ||
195 | if (buf->st_gid == (unsigned short)-1) | ||
196 | buf->st_gid = v9ses->gid; | ||
197 | |||
198 | buf->st_mode = p9mode2unixmode(v9ses, mistat->mode); | ||
199 | if ((S_ISBLK(buf->st_mode)) || (S_ISCHR(buf->st_mode))) { | ||
200 | char type = 0; | ||
201 | int major = -1; | ||
202 | int minor = -1; | ||
203 | sscanf(mistat->extension, "%c %u %u", &type, &major, &minor); | ||
204 | switch (type) { | ||
205 | case 'c': | ||
206 | buf->st_mode &= ~S_IFBLK; | ||
207 | buf->st_mode |= S_IFCHR; | ||
208 | break; | ||
209 | case 'b': | ||
210 | break; | ||
211 | default: | ||
212 | dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n", | ||
213 | type, mistat->extension); | ||
214 | }; | ||
215 | buf->st_rdev = MKDEV(major, minor); | ||
216 | } else | ||
217 | buf->st_rdev = 0; | ||
218 | |||
219 | buf->st_size = mistat->length; | ||
220 | |||
221 | buf->st_blksize = sb->s_blocksize; | ||
222 | buf->st_blocks = | ||
223 | (buf->st_size + buf->st_blksize - 1) >> sb->s_blocksize_bits; | ||
224 | } | 155 | } |
225 | 156 | ||
226 | /** | 157 | /** |
@@ -312,7 +243,6 @@ v9fs_create(struct inode *dir, | |||
312 | struct inode *file_inode = NULL; | 243 | struct inode *file_inode = NULL; |
313 | struct v9fs_fcall *fcall = NULL; | 244 | struct v9fs_fcall *fcall = NULL; |
314 | struct v9fs_qid qid; | 245 | struct v9fs_qid qid; |
315 | struct stat newstat; | ||
316 | int dirfidnum = -1; | 246 | int dirfidnum = -1; |
317 | long newfid = -1; | 247 | long newfid = -1; |
318 | int result = 0; | 248 | int result = 0; |
@@ -350,7 +280,7 @@ v9fs_create(struct inode *dir, | |||
350 | 280 | ||
351 | result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall); | 281 | result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall); |
352 | if (result < 0) { | 282 | if (result < 0) { |
353 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); | 283 | PRINT_FCALL_ERROR("clone error", fcall); |
354 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 284 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
355 | newfid = -1; | 285 | newfid = -1; |
356 | goto CleanUpFid; | 286 | goto CleanUpFid; |
@@ -362,9 +292,7 @@ v9fs_create(struct inode *dir, | |||
362 | result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name, | 292 | result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name, |
363 | perm, open_mode, &fcall); | 293 | perm, open_mode, &fcall); |
364 | if (result < 0) { | 294 | if (result < 0) { |
365 | dprintk(DEBUG_ERROR, "create fails: %s(%d)\n", | 295 | PRINT_FCALL_ERROR("create fails", fcall); |
366 | FCALL_ERROR(fcall), result); | ||
367 | |||
368 | goto CleanUpFid; | 296 | goto CleanUpFid; |
369 | } | 297 | } |
370 | 298 | ||
@@ -400,7 +328,7 @@ v9fs_create(struct inode *dir, | |||
400 | result = v9fs_t_walk(v9ses, dirfidnum, wfidno, | 328 | result = v9fs_t_walk(v9ses, dirfidnum, wfidno, |
401 | (char *) file_dentry->d_name.name, &fcall); | 329 | (char *) file_dentry->d_name.name, &fcall); |
402 | if (result < 0) { | 330 | if (result < 0) { |
403 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); | 331 | PRINT_FCALL_ERROR("clone error", fcall); |
404 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | 332 | v9fs_put_idpool(wfidno, &v9ses->fidpool); |
405 | wfidno = -1; | 333 | wfidno = -1; |
406 | goto CleanUpFid; | 334 | goto CleanUpFid; |
@@ -421,21 +349,21 @@ v9fs_create(struct inode *dir, | |||
421 | 349 | ||
422 | result = v9fs_t_stat(v9ses, wfidno, &fcall); | 350 | result = v9fs_t_stat(v9ses, wfidno, &fcall); |
423 | if (result < 0) { | 351 | if (result < 0) { |
424 | dprintk(DEBUG_ERROR, "stat error: %s(%d)\n", FCALL_ERROR(fcall), | 352 | PRINT_FCALL_ERROR("stat error", fcall); |
425 | result); | ||
426 | goto CleanUpFid; | 353 | goto CleanUpFid; |
427 | } | 354 | } |
428 | 355 | ||
429 | v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb); | ||
430 | 356 | ||
431 | file_inode = v9fs_get_inode(sb, newstat.st_mode); | 357 | file_inode = v9fs_get_inode(sb, |
358 | p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode)); | ||
359 | |||
432 | if ((!file_inode) || IS_ERR(file_inode)) { | 360 | if ((!file_inode) || IS_ERR(file_inode)) { |
433 | dprintk(DEBUG_ERROR, "create inode failed\n"); | 361 | dprintk(DEBUG_ERROR, "create inode failed\n"); |
434 | result = -EBADF; | 362 | result = -EBADF; |
435 | goto CleanUpFid; | 363 | goto CleanUpFid; |
436 | } | 364 | } |
437 | 365 | ||
438 | v9fs_mistat2inode(fcall->params.rstat.stat, file_inode, sb); | 366 | v9fs_stat2inode(&fcall->params.rstat.stat, file_inode, sb); |
439 | kfree(fcall); | 367 | kfree(fcall); |
440 | fcall = NULL; | 368 | fcall = NULL; |
441 | file_dentry->d_op = &v9fs_dentry_operations; | 369 | file_dentry->d_op = &v9fs_dentry_operations; |
@@ -500,10 +428,9 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
500 | } | 428 | } |
501 | 429 | ||
502 | result = v9fs_t_remove(v9ses, fid, &fcall); | 430 | result = v9fs_t_remove(v9ses, fid, &fcall); |
503 | if (result < 0) | 431 | if (result < 0) { |
504 | dprintk(DEBUG_ERROR, "remove of file fails: %s(%d)\n", | 432 | PRINT_FCALL_ERROR("remove fails", fcall); |
505 | FCALL_ERROR(fcall), result); | 433 | } else { |
506 | else { | ||
507 | v9fs_put_idpool(fid, &v9ses->fidpool); | 434 | v9fs_put_idpool(fid, &v9ses->fidpool); |
508 | v9fs_fid_destroy(v9fid); | 435 | v9fs_fid_destroy(v9fid); |
509 | } | 436 | } |
@@ -558,7 +485,6 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
558 | struct v9fs_fid *fid; | 485 | struct v9fs_fid *fid; |
559 | struct inode *inode; | 486 | struct inode *inode; |
560 | struct v9fs_fcall *fcall = NULL; | 487 | struct v9fs_fcall *fcall = NULL; |
561 | struct stat newstat; | ||
562 | int dirfidnum = -1; | 488 | int dirfidnum = -1; |
563 | int newfid = -1; | 489 | int newfid = -1; |
564 | int result = 0; | 490 | int result = 0; |
@@ -611,8 +537,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
611 | goto FreeFcall; | 537 | goto FreeFcall; |
612 | } | 538 | } |
613 | 539 | ||
614 | v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb); | 540 | inode = v9fs_get_inode(sb, p9mode2unixmode(v9ses, |
615 | inode = v9fs_get_inode(sb, newstat.st_mode); | 541 | fcall->params.rstat.stat.mode)); |
616 | 542 | ||
617 | if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) { | 543 | if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) { |
618 | eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n", | 544 | eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n", |
@@ -622,7 +548,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
622 | goto FreeFcall; | 548 | goto FreeFcall; |
623 | } | 549 | } |
624 | 550 | ||
625 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); | 551 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); |
626 | 552 | ||
627 | fid = v9fs_fid_create(dentry, v9ses, newfid, 0); | 553 | fid = v9fs_fid_create(dentry, v9ses, newfid, 0); |
628 | if (fid == NULL) { | 554 | if (fid == NULL) { |
@@ -631,10 +557,10 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
631 | goto FreeFcall; | 557 | goto FreeFcall; |
632 | } | 558 | } |
633 | 559 | ||
634 | fid->qid = fcall->params.rstat.stat->qid; | 560 | fid->qid = fcall->params.rstat.stat.qid; |
635 | 561 | ||
636 | dentry->d_op = &v9fs_dentry_operations; | 562 | dentry->d_op = &v9fs_dentry_operations; |
637 | v9fs_mistat2inode(fcall->params.rstat.stat, inode, inode->i_sb); | 563 | v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb); |
638 | 564 | ||
639 | d_add(dentry, inode); | 565 | d_add(dentry, inode); |
640 | kfree(fcall); | 566 | kfree(fcall); |
@@ -690,7 +616,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
690 | v9fs_fid_lookup(old_dentry->d_parent); | 616 | v9fs_fid_lookup(old_dentry->d_parent); |
691 | struct v9fs_fid *newdirfid = | 617 | struct v9fs_fid *newdirfid = |
692 | v9fs_fid_lookup(new_dentry->d_parent); | 618 | v9fs_fid_lookup(new_dentry->d_parent); |
693 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 619 | struct v9fs_wstat wstat; |
694 | struct v9fs_fcall *fcall = NULL; | 620 | struct v9fs_fcall *fcall = NULL; |
695 | int fid = -1; | 621 | int fid = -1; |
696 | int olddirfidnum = -1; | 622 | int olddirfidnum = -1; |
@@ -699,9 +625,6 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
699 | 625 | ||
700 | dprintk(DEBUG_VFS, "\n"); | 626 | dprintk(DEBUG_VFS, "\n"); |
701 | 627 | ||
702 | if (!mistat) | ||
703 | return -ENOMEM; | ||
704 | |||
705 | if ((!oldfid) || (!olddirfid) || (!newdirfid)) { | 628 | if ((!oldfid) || (!olddirfid) || (!newdirfid)) { |
706 | dprintk(DEBUG_ERROR, "problem with arguments\n"); | 629 | dprintk(DEBUG_ERROR, "problem with arguments\n"); |
707 | return -EBADF; | 630 | return -EBADF; |
@@ -725,26 +648,15 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
725 | goto FreeFcallnBail; | 648 | goto FreeFcallnBail; |
726 | } | 649 | } |
727 | 650 | ||
728 | v9fs_blank_mistat(v9ses, mistat); | 651 | v9fs_blank_wstat(&wstat); |
729 | 652 | wstat.muid = v9ses->name; | |
730 | strcpy(mistat->data + 1, v9ses->name); | 653 | wstat.name = (char *) new_dentry->d_name.name; |
731 | mistat->name = mistat->data + 1 + strlen(v9ses->name); | ||
732 | |||
733 | if (new_dentry->d_name.len > | ||
734 | (v9ses->maxdata - strlen(v9ses->name) - sizeof(struct v9fs_stat))) { | ||
735 | dprintk(DEBUG_ERROR, "new name too long\n"); | ||
736 | goto FreeFcallnBail; | ||
737 | } | ||
738 | 654 | ||
739 | strcpy(mistat->name, new_dentry->d_name.name); | 655 | retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall); |
740 | retval = v9fs_t_wstat(v9ses, fid, mistat, &fcall); | ||
741 | 656 | ||
742 | FreeFcallnBail: | 657 | FreeFcallnBail: |
743 | kfree(mistat); | ||
744 | |||
745 | if (retval < 0) | 658 | if (retval < 0) |
746 | dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n", | 659 | PRINT_FCALL_ERROR("wstat error", fcall); |
747 | FCALL_ERROR(fcall)); | ||
748 | 660 | ||
749 | kfree(fcall); | 661 | kfree(fcall); |
750 | return retval; | 662 | return retval; |
@@ -779,7 +691,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
779 | if (err < 0) | 691 | if (err < 0) |
780 | dprintk(DEBUG_ERROR, "stat error\n"); | 692 | dprintk(DEBUG_ERROR, "stat error\n"); |
781 | else { | 693 | else { |
782 | v9fs_mistat2inode(fcall->params.rstat.stat, dentry->d_inode, | 694 | v9fs_stat2inode(&fcall->params.rstat.stat, dentry->d_inode, |
783 | dentry->d_inode->i_sb); | 695 | dentry->d_inode->i_sb); |
784 | generic_fillattr(dentry->d_inode, stat); | 696 | generic_fillattr(dentry->d_inode, stat); |
785 | } | 697 | } |
@@ -800,57 +712,44 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
800 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 712 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
801 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); | 713 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
802 | struct v9fs_fcall *fcall = NULL; | 714 | struct v9fs_fcall *fcall = NULL; |
803 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 715 | struct v9fs_wstat wstat; |
804 | int res = -EPERM; | 716 | int res = -EPERM; |
805 | 717 | ||
806 | dprintk(DEBUG_VFS, "\n"); | 718 | dprintk(DEBUG_VFS, "\n"); |
807 | 719 | ||
808 | if (!mistat) | ||
809 | return -ENOMEM; | ||
810 | |||
811 | if (!fid) { | 720 | if (!fid) { |
812 | dprintk(DEBUG_ERROR, | 721 | dprintk(DEBUG_ERROR, |
813 | "Couldn't find fid associated with dentry\n"); | 722 | "Couldn't find fid associated with dentry\n"); |
814 | return -EBADF; | 723 | return -EBADF; |
815 | } | 724 | } |
816 | 725 | ||
817 | v9fs_blank_mistat(v9ses, mistat); | 726 | v9fs_blank_wstat(&wstat); |
818 | if (iattr->ia_valid & ATTR_MODE) | 727 | if (iattr->ia_valid & ATTR_MODE) |
819 | mistat->mode = unixmode2p9mode(v9ses, iattr->ia_mode); | 728 | wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode); |
820 | 729 | ||
821 | if (iattr->ia_valid & ATTR_MTIME) | 730 | if (iattr->ia_valid & ATTR_MTIME) |
822 | mistat->mtime = iattr->ia_mtime.tv_sec; | 731 | wstat.mtime = iattr->ia_mtime.tv_sec; |
823 | 732 | ||
824 | if (iattr->ia_valid & ATTR_ATIME) | 733 | if (iattr->ia_valid & ATTR_ATIME) |
825 | mistat->atime = iattr->ia_atime.tv_sec; | 734 | wstat.atime = iattr->ia_atime.tv_sec; |
826 | 735 | ||
827 | if (iattr->ia_valid & ATTR_SIZE) | 736 | if (iattr->ia_valid & ATTR_SIZE) |
828 | mistat->length = iattr->ia_size; | 737 | wstat.length = iattr->ia_size; |
829 | 738 | ||
830 | if (v9ses->extended) { | 739 | if (v9ses->extended) { |
831 | char *ptr = mistat->data+1; | 740 | if (iattr->ia_valid & ATTR_UID) |
741 | wstat.n_uid = iattr->ia_uid; | ||
832 | 742 | ||
833 | if (iattr->ia_valid & ATTR_UID) { | 743 | if (iattr->ia_valid & ATTR_GID) |
834 | mistat->uid = ptr; | 744 | wstat.n_gid = iattr->ia_gid; |
835 | ptr += 1+sprintf(ptr, "%08x", iattr->ia_uid); | ||
836 | mistat->n_uid = iattr->ia_uid; | ||
837 | } | ||
838 | |||
839 | if (iattr->ia_valid & ATTR_GID) { | ||
840 | mistat->gid = ptr; | ||
841 | ptr += 1+sprintf(ptr, "%08x", iattr->ia_gid); | ||
842 | mistat->n_gid = iattr->ia_gid; | ||
843 | } | ||
844 | } | 745 | } |
845 | 746 | ||
846 | res = v9fs_t_wstat(v9ses, fid->fid, mistat, &fcall); | 747 | res = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall); |
847 | 748 | ||
848 | if (res < 0) | 749 | if (res < 0) |
849 | dprintk(DEBUG_ERROR, "wstat error: %s\n", FCALL_ERROR(fcall)); | 750 | PRINT_FCALL_ERROR("wstat error", fcall); |
850 | 751 | ||
851 | kfree(mistat); | ||
852 | kfree(fcall); | 752 | kfree(fcall); |
853 | |||
854 | if (res >= 0) | 753 | if (res >= 0) |
855 | res = inode_setattr(dentry->d_inode, iattr); | 754 | res = inode_setattr(dentry->d_inode, iattr); |
856 | 755 | ||
@@ -858,51 +757,42 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
858 | } | 757 | } |
859 | 758 | ||
860 | /** | 759 | /** |
861 | * v9fs_mistat2inode - populate an inode structure with mistat info | 760 | * v9fs_stat2inode - populate an inode structure with mistat info |
862 | * @mistat: Plan 9 metadata (mistat) structure | 761 | * @stat: Plan 9 metadata (mistat) structure |
863 | * @inode: inode to populate | 762 | * @inode: inode to populate |
864 | * @sb: superblock of filesystem | 763 | * @sb: superblock of filesystem |
865 | * | 764 | * |
866 | */ | 765 | */ |
867 | 766 | ||
868 | void | 767 | void |
869 | v9fs_mistat2inode(struct v9fs_stat *mistat, struct inode *inode, | 768 | v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, |
870 | struct super_block *sb) | 769 | struct super_block *sb) |
871 | { | 770 | { |
771 | char ext[32]; | ||
872 | struct v9fs_session_info *v9ses = sb->s_fs_info; | 772 | struct v9fs_session_info *v9ses = sb->s_fs_info; |
873 | 773 | ||
874 | inode->i_nlink = 1; | 774 | inode->i_nlink = 1; |
875 | 775 | ||
876 | inode->i_atime.tv_sec = mistat->atime; | 776 | inode->i_atime.tv_sec = stat->atime; |
877 | inode->i_mtime.tv_sec = mistat->mtime; | 777 | inode->i_mtime.tv_sec = stat->mtime; |
878 | inode->i_ctime.tv_sec = mistat->mtime; | 778 | inode->i_ctime.tv_sec = stat->mtime; |
879 | 779 | ||
880 | inode->i_uid = -1; | 780 | inode->i_uid = v9ses->uid; |
881 | inode->i_gid = -1; | 781 | inode->i_gid = v9ses->gid; |
882 | 782 | ||
883 | if (v9ses->extended) { | 783 | if (v9ses->extended) { |
884 | /* TODO: string to uid mapping via user-space daemon */ | 784 | inode->i_uid = stat->n_uid; |
885 | inode->i_uid = mistat->n_uid; | 785 | inode->i_gid = stat->n_gid; |
886 | inode->i_gid = mistat->n_gid; | ||
887 | |||
888 | if (mistat->n_uid == -1) | ||
889 | sscanf(mistat->uid, "%x", &inode->i_uid); | ||
890 | |||
891 | if (mistat->n_gid == -1) | ||
892 | sscanf(mistat->gid, "%x", &inode->i_gid); | ||
893 | } | 786 | } |
894 | 787 | ||
895 | if (inode->i_uid == -1) | 788 | inode->i_mode = p9mode2unixmode(v9ses, stat->mode); |
896 | inode->i_uid = v9ses->uid; | ||
897 | if (inode->i_gid == -1) | ||
898 | inode->i_gid = v9ses->gid; | ||
899 | |||
900 | inode->i_mode = p9mode2unixmode(v9ses, mistat->mode); | ||
901 | if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { | 789 | if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { |
902 | char type = 0; | 790 | char type = 0; |
903 | int major = -1; | 791 | int major = -1; |
904 | int minor = -1; | 792 | int minor = -1; |
905 | sscanf(mistat->extension, "%c %u %u", &type, &major, &minor); | 793 | |
794 | v9fs_str_copy(ext, sizeof(ext), &stat->extension); | ||
795 | sscanf(ext, "%c %u %u", &type, &major, &minor); | ||
906 | switch (type) { | 796 | switch (type) { |
907 | case 'c': | 797 | case 'c': |
908 | inode->i_mode &= ~S_IFBLK; | 798 | inode->i_mode &= ~S_IFBLK; |
@@ -911,14 +801,14 @@ v9fs_mistat2inode(struct v9fs_stat *mistat, struct inode *inode, | |||
911 | case 'b': | 801 | case 'b': |
912 | break; | 802 | break; |
913 | default: | 803 | default: |
914 | dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n", | 804 | dprintk(DEBUG_ERROR, "Unknown special type %c (%.*s)\n", |
915 | type, mistat->extension); | 805 | type, stat->extension.len, stat->extension.str); |
916 | }; | 806 | }; |
917 | inode->i_rdev = MKDEV(major, minor); | 807 | inode->i_rdev = MKDEV(major, minor); |
918 | } else | 808 | } else |
919 | inode->i_rdev = 0; | 809 | inode->i_rdev = 0; |
920 | 810 | ||
921 | inode->i_size = mistat->length; | 811 | inode->i_size = stat->length; |
922 | 812 | ||
923 | inode->i_blksize = sb->s_blocksize; | 813 | inode->i_blksize = sb->s_blocksize; |
924 | inode->i_blocks = | 814 | inode->i_blocks = |
@@ -946,72 +836,6 @@ ino_t v9fs_qid2ino(struct v9fs_qid *qid) | |||
946 | } | 836 | } |
947 | 837 | ||
948 | /** | 838 | /** |
949 | * v9fs_vfs_symlink - helper function to create symlinks | ||
950 | * @dir: directory inode containing symlink | ||
951 | * @dentry: dentry for symlink | ||
952 | * @symname: symlink data | ||
953 | * | ||
954 | * See 9P2000.u RFC for more information | ||
955 | * | ||
956 | */ | ||
957 | |||
958 | static int | ||
959 | v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | ||
960 | { | ||
961 | int retval = -EPERM; | ||
962 | struct v9fs_fid *newfid; | ||
963 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | ||
964 | struct v9fs_fcall *fcall = NULL; | ||
965 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | ||
966 | int err; | ||
967 | |||
968 | dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, | ||
969 | symname); | ||
970 | |||
971 | if (!mistat) | ||
972 | return -ENOMEM; | ||
973 | |||
974 | if (!v9ses->extended) { | ||
975 | dprintk(DEBUG_ERROR, "not extended\n"); | ||
976 | goto FreeFcall; | ||
977 | } | ||
978 | |||
979 | /* issue a create */ | ||
980 | retval = v9fs_create(dir, dentry, S_IFLNK, 0); | ||
981 | if (retval != 0) | ||
982 | goto FreeFcall; | ||
983 | |||
984 | newfid = v9fs_fid_lookup(dentry); | ||
985 | |||
986 | /* issue a twstat */ | ||
987 | v9fs_blank_mistat(v9ses, mistat); | ||
988 | strcpy(mistat->data + 1, symname); | ||
989 | mistat->extension = mistat->data + 1; | ||
990 | retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall); | ||
991 | if (retval < 0) { | ||
992 | dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n", | ||
993 | FCALL_ERROR(fcall)); | ||
994 | goto FreeFcall; | ||
995 | } | ||
996 | |||
997 | kfree(fcall); | ||
998 | |||
999 | err = v9fs_t_clunk(v9ses, newfid->fid); | ||
1000 | if (err < 0) { | ||
1001 | dprintk(DEBUG_ERROR, "clunk for symlink failed: %d\n", err); | ||
1002 | goto FreeFcall; | ||
1003 | } | ||
1004 | |||
1005 | d_drop(dentry); /* FID - will this also clunk? */ | ||
1006 | |||
1007 | FreeFcall: | ||
1008 | kfree(mistat); | ||
1009 | kfree(fcall); | ||
1010 | |||
1011 | return retval; | ||
1012 | } | ||
1013 | |||
1014 | /** | ||
1015 | * v9fs_readlink - read a symlink's location (internal version) | 839 | * v9fs_readlink - read a symlink's location (internal version) |
1016 | * @dentry: dentry for symlink | 840 | * @dentry: dentry for symlink |
1017 | * @buffer: buffer to load symlink location into | 841 | * @buffer: buffer to load symlink location into |
@@ -1050,16 +874,17 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
1050 | if (!fcall) | 874 | if (!fcall) |
1051 | return -EIO; | 875 | return -EIO; |
1052 | 876 | ||
1053 | if (!(fcall->params.rstat.stat->mode & V9FS_DMSYMLINK)) { | 877 | if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) { |
1054 | retval = -EINVAL; | 878 | retval = -EINVAL; |
1055 | goto FreeFcall; | 879 | goto FreeFcall; |
1056 | } | 880 | } |
1057 | 881 | ||
1058 | /* copy extension buffer into buffer */ | 882 | /* copy extension buffer into buffer */ |
1059 | if (strlen(fcall->params.rstat.stat->extension) < buflen) | 883 | if (fcall->params.rstat.stat.extension.len < buflen) |
1060 | buflen = strlen(fcall->params.rstat.stat->extension); | 884 | buflen = fcall->params.rstat.stat.extension.len; |
1061 | 885 | ||
1062 | memcpy(buffer, fcall->params.rstat.stat->extension, buflen + 1); | 886 | memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1); |
887 | buffer[buflen-1] = 0; | ||
1063 | 888 | ||
1064 | retval = buflen; | 889 | retval = buflen; |
1065 | 890 | ||
@@ -1149,82 +974,111 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void | |||
1149 | __putname(s); | 974 | __putname(s); |
1150 | } | 975 | } |
1151 | 976 | ||
1152 | /** | 977 | static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, |
1153 | * v9fs_vfs_link - create a hardlink | 978 | int mode, const char *extension) |
1154 | * @old_dentry: dentry for file to link to | ||
1155 | * @dir: inode destination for new link | ||
1156 | * @dentry: dentry for link | ||
1157 | * | ||
1158 | */ | ||
1159 | |||
1160 | /* XXX - lots of code dup'd from symlink and creates, | ||
1161 | * figure out a better reuse strategy | ||
1162 | */ | ||
1163 | |||
1164 | static int | ||
1165 | v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | ||
1166 | struct dentry *dentry) | ||
1167 | { | 979 | { |
1168 | int retval = -EPERM; | 980 | int err, retval; |
1169 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 981 | struct v9fs_session_info *v9ses; |
1170 | struct v9fs_fcall *fcall = NULL; | 982 | struct v9fs_fcall *fcall; |
1171 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 983 | struct v9fs_fid *fid; |
1172 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); | 984 | struct v9fs_wstat wstat; |
1173 | struct v9fs_fid *newfid = NULL; | ||
1174 | char *symname = __getname(); | ||
1175 | int err; | ||
1176 | 985 | ||
1177 | dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, | 986 | v9ses = v9fs_inode2v9ses(dir); |
1178 | old_dentry->d_name.name); | 987 | retval = -EPERM; |
988 | fcall = NULL; | ||
1179 | 989 | ||
1180 | if (!v9ses->extended) { | 990 | if (!v9ses->extended) { |
1181 | dprintk(DEBUG_ERROR, "not extended\n"); | 991 | dprintk(DEBUG_ERROR, "not extended\n"); |
1182 | goto FreeMem; | 992 | goto free_mem; |
1183 | } | 993 | } |
1184 | 994 | ||
1185 | /* get fid of old_dentry */ | ||
1186 | sprintf(symname, "hardlink(%d)\n", oldfid->fid); | ||
1187 | |||
1188 | /* issue a create */ | 995 | /* issue a create */ |
1189 | retval = v9fs_create(dir, dentry, V9FS_DMLINK, 0); | 996 | retval = v9fs_create(dir, dentry, mode, 0); |
1190 | if (retval != 0) | 997 | if (retval != 0) |
1191 | goto FreeMem; | 998 | goto free_mem; |
1192 | 999 | ||
1193 | newfid = v9fs_fid_lookup(dentry); | 1000 | fid = v9fs_fid_get_created(dentry); |
1194 | if (!newfid) { | 1001 | if (!fid) { |
1195 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); | 1002 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); |
1196 | goto FreeMem; | 1003 | goto free_mem; |
1197 | } | 1004 | } |
1198 | 1005 | ||
1199 | /* issue a twstat */ | 1006 | /* issue a Twstat */ |
1200 | v9fs_blank_mistat(v9ses, mistat); | 1007 | v9fs_blank_wstat(&wstat); |
1201 | strcpy(mistat->data + 1, symname); | 1008 | wstat.muid = v9ses->name; |
1202 | mistat->extension = mistat->data + 1; | 1009 | wstat.extension = (char *) extension; |
1203 | retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall); | 1010 | retval = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall); |
1204 | if (retval < 0) { | 1011 | if (retval < 0) { |
1205 | dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n", | 1012 | PRINT_FCALL_ERROR("wstat error", fcall); |
1206 | FCALL_ERROR(fcall)); | 1013 | goto free_mem; |
1207 | goto FreeMem; | ||
1208 | } | 1014 | } |
1209 | 1015 | ||
1210 | kfree(fcall); | 1016 | err = v9fs_t_clunk(v9ses, fid->fid); |
1211 | |||
1212 | err = v9fs_t_clunk(v9ses, newfid->fid); | ||
1213 | |||
1214 | if (err < 0) { | 1017 | if (err < 0) { |
1215 | dprintk(DEBUG_ERROR, "clunk for symlink failed: %d\n", err); | 1018 | dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); |
1216 | goto FreeMem; | 1019 | goto free_mem; |
1217 | } | 1020 | } |
1218 | 1021 | ||
1219 | d_drop(dentry); /* FID - will this also clunk? */ | 1022 | d_drop(dentry); /* FID - will this also clunk? */ |
1220 | 1023 | ||
1024 | free_mem: | ||
1221 | kfree(fcall); | 1025 | kfree(fcall); |
1222 | fcall = NULL; | 1026 | return retval; |
1027 | } | ||
1028 | |||
1029 | /** | ||
1030 | * v9fs_vfs_symlink - helper function to create symlinks | ||
1031 | * @dir: directory inode containing symlink | ||
1032 | * @dentry: dentry for symlink | ||
1033 | * @symname: symlink data | ||
1034 | * | ||
1035 | * See 9P2000.u RFC for more information | ||
1036 | * | ||
1037 | */ | ||
1038 | |||
1039 | static int | ||
1040 | v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | ||
1041 | { | ||
1042 | dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, | ||
1043 | symname); | ||
1044 | |||
1045 | return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname); | ||
1046 | } | ||
1047 | |||
1048 | /** | ||
1049 | * v9fs_vfs_link - create a hardlink | ||
1050 | * @old_dentry: dentry for file to link to | ||
1051 | * @dir: inode destination for new link | ||
1052 | * @dentry: dentry for link | ||
1053 | * | ||
1054 | */ | ||
1055 | |||
1056 | /* XXX - lots of code dup'd from symlink and creates, | ||
1057 | * figure out a better reuse strategy | ||
1058 | */ | ||
1059 | |||
1060 | static int | ||
1061 | v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | ||
1062 | struct dentry *dentry) | ||
1063 | { | ||
1064 | int retval; | ||
1065 | struct v9fs_fid *oldfid; | ||
1066 | char *name; | ||
1067 | |||
1068 | dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, | ||
1069 | old_dentry->d_name.name); | ||
1070 | |||
1071 | oldfid = v9fs_fid_lookup(old_dentry); | ||
1072 | if (!oldfid) { | ||
1073 | dprintk(DEBUG_ERROR, "can't find oldfid\n"); | ||
1074 | return -EPERM; | ||
1075 | } | ||
1076 | |||
1077 | name = __getname(); | ||
1078 | sprintf(name, "hardlink(%d)\n", oldfid->fid); | ||
1079 | retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name); | ||
1080 | __putname(name); | ||
1223 | 1081 | ||
1224 | FreeMem: | ||
1225 | kfree(mistat); | ||
1226 | kfree(fcall); | ||
1227 | __putname(symname); | ||
1228 | return retval; | 1082 | return retval; |
1229 | } | 1083 | } |
1230 | 1084 | ||
@@ -1240,83 +1094,30 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
1240 | static int | 1094 | static int |
1241 | v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | 1095 | v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) |
1242 | { | 1096 | { |
1243 | int retval = -EPERM; | 1097 | int retval; |
1244 | struct v9fs_fid *newfid; | 1098 | char *name; |
1245 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | ||
1246 | struct v9fs_fcall *fcall = NULL; | ||
1247 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | ||
1248 | char *symname = __getname(); | ||
1249 | int err; | ||
1250 | 1099 | ||
1251 | dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, | 1100 | dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, |
1252 | dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); | 1101 | dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); |
1253 | 1102 | ||
1254 | if (!mistat) | 1103 | if (!new_valid_dev(rdev)) |
1255 | return -ENOMEM; | 1104 | return -EINVAL; |
1256 | |||
1257 | if (!new_valid_dev(rdev)) { | ||
1258 | retval = -EINVAL; | ||
1259 | goto FreeMem; | ||
1260 | } | ||
1261 | |||
1262 | if (!v9ses->extended) { | ||
1263 | dprintk(DEBUG_ERROR, "not extended\n"); | ||
1264 | goto FreeMem; | ||
1265 | } | ||
1266 | |||
1267 | /* issue a create */ | ||
1268 | retval = v9fs_create(dir, dentry, mode, 0); | ||
1269 | |||
1270 | if (retval != 0) | ||
1271 | goto FreeMem; | ||
1272 | |||
1273 | newfid = v9fs_fid_lookup(dentry); | ||
1274 | if (!newfid) { | ||
1275 | dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n"); | ||
1276 | retval = -EINVAL; | ||
1277 | goto FreeMem; | ||
1278 | } | ||
1279 | 1105 | ||
1106 | name = __getname(); | ||
1280 | /* build extension */ | 1107 | /* build extension */ |
1281 | if (S_ISBLK(mode)) | 1108 | if (S_ISBLK(mode)) |
1282 | sprintf(symname, "b %u %u", MAJOR(rdev), MINOR(rdev)); | 1109 | sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev)); |
1283 | else if (S_ISCHR(mode)) | 1110 | else if (S_ISCHR(mode)) |
1284 | sprintf(symname, "c %u %u", MAJOR(rdev), MINOR(rdev)); | 1111 | sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev)); |
1285 | else if (S_ISFIFO(mode)) | 1112 | else if (S_ISFIFO(mode)) |
1286 | ; /* DO NOTHING */ | 1113 | *name = 0; |
1287 | else { | 1114 | else { |
1288 | retval = -EINVAL; | 1115 | __putname(name); |
1289 | goto FreeMem; | 1116 | return -EINVAL; |
1290 | } | 1117 | } |
1291 | 1118 | ||
1292 | if (!S_ISFIFO(mode)) { | 1119 | retval = v9fs_vfs_mkspecial(dir, dentry, mode, name); |
1293 | /* issue a twstat */ | 1120 | __putname(name); |
1294 | v9fs_blank_mistat(v9ses, mistat); | ||
1295 | strcpy(mistat->data + 1, symname); | ||
1296 | mistat->extension = mistat->data + 1; | ||
1297 | retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall); | ||
1298 | if (retval < 0) { | ||
1299 | dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n", | ||
1300 | FCALL_ERROR(fcall)); | ||
1301 | goto FreeMem; | ||
1302 | } | ||
1303 | } | ||
1304 | |||
1305 | /* need to update dcache so we show up */ | ||
1306 | kfree(fcall); | ||
1307 | |||
1308 | err = v9fs_t_clunk(v9ses, newfid->fid); | ||
1309 | if (err < 0) { | ||
1310 | dprintk(DEBUG_ERROR, "clunk for symlink failed: %d\n", err); | ||
1311 | goto FreeMem; | ||
1312 | } | ||
1313 | |||
1314 | d_drop(dentry); /* FID - will this also clunk? */ | ||
1315 | |||
1316 | FreeMem: | ||
1317 | kfree(mistat); | ||
1318 | kfree(fcall); | ||
1319 | __putname(symname); | ||
1320 | 1121 | ||
1321 | return retval; | 1122 | return retval; |
1322 | } | 1123 | } |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 83b6edd0988a..d4d71a9ca573 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include "v9fs.h" | 44 | #include "v9fs.h" |
45 | #include "9p.h" | 45 | #include "9p.h" |
46 | #include "v9fs_vfs.h" | 46 | #include "v9fs_vfs.h" |
47 | #include "conv.h" | ||
48 | #include "fid.h" | 47 | #include "fid.h" |
49 | 48 | ||
50 | static void v9fs_clear_inode(struct inode *); | 49 | static void v9fs_clear_inode(struct inode *); |
@@ -123,10 +122,11 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
123 | 122 | ||
124 | dprintk(DEBUG_VFS, " \n"); | 123 | dprintk(DEBUG_VFS, " \n"); |
125 | 124 | ||
126 | v9ses = kcalloc(1, sizeof(struct v9fs_session_info), GFP_KERNEL); | 125 | v9ses = kmalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); |
127 | if (!v9ses) | 126 | if (!v9ses) |
128 | return ERR_PTR(-ENOMEM); | 127 | return ERR_PTR(-ENOMEM); |
129 | 128 | ||
129 | memset(v9ses, 0, sizeof(struct v9fs_session_info)); | ||
130 | if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { | 130 | if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { |
131 | dprintk(DEBUG_ERROR, "problem initiating session\n"); | 131 | dprintk(DEBUG_ERROR, "problem initiating session\n"); |
132 | kfree(v9ses); | 132 | kfree(v9ses); |
@@ -168,10 +168,10 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
168 | goto put_back_sb; | 168 | goto put_back_sb; |
169 | } | 169 | } |
170 | 170 | ||
171 | root_fid->qid = fcall->params.rstat.stat->qid; | 171 | root_fid->qid = fcall->params.rstat.stat.qid; |
172 | root->d_inode->i_ino = | 172 | root->d_inode->i_ino = |
173 | v9fs_qid2ino(&fcall->params.rstat.stat->qid); | 173 | v9fs_qid2ino(&fcall->params.rstat.stat.qid); |
174 | v9fs_mistat2inode(fcall->params.rstat.stat, root->d_inode, sb); | 174 | v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb); |
175 | } | 175 | } |
176 | 176 | ||
177 | kfree(fcall); | 177 | kfree(fcall); |