aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/9p.c
diff options
context:
space:
mode:
authorLatchesar Ionkov <lucho@ionkov.net>2006-01-08 04:05:00 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-08 23:14:06 -0500
commit531b1094b74365dcc55fa464d28a9a2497ae825d (patch)
treea0384dabe3be1c844166d028b3ef7c21c3dfe5fc /fs/9p/9p.c
parentd8da097afb765654c866062148fd98b11db9003e (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.c302
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
47int 49int
48v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize, 50v9fs_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
73int 79int
74v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname, 80v9fs_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
90static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc, 100static 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
120int 131int
121v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid) 132v9fs_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
147int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag) 161int 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
165int 187int
166v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall) 188v9fs_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
188int 215int
189v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, 216v9fs_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
214int 247int
215v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, 248v9fs_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
245int 283int
246v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode, 284v9fs_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
270int 311int
271v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid, 312v9fs_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
293int 342int
294v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, 343v9fs_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
321int 373int
322v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset, 374v9fs_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
360int 411int
361v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, 412v9fs_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