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 /fs/9p/9p.c | |
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>
Diffstat (limited to 'fs/9p/9p.c')
-rw-r--r-- | fs/9p/9p.c | 302 |
1 files changed, 176 insertions, 126 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 | |||