aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/client.c
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@gmail.com>2008-10-16 09:30:07 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2008-10-17 12:04:45 -0400
commit51a87c552dfd428e304c865e24ecbe091556f226 (patch)
tree6e9012962e6601b559dcf15ae3228647a8581a31 /net/9p/client.c
parentcb198131b0e7aba755ac164744536d461e86ab82 (diff)
9p: rework client code to use new protocol support functions
Now that the new protocol functions are in place, this patch switches the client code to using the new support code. Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'net/9p/client.c')
-rw-r--r--net/9p/client.c931
1 files changed, 454 insertions, 477 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index 6004fded6682..2a166bfb95a3 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -35,6 +35,7 @@
35#include <linux/parser.h> 35#include <linux/parser.h>
36#include <net/9p/client.h> 36#include <net/9p/client.h>
37#include <net/9p/transport.h> 37#include <net/9p/transport.h>
38#include "protocol.h"
38 39
39/* 40/*
40 * Client Option Parsing (code inspired by NFS code) 41 * Client Option Parsing (code inspired by NFS code)
@@ -55,8 +56,8 @@ static const match_table_t tokens = {
55 {Opt_err, NULL}, 56 {Opt_err, NULL},
56}; 57};
57 58
58static int 59static struct p9_req_t *
59p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc); 60p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
60 61
61/** 62/**
62 * v9fs_parse_options - parse mount options into session structure 63 * v9fs_parse_options - parse mount options into session structure
@@ -138,10 +139,11 @@ static int parse_opts(char *opts, struct p9_client *clnt)
138 * 139 *
139 */ 140 */
140 141
141struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) 142static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
142{ 143{
143 unsigned long flags; 144 unsigned long flags;
144 int row, col; 145 int row, col;
146 struct p9_req_t *req;
145 147
146 /* This looks up the original request by tag so we know which 148 /* This looks up the original request by tag so we know which
147 * buffer to read the data into */ 149 * buffer to read the data into */
@@ -157,19 +159,11 @@ struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
157 159
158 if (!c->reqs[row]) { 160 if (!c->reqs[row]) {
159 printk(KERN_ERR "Couldn't grow tag array\n"); 161 printk(KERN_ERR "Couldn't grow tag array\n");
160 BUG(); 162 return ERR_PTR(-ENOMEM);
161 } 163 }
162 for (col = 0; col < P9_ROW_MAXTAG; col++) { 164 for (col = 0; col < P9_ROW_MAXTAG; col++) {
163 c->reqs[row][col].status = REQ_STATUS_IDLE; 165 c->reqs[row][col].status = REQ_STATUS_IDLE;
164 c->reqs[row][col].flush_tag = P9_NOTAG; 166 c->reqs[row][col].tc = NULL;
165 c->reqs[row][col].wq = kmalloc(
166 sizeof(wait_queue_head_t), GFP_ATOMIC);
167 if (!c->reqs[row][col].wq) {
168 printk(KERN_ERR
169 "Couldn't grow tag array\n");
170 BUG();
171 }
172 init_waitqueue_head(c->reqs[row][col].wq);
173 } 167 }
174 c->max_tag += P9_ROW_MAXTAG; 168 c->max_tag += P9_ROW_MAXTAG;
175 } 169 }
@@ -178,12 +172,39 @@ struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
178 row = tag / P9_ROW_MAXTAG; 172 row = tag / P9_ROW_MAXTAG;
179 col = tag % P9_ROW_MAXTAG; 173 col = tag % P9_ROW_MAXTAG;
180 174
181 c->reqs[row][col].status = REQ_STATUS_ALLOC; 175 req = &c->reqs[row][col];
182 c->reqs[row][col].flush_tag = P9_NOTAG; 176 if (!req->tc) {
177 req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
178 if (!req->wq) {
179 printk(KERN_ERR "Couldn't grow tag array\n");
180 return ERR_PTR(-ENOMEM);
181 }
182 init_waitqueue_head(req->wq);
183 req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
184 GFP_KERNEL);
185 req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
186 GFP_KERNEL);
187 if ((!req->tc) || (!req->rc)) {
188 printk(KERN_ERR "Couldn't grow tag array\n");
189 kfree(req->tc);
190 kfree(req->rc);
191 return ERR_PTR(-ENOMEM);
192 }
193 req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
194 req->tc->capacity = c->msize;
195 req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
196 req->rc->capacity = c->msize;
197 }
198
199 p9pdu_reset(req->tc);
200 p9pdu_reset(req->rc);
201
202 req->flush_tag = 0;
203 req->tc->tag = tag-1;
204 req->status = REQ_STATUS_ALLOC;
183 205
184 return &c->reqs[row][col]; 206 return &c->reqs[row][col];
185} 207}
186EXPORT_SYMBOL(p9_tag_alloc);
187 208
188/** 209/**
189 * p9_tag_lookup - lookup a request by tag 210 * p9_tag_lookup - lookup a request by tag
@@ -264,59 +285,34 @@ static void p9_tag_cleanup(struct p9_client *c)
264 285
265 /* free requests associated with tags */ 286 /* free requests associated with tags */
266 for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { 287 for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
267 for (col = 0; col < P9_ROW_MAXTAG; col++) 288 for (col = 0; col < P9_ROW_MAXTAG; col++) {
268 kfree(c->reqs[row][col].wq); 289 kfree(c->reqs[row][col].wq);
290 kfree(c->reqs[row][col].tc);
291 kfree(c->reqs[row][col].rc);
292 }
269 kfree(c->reqs[row]); 293 kfree(c->reqs[row]);
270 } 294 }
271 c->max_tag = 0; 295 c->max_tag = 0;
272} 296}
273 297
274/** 298/**
275 * p9_client_flush - flush (cancel) a request
276 * c: client state
277 * req: request to cancel
278 *
279 * This sents a flush for a particular requests and links
280 * the flush request to the original request. The current
281 * code only supports a single flush request although the protocol
282 * allows for multiple flush requests to be sent for a single request.
283 *
284 */
285
286static int p9_client_flush(struct p9_client *c, struct p9_req_t *req)
287{
288 struct p9_fcall *tc, *rc = NULL;
289 int err;
290
291 P9_DPRINTK(P9_DEBUG_9P, "client %p tag %d\n", c, req->tc->tag);
292
293 tc = p9_create_tflush(req->tc->tag);
294 if (IS_ERR(tc))
295 return PTR_ERR(tc);
296
297 err = p9_client_rpc(c, tc, &rc);
298
299 /* we don't free anything here because RPC isn't complete */
300
301 return err;
302}
303
304/**
305 * p9_free_req - free a request and clean-up as necessary 299 * p9_free_req - free a request and clean-up as necessary
306 * c: client state 300 * c: client state
307 * r: request to release 301 * r: request to release
308 * 302 *
309 */ 303 */
310 304
311void p9_free_req(struct p9_client *c, struct p9_req_t *r) 305static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
312{ 306{
313 r->flush_tag = P9_NOTAG; 307 int tag = r->tc->tag;
308 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
309
314 r->status = REQ_STATUS_IDLE; 310 r->status = REQ_STATUS_IDLE;
315 if (r->tc->tag != P9_NOTAG && p9_idpool_check(r->tc->tag, c->tagpool)) 311 if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
316 p9_idpool_put(r->tc->tag, c->tagpool); 312 p9_idpool_put(tag, c->tagpool);
317 313
318 /* if this was a flush request we have to free response fcall */ 314 /* if this was a flush request we have to free response fcall */
319 if (r->tc->id == P9_TFLUSH) { 315 if (r->rc->id == P9_RFLUSH) {
320 kfree(r->tc); 316 kfree(r->tc);
321 kfree(r->rc); 317 kfree(r->rc);
322 } 318 }
@@ -333,30 +329,28 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
333 struct p9_req_t *other_req; 329 struct p9_req_t *other_req;
334 unsigned long flags; 330 unsigned long flags;
335 331
336 P9_DPRINTK(P9_DEBUG_MUX, ": %d\n", req->tc->tag); 332 P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
337 333
338 if (req->status == REQ_STATUS_ERROR) 334 if (req->status == REQ_STATUS_ERROR)
339 wake_up(req->wq); 335 wake_up(req->wq);
340 336
341 if (req->tc->id == P9_TFLUSH) { /* flush receive path */ 337 if (req->flush_tag) { /* flush receive path */
342 P9_DPRINTK(P9_DEBUG_MUX, "flush: %d\n", req->tc->tag); 338 P9_DPRINTK(P9_DEBUG_9P, "<<< RFLUSH %d\n", req->tc->tag);
343 spin_lock_irqsave(&c->lock, flags); 339 spin_lock_irqsave(&c->lock, flags);
344 other_req = p9_tag_lookup(c, req->tc->params.tflush.oldtag); 340 other_req = p9_tag_lookup(c, req->flush_tag);
345 if (other_req->flush_tag != req->tc->tag) /* stale flush */ 341 if (other_req->status != REQ_STATUS_FLSH) /* stale flush */
346 spin_unlock_irqrestore(&c->lock, flags); 342 spin_unlock_irqrestore(&c->lock, flags);
347 else { 343 else {
348 BUG_ON(other_req->status != REQ_STATUS_FLSH);
349 other_req->status = REQ_STATUS_FLSHD; 344 other_req->status = REQ_STATUS_FLSHD;
350 spin_unlock_irqrestore(&c->lock, flags); 345 spin_unlock_irqrestore(&c->lock, flags);
351 wake_up(other_req->wq); 346 wake_up(other_req->wq);
352 } 347 }
353 p9_free_req(c, req); 348 p9_free_req(c, req);
354 } else { /* normal receive path */ 349 } else { /* normal receive path */
355 P9_DPRINTK(P9_DEBUG_MUX, "normal: %d\n", req->tc->tag); 350 P9_DPRINTK(P9_DEBUG_MUX, "normal: tag %d\n", req->tc->tag);
356 spin_lock_irqsave(&c->lock, flags); 351 spin_lock_irqsave(&c->lock, flags);
357 if (req->status != REQ_STATUS_FLSHD) 352 if (req->status != REQ_STATUS_FLSHD)
358 req->status = REQ_STATUS_RCVD; 353 req->status = REQ_STATUS_RCVD;
359 req->flush_tag = P9_NOTAG;
360 spin_unlock_irqrestore(&c->lock, flags); 354 spin_unlock_irqrestore(&c->lock, flags);
361 wake_up(req->wq); 355 wake_up(req->wq);
362 P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); 356 P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
@@ -365,28 +359,164 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
365EXPORT_SYMBOL(p9_client_cb); 359EXPORT_SYMBOL(p9_client_cb);
366 360
367/** 361/**
362 * p9_parse_header - parse header arguments out of a packet
363 * @pdu: packet to parse
364 * @size: size of packet
365 * @type: type of request
366 * @tag: tag of packet
367 * @rewind: set if we need to rewind offset afterwards
368 */
369
370int
371p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
372 int rewind)
373{
374 int8_t r_type;
375 int16_t r_tag;
376 int32_t r_size;
377 int offset = pdu->offset;
378 int err;
379
380 pdu->offset = 0;
381 if (pdu->size == 0)
382 pdu->size = 7;
383
384 err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
385 if (err)
386 goto rewind_and_exit;
387
388 pdu->size = r_size;
389 pdu->id = r_type;
390 pdu->tag = r_tag;
391
392 P9_DPRINTK(P9_DEBUG_MUX, "pdu: type: %d tag: %d size=%d offset=%d\n",
393 pdu->id, pdu->tag, pdu->size, pdu->offset);
394
395 if (type)
396 *type = r_type;
397 if (tag)
398 *tag = r_tag;
399 if (size)
400 *size = r_size;
401
402
403rewind_and_exit:
404 if (rewind)
405 pdu->offset = offset;
406 return err;
407}
408EXPORT_SYMBOL(p9_parse_header);
409
410/**
411 * p9_check_errors - check 9p packet for error return and process it
412 * @c: current client instance
413 * @req: request to parse and check for error conditions
414 *
415 * returns error code if one is discovered, otherwise returns 0
416 *
417 * this will have to be more complicated if we have multiple
418 * error packet types
419 */
420
421static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
422{
423 int8_t type;
424 int err;
425
426 err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
427 if (err) {
428 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
429 return err;
430 }
431
432 if (type == P9_RERROR) {
433 int ecode;
434 char *ename;
435
436 err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode);
437 if (err) {
438 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
439 err);
440 return err;
441 }
442
443 if (c->dotu)
444 err = -ecode;
445
446 if (!err) {
447 err = p9_errstr2errno(ename, strlen(ename));
448
449 /* string match failed */
450 if (!err)
451 err = -ESERVERFAULT;
452 }
453
454 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
455
456 kfree(ename);
457 } else
458 err = 0;
459
460 return err;
461}
462
463/**
464 * p9_client_flush - flush (cancel) a request
465 * c: client state
466 * req: request to cancel
467 *
468 * This sents a flush for a particular requests and links
469 * the flush request to the original request. The current
470 * code only supports a single flush request although the protocol
471 * allows for multiple flush requests to be sent for a single request.
472 *
473 */
474
475static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
476{
477 struct p9_req_t *req;
478 int16_t oldtag;
479 int err;
480
481 err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
482 if (err)
483 return err;
484
485 P9_DPRINTK(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);
486
487 req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
488 if (IS_ERR(req))
489 return PTR_ERR(req);
490
491 req->flush_tag = oldtag;
492
493 /* we don't free anything here because RPC isn't complete */
494 return 0;
495}
496
497/**
368 * p9_client_rpc - issue a request and wait for a response 498 * p9_client_rpc - issue a request and wait for a response
369 * @c: client session 499 * @c: client session
370 * @tc: &p9_fcall request to transmit 500 * @type: type of request
371 * @rc: &p9_fcall to put reponse into 501 * @fmt: protocol format string (see protocol.c)
372 * 502 *
373 * Returns 0 on success, error code on failure 503 * Returns request structure (which client must free using p9_free_req)
374 */ 504 */
375 505
376static int 506static struct p9_req_t *
377p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc) 507p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
378{ 508{
379 int tag, err, size; 509 va_list ap;
380 char *rdata; 510 int tag, err;
381 struct p9_req_t *req; 511 struct p9_req_t *req;
382 unsigned long flags; 512 unsigned long flags;
383 int sigpending; 513 int sigpending;
384 int flushed = 0; 514 int flushed = 0;
385 515
386 P9_DPRINTK(P9_DEBUG_9P, "client %p tc %p rc %p\n", c, tc, rc); 516 P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
387 517
388 if (c->status != Connected) 518 if (c->status != Connected)
389 return -EIO; 519 return ERR_PTR(-EIO);
390 520
391 if (signal_pending(current)) { 521 if (signal_pending(current)) {
392 sigpending = 1; 522 sigpending = 1;
@@ -395,50 +525,22 @@ p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
395 sigpending = 0; 525 sigpending = 0;
396 526
397 tag = P9_NOTAG; 527 tag = P9_NOTAG;
398 if (tc->id != P9_TVERSION) { 528 if (type != P9_TVERSION) {
399 tag = p9_idpool_get(c->tagpool); 529 tag = p9_idpool_get(c->tagpool);
400 if (tag < 0) 530 if (tag < 0)
401 return -ENOMEM; 531 return ERR_PTR(-ENOMEM);
402 } 532 }
403 533
404 req = p9_tag_alloc(c, tag); 534 req = p9_tag_alloc(c, tag);
535 if (IS_ERR(req))
536 return req;
405 537
406 /* if this is a flush request, backlink flush request now to 538 /* marshall the data */
407 * avoid race conditions later. */ 539 p9pdu_prepare(req->tc, tag, type);
408 if (tc->id == P9_TFLUSH) { 540 va_start(ap, fmt);
409 struct p9_req_t *other_req = 541 err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap);
410 p9_tag_lookup(c, tc->params.tflush.oldtag); 542 va_end(ap);
411 if (other_req->status == REQ_STATUS_FLSH) 543 p9pdu_finalize(req->tc);
412 other_req->flush_tag = tag;
413 }
414
415 p9_set_tag(tc, tag);
416
417 /*
418 * if client passed in a pre-allocated response fcall struct
419 * then we just use that, otherwise we allocate one.
420 */
421
422 if (rc == NULL)
423 req->rc = NULL;
424 else
425 req->rc = *rc;
426 if (req->rc == NULL) {
427 req->rc = kmalloc(sizeof(struct p9_fcall) + c->msize,
428 GFP_KERNEL);
429 if (!req->rc) {
430 err = -ENOMEM;
431 p9_idpool_put(tag, c->tagpool);
432 p9_free_req(c, req);
433 goto reterr;
434 }
435 *rc = req->rc;
436 }
437
438 rdata = (char *)req->rc+sizeof(struct p9_fcall);
439
440 req->tc = tc;
441 P9_DPRINTK(P9_DEBUG_9P, "request: tc: %p rc: %p\n", req->tc, req->rc);
442 544
443 err = c->trans_mod->request(c, req); 545 err = c->trans_mod->request(c, req);
444 if (err < 0) { 546 if (err < 0) {
@@ -447,28 +549,28 @@ p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
447 } 549 }
448 550
449 /* if it was a flush we just transmitted, return our tag */ 551 /* if it was a flush we just transmitted, return our tag */
450 if (tc->id == P9_TFLUSH) 552 if (type == P9_TFLUSH)
451 return 0; 553 return req;
452again: 554again:
453 P9_DPRINTK(P9_DEBUG_9P, "wait %p tag: %d\n", req->wq, tag); 555 P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag);
454 err = wait_event_interruptible(*req->wq, 556 err = wait_event_interruptible(*req->wq,
455 req->status >= REQ_STATUS_RCVD); 557 req->status >= REQ_STATUS_RCVD);
456 P9_DPRINTK(P9_DEBUG_9P, "wait %p tag: %d returned %d (flushed=%d)\n", 558 P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n",
457 req->wq, tag, err, flushed); 559 req->wq, tag, err, flushed);
458 560
459 if (req->status == REQ_STATUS_ERROR) { 561 if (req->status == REQ_STATUS_ERROR) {
460 P9_DPRINTK(P9_DEBUG_9P, "req_status error %d\n", req->t_err); 562 P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
461 err = req->t_err; 563 err = req->t_err;
462 } else if (err == -ERESTARTSYS && flushed) { 564 } else if (err == -ERESTARTSYS && flushed) {
463 P9_DPRINTK(P9_DEBUG_9P, "flushed - going again\n"); 565 P9_DPRINTK(P9_DEBUG_MUX, "flushed - going again\n");
464 goto again; 566 goto again;
465 } else if (req->status == REQ_STATUS_FLSHD) { 567 } else if (req->status == REQ_STATUS_FLSHD) {
466 P9_DPRINTK(P9_DEBUG_9P, "flushed - erestartsys\n"); 568 P9_DPRINTK(P9_DEBUG_MUX, "flushed - erestartsys\n");
467 err = -ERESTARTSYS; 569 err = -ERESTARTSYS;
468 } 570 }
469 571
470 if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) { 572 if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) {
471 P9_DPRINTK(P9_DEBUG_9P, "flushing\n"); 573 P9_DPRINTK(P9_DEBUG_MUX, "flushing\n");
472 spin_lock_irqsave(&c->lock, flags); 574 spin_lock_irqsave(&c->lock, flags);
473 if (req->status == REQ_STATUS_SENT) 575 if (req->status == REQ_STATUS_SENT)
474 req->status = REQ_STATUS_FLSH; 576 req->status = REQ_STATUS_FLSH;
@@ -493,42 +595,17 @@ again:
493 if (err < 0) 595 if (err < 0)
494 goto reterr; 596 goto reterr;
495 597
496 size = le32_to_cpu(*(__le32 *) rdata); 598 err = p9_check_errors(c, req);
497 599 if (!err) {
498 err = p9_deserialize_fcall(rdata, size, req->rc, c->dotu); 600 P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type);
499 if (err < 0) { 601 return req;
500 P9_DPRINTK(P9_DEBUG_9P,
501 "9p debug: client rpc deserialize returned %d\n", err);
502 goto reterr;
503 } 602 }
504 603
505 if (req->rc->id == P9_RERROR) {
506 int ecode = req->rc->params.rerror.errno;
507 struct p9_str *ename = &req->rc->params.rerror.error;
508
509 P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len,
510 ename->str);
511
512 if (c->dotu)
513 err = -ecode;
514
515 if (!err) {
516 err = p9_errstr2errno(ename->str, ename->len);
517
518 /* string match failed */
519 if (!err) {
520 PRINT_FCALL_ERROR("unknown error", req->rc);
521 err = -ESERVERFAULT;
522 }
523 }
524 } else
525 err = 0;
526
527reterr: 604reterr:
605 P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type,
606 err);
528 p9_free_req(c, req); 607 p9_free_req(c, req);
529 608 return ERR_PTR(err);
530 P9_DPRINTK(P9_DEBUG_9P, "returning %d\n", err);
531 return err;
532} 609}
533 610
534static struct p9_fid *p9_fid_create(struct p9_client *clnt) 611static struct p9_fid *p9_fid_create(struct p9_client *clnt)
@@ -536,7 +613,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
536 int err; 613 int err;
537 struct p9_fid *fid; 614 struct p9_fid *fid;
538 615
539 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); 616 P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt);
540 fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); 617 fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
541 if (!fid) 618 if (!fid)
542 return ERR_PTR(-ENOMEM); 619 return ERR_PTR(-ENOMEM);
@@ -569,7 +646,7 @@ static void p9_fid_destroy(struct p9_fid *fid)
569{ 646{
570 struct p9_client *clnt; 647 struct p9_client *clnt;
571 648
572 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 649 P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid);
573 clnt = fid->clnt; 650 clnt = fid->clnt;
574 p9_idpool_put(fid->fid, clnt->fidpool); 651 p9_idpool_put(fid->fid, clnt->fidpool);
575 spin_lock(&clnt->lock); 652 spin_lock(&clnt->lock);
@@ -578,49 +655,46 @@ static void p9_fid_destroy(struct p9_fid *fid)
578 kfree(fid); 655 kfree(fid);
579} 656}
580 657
581static int p9_client_version(struct p9_client *clnt) 658int p9_client_version(struct p9_client *c)
582{ 659{
583 int err = 0; 660 int err = 0;
584 struct p9_fcall *tc, *rc; 661 struct p9_req_t *req;
585 struct p9_str *version; 662 char *version;
663 int msize;
586 664
587 P9_DPRINTK(P9_DEBUG_9P, "%p\n", clnt); 665 P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n",
588 err = 0; 666 c->msize, c->dotu);
589 tc = NULL; 667 req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize,
590 rc = NULL; 668 c->dotu ? "9P2000.u" : "9P2000");
591 669 if (IS_ERR(req))
592 tc = p9_create_tversion(clnt->msize, 670 return PTR_ERR(req);
593 clnt->dotu ? "9P2000.u" : "9P2000");
594 if (IS_ERR(tc)) {
595 err = PTR_ERR(tc);
596 tc = NULL;
597 goto error;
598 }
599 671
600 err = p9_client_rpc(clnt, tc, &rc); 672 err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version);
601 if (err) 673 if (err) {
674 P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
602 goto error; 675 goto error;
676 }
603 677
604 version = &rc->params.rversion.version; 678 P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
605 if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8)) 679 if (!memcmp(version, "9P2000.u", 8))
606 clnt->dotu = 1; 680 c->dotu = 1;
607 else if (version->len == 6 && !memcmp(version->str, "9P2000", 6)) 681 else if (!memcmp(version, "9P2000", 6))
608 clnt->dotu = 0; 682 c->dotu = 0;
609 else { 683 else {
610 err = -EREMOTEIO; 684 err = -EREMOTEIO;
611 goto error; 685 goto error;
612 } 686 }
613 687
614 if (rc->params.rversion.msize < clnt->msize) 688 if (msize < c->msize)
615 clnt->msize = rc->params.rversion.msize; 689 c->msize = msize;
616 690
617error: 691error:
618 kfree(tc); 692 kfree(version);
619 kfree(rc); 693 p9_free_req(c, req);
620 694
621 return err; 695 return err;
622} 696}
623EXPORT_SYMBOL(p9_client_auth); 697EXPORT_SYMBOL(p9_client_version);
624 698
625struct p9_client *p9_client_create(const char *dev_name, char *options) 699struct p9_client *p9_client_create(const char *dev_name, char *options)
626{ 700{
@@ -656,7 +730,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
656 goto error; 730 goto error;
657 } 731 }
658 732
659 P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n", 733 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n",
660 clnt, clnt->trans_mod, clnt->msize, clnt->dotu); 734 clnt, clnt->trans_mod, clnt->msize, clnt->dotu);
661 735
662 err = clnt->trans_mod->create(clnt, dev_name, options); 736 err = clnt->trans_mod->create(clnt, dev_name, options);
@@ -682,7 +756,7 @@ void p9_client_destroy(struct p9_client *clnt)
682{ 756{
683 struct p9_fid *fid, *fidptr; 757 struct p9_fid *fid, *fidptr;
684 758
685 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); 759 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p\n", clnt);
686 760
687 if (clnt->trans_mod) 761 if (clnt->trans_mod)
688 clnt->trans_mod->close(clnt); 762 clnt->trans_mod->close(clnt);
@@ -712,14 +786,13 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
712 char *uname, u32 n_uname, char *aname) 786 char *uname, u32 n_uname, char *aname)
713{ 787{
714 int err; 788 int err;
715 struct p9_fcall *tc, *rc; 789 struct p9_req_t *req;
716 struct p9_fid *fid; 790 struct p9_fid *fid;
791 struct p9_qid qid;
717 792
718 P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n", 793 P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
719 clnt, afid?afid->fid:-1, uname, aname); 794 afid ? afid->fid : -1, uname, aname);
720 err = 0; 795 err = 0;
721 tc = NULL;
722 rc = NULL;
723 796
724 fid = p9_fid_create(clnt); 797 fid = p9_fid_create(clnt);
725 if (IS_ERR(fid)) { 798 if (IS_ERR(fid)) {
@@ -728,73 +801,75 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
728 goto error; 801 goto error;
729 } 802 }
730 803
731 tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname, 804 req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid,
732 n_uname, clnt->dotu); 805 afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
733 if (IS_ERR(tc)) { 806 if (IS_ERR(req)) {
734 err = PTR_ERR(tc); 807 err = PTR_ERR(req);
735 tc = NULL;
736 goto error; 808 goto error;
737 } 809 }
738 810
739 err = p9_client_rpc(clnt, tc, &rc); 811 err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
740 if (err) 812 if (err) {
813 p9_free_req(clnt, req);
741 goto error; 814 goto error;
815 }
742 816
743 memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid)); 817 P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
744 kfree(tc); 818 qid.type, qid.path, qid.version);
745 kfree(rc); 819
820 memmove(&fid->qid, &qid, sizeof(struct p9_qid));
821
822 p9_free_req(clnt, req);
746 return fid; 823 return fid;
747 824
748error: 825error:
749 kfree(tc);
750 kfree(rc);
751 if (fid) 826 if (fid)
752 p9_fid_destroy(fid); 827 p9_fid_destroy(fid);
753 return ERR_PTR(err); 828 return ERR_PTR(err);
754} 829}
755EXPORT_SYMBOL(p9_client_attach); 830EXPORT_SYMBOL(p9_client_attach);
756 831
757struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, 832struct p9_fid *
758 u32 n_uname, char *aname) 833p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname)
759{ 834{
760 int err; 835 int err;
761 struct p9_fcall *tc, *rc; 836 struct p9_req_t *req;
762 struct p9_fid *fid; 837 struct p9_qid qid;
838 struct p9_fid *afid;
763 839
764 P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname, 840 P9_DPRINTK(P9_DEBUG_9P, ">>> TAUTH uname %s aname %s\n", uname, aname);
765 aname);
766 err = 0; 841 err = 0;
767 tc = NULL;
768 rc = NULL;
769 842
770 fid = p9_fid_create(clnt); 843 afid = p9_fid_create(clnt);
771 if (IS_ERR(fid)) { 844 if (IS_ERR(afid)) {
772 err = PTR_ERR(fid); 845 err = PTR_ERR(afid);
773 fid = NULL; 846 afid = NULL;
774 goto error; 847 goto error;
775 } 848 }
776 849
777 tc = p9_create_tauth(fid->fid, uname, aname, n_uname, clnt->dotu); 850 req = p9_client_rpc(clnt, P9_TAUTH, "dss?d",
778 if (IS_ERR(tc)) { 851 afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
779 err = PTR_ERR(tc); 852 if (IS_ERR(req)) {
780 tc = NULL; 853 err = PTR_ERR(req);
781 goto error; 854 goto error;
782 } 855 }
783 856
784 err = p9_client_rpc(clnt, tc, &rc); 857 err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
785 if (err) 858 if (err) {
859 p9_free_req(clnt, req);
786 goto error; 860 goto error;
861 }
787 862
788 memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid)); 863 P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n",
789 kfree(tc); 864 qid.type, qid.path, qid.version);
790 kfree(rc); 865
791 return fid; 866 memmove(&afid->qid, &qid, sizeof(struct p9_qid));
867 p9_free_req(clnt, req);
868 return afid;
792 869
793error: 870error:
794 kfree(tc); 871 if (afid)
795 kfree(rc); 872 p9_fid_destroy(afid);
796 if (fid)
797 p9_fid_destroy(fid);
798 return ERR_PTR(err); 873 return ERR_PTR(err);
799} 874}
800EXPORT_SYMBOL(p9_client_auth); 875EXPORT_SYMBOL(p9_client_auth);
@@ -803,15 +878,13 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
803 int clone) 878 int clone)
804{ 879{
805 int err; 880 int err;
806 struct p9_fcall *tc, *rc;
807 struct p9_client *clnt; 881 struct p9_client *clnt;
808 struct p9_fid *fid; 882 struct p9_fid *fid;
883 struct p9_qid *wqids;
884 struct p9_req_t *req;
885 int16_t nwqids, count;
809 886
810 P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n",
811 oldfid->fid, nwname, wnames?wnames[0]:NULL);
812 err = 0; 887 err = 0;
813 tc = NULL;
814 rc = NULL;
815 clnt = oldfid->clnt; 888 clnt = oldfid->clnt;
816 if (clone) { 889 if (clone) {
817 fid = p9_fid_create(clnt); 890 fid = p9_fid_create(clnt);
@@ -825,53 +898,46 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
825 } else 898 } else
826 fid = oldfid; 899 fid = oldfid;
827 900
828 tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames); 901
829 if (IS_ERR(tc)) { 902 P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n",
830 err = PTR_ERR(tc); 903 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
831 tc = NULL; 904
905 req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
906 nwname, wnames);
907 if (IS_ERR(req)) {
908 err = PTR_ERR(req);
832 goto error; 909 goto error;
833 } 910 }
834 911
835 err = p9_client_rpc(clnt, tc, &rc); 912 err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids);
836 if (err) { 913 p9_free_req(clnt, req);
837 if (rc && rc->id == P9_RWALK) 914 if (err)
838 goto clunk_fid; 915 goto clunk_fid;
839 else
840 goto error;
841 }
842 916
843 if (rc->params.rwalk.nwqid != nwname) { 917 P9_DPRINTK(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
918
919 if (nwqids != nwname) {
844 err = -ENOENT; 920 err = -ENOENT;
845 goto clunk_fid; 921 goto clunk_fid;
846 } 922 }
847 923
924 for (count = 0; count < nwqids; count++)
925 P9_DPRINTK(P9_DEBUG_9P, "<<< [%d] %x.%llx.%x\n",
926 count, wqids[count].type, wqids[count].path,
927 wqids[count].version);
928
848 if (nwname) 929 if (nwname)
849 memmove(&fid->qid, 930 memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
850 &rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1],
851 sizeof(struct p9_qid));
852 else 931 else
853 fid->qid = oldfid->qid; 932 fid->qid = oldfid->qid;
854 933
855 kfree(tc);
856 kfree(rc);
857 return fid; 934 return fid;
858 935
859clunk_fid: 936clunk_fid:
860 kfree(tc); 937 p9_client_clunk(fid);
861 kfree(rc); 938 fid = NULL;
862 rc = NULL;
863 tc = p9_create_tclunk(fid->fid);
864 if (IS_ERR(tc)) {
865 err = PTR_ERR(tc);
866 tc = NULL;
867 goto error;
868 }
869
870 p9_client_rpc(clnt, tc, &rc);
871 939
872error: 940error:
873 kfree(tc);
874 kfree(rc);
875 if (fid && (fid != oldfid)) 941 if (fid && (fid != oldfid))
876 p9_fid_destroy(fid); 942 p9_fid_destroy(fid);
877 943
@@ -882,35 +948,36 @@ EXPORT_SYMBOL(p9_client_walk);
882int p9_client_open(struct p9_fid *fid, int mode) 948int p9_client_open(struct p9_fid *fid, int mode)
883{ 949{
884 int err; 950 int err;
885 struct p9_fcall *tc, *rc;
886 struct p9_client *clnt; 951 struct p9_client *clnt;
952 struct p9_req_t *req;
953 struct p9_qid qid;
954 int iounit;
887 955
888 P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode); 956 P9_DPRINTK(P9_DEBUG_9P, ">>> TOPEN fid %d mode %d\n", fid->fid, mode);
889 err = 0; 957 err = 0;
890 tc = NULL;
891 rc = NULL;
892 clnt = fid->clnt; 958 clnt = fid->clnt;
893 959
894 if (fid->mode != -1) 960 if (fid->mode != -1)
895 return -EINVAL; 961 return -EINVAL;
896 962
897 tc = p9_create_topen(fid->fid, mode); 963 req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode);
898 if (IS_ERR(tc)) { 964 if (IS_ERR(req)) {
899 err = PTR_ERR(tc); 965 err = PTR_ERR(req);
900 tc = NULL; 966 goto error;
901 goto done;
902 } 967 }
903 968
904 err = p9_client_rpc(clnt, tc, &rc); 969 err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
970 p9_free_req(clnt, req);
905 if (err) 971 if (err)
906 goto done; 972 goto error;
973
974 P9_DPRINTK(P9_DEBUG_9P, "<<< ROPEN qid %x.%llx.%x iounit %x\n",
975 qid.type, qid.path, qid.version, iounit);
907 976
908 fid->mode = mode; 977 fid->mode = mode;
909 fid->iounit = rc->params.ropen.iounit; 978 fid->iounit = iounit;
910 979
911done: 980error:
912 kfree(tc);
913 kfree(rc);
914 return err; 981 return err;
915} 982}
916EXPORT_SYMBOL(p9_client_open); 983EXPORT_SYMBOL(p9_client_open);
@@ -919,37 +986,38 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
919 char *extension) 986 char *extension)
920{ 987{
921 int err; 988 int err;
922 struct p9_fcall *tc, *rc;
923 struct p9_client *clnt; 989 struct p9_client *clnt;
990 struct p9_req_t *req;
991 struct p9_qid qid;
992 int iounit;
924 993
925 P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid, 994 P9_DPRINTK(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
926 name, perm, mode); 995 fid->fid, name, perm, mode);
927 err = 0; 996 err = 0;
928 tc = NULL;
929 rc = NULL;
930 clnt = fid->clnt; 997 clnt = fid->clnt;
931 998
932 if (fid->mode != -1) 999 if (fid->mode != -1)
933 return -EINVAL; 1000 return -EINVAL;
934 1001
935 tc = p9_create_tcreate(fid->fid, name, perm, mode, extension, 1002 req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm,
936 clnt->dotu); 1003 mode, extension);
937 if (IS_ERR(tc)) { 1004 if (IS_ERR(req)) {
938 err = PTR_ERR(tc); 1005 err = PTR_ERR(req);
939 tc = NULL; 1006 goto error;
940 goto done;
941 } 1007 }
942 1008
943 err = p9_client_rpc(clnt, tc, &rc); 1009 err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
1010 p9_free_req(clnt, req);
944 if (err) 1011 if (err)
945 goto done; 1012 goto error;
1013
1014 P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
1015 qid.type, qid.path, qid.version, iounit);
946 1016
947 fid->mode = mode; 1017 fid->mode = mode;
948 fid->iounit = rc->params.ropen.iounit; 1018 fid->iounit = iounit;
949 1019
950done: 1020error:
951 kfree(tc);
952 kfree(rc);
953 return err; 1021 return err;
954} 1022}
955EXPORT_SYMBOL(p9_client_fcreate); 1023EXPORT_SYMBOL(p9_client_fcreate);
@@ -957,31 +1025,25 @@ EXPORT_SYMBOL(p9_client_fcreate);
957int p9_client_clunk(struct p9_fid *fid) 1025int p9_client_clunk(struct p9_fid *fid)
958{ 1026{
959 int err; 1027 int err;
960 struct p9_fcall *tc, *rc;
961 struct p9_client *clnt; 1028 struct p9_client *clnt;
1029 struct p9_req_t *req;
962 1030
963 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 1031 P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid);
964 err = 0; 1032 err = 0;
965 tc = NULL;
966 rc = NULL;
967 clnt = fid->clnt; 1033 clnt = fid->clnt;
968 1034
969 tc = p9_create_tclunk(fid->fid); 1035 req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid);
970 if (IS_ERR(tc)) { 1036 if (IS_ERR(req)) {
971 err = PTR_ERR(tc); 1037 err = PTR_ERR(req);
972 tc = NULL; 1038 goto error;
973 goto done;
974 } 1039 }
975 1040
976 err = p9_client_rpc(clnt, tc, &rc); 1041 P9_DPRINTK(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
977 if (err)
978 goto done;
979 1042
1043 p9_free_req(clnt, req);
980 p9_fid_destroy(fid); 1044 p9_fid_destroy(fid);
981 1045
982done: 1046error:
983 kfree(tc);
984 kfree(rc);
985 return err; 1047 return err;
986} 1048}
987EXPORT_SYMBOL(p9_client_clunk); 1049EXPORT_SYMBOL(p9_client_clunk);
@@ -989,31 +1051,25 @@ EXPORT_SYMBOL(p9_client_clunk);
989int p9_client_remove(struct p9_fid *fid) 1051int p9_client_remove(struct p9_fid *fid)
990{ 1052{
991 int err; 1053 int err;
992 struct p9_fcall *tc, *rc;
993 struct p9_client *clnt; 1054 struct p9_client *clnt;
1055 struct p9_req_t *req;
994 1056
995 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 1057 P9_DPRINTK(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
996 err = 0; 1058 err = 0;
997 tc = NULL;
998 rc = NULL;
999 clnt = fid->clnt; 1059 clnt = fid->clnt;
1000 1060
1001 tc = p9_create_tremove(fid->fid); 1061 req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
1002 if (IS_ERR(tc)) { 1062 if (IS_ERR(req)) {
1003 err = PTR_ERR(tc); 1063 err = PTR_ERR(req);
1004 tc = NULL; 1064 goto error;
1005 goto done;
1006 } 1065 }
1007 1066
1008 err = p9_client_rpc(clnt, tc, &rc); 1067 P9_DPRINTK(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
1009 if (err)
1010 goto done;
1011 1068
1069 p9_free_req(clnt, req);
1012 p9_fid_destroy(fid); 1070 p9_fid_destroy(fid);
1013 1071
1014done: 1072error:
1015 kfree(tc);
1016 kfree(rc);
1017 return err; 1073 return err;
1018} 1074}
1019EXPORT_SYMBOL(p9_client_remove); 1075EXPORT_SYMBOL(p9_client_remove);
@@ -1022,15 +1078,14 @@ int
1022p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, 1078p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1023 u32 count) 1079 u32 count)
1024{ 1080{
1025 int err, n, rsize, total; 1081 int err, rsize, total;
1026 struct p9_fcall *tc, *rc;
1027 struct p9_client *clnt; 1082 struct p9_client *clnt;
1083 struct p9_req_t *req;
1084 char *dataptr;
1028 1085
1029 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid, 1086 P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid,
1030 (long long unsigned) offset, count); 1087 (long long unsigned) offset, count);
1031 err = 0; 1088 err = 0;
1032 tc = NULL;
1033 rc = NULL;
1034 clnt = fid->clnt; 1089 clnt = fid->clnt;
1035 total = 0; 1090 total = 0;
1036 1091
@@ -1038,53 +1093,40 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1038 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1093 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1039 rsize = clnt->msize - P9_IOHDRSZ; 1094 rsize = clnt->msize - P9_IOHDRSZ;
1040 1095
1041 do { 1096 if (count < rsize)
1042 if (count < rsize) 1097 rsize = count;
1043 rsize = count;
1044 1098
1045 tc = p9_create_tread(fid->fid, offset, rsize); 1099 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize);
1046 if (IS_ERR(tc)) { 1100 if (IS_ERR(req)) {
1047 err = PTR_ERR(tc); 1101 err = PTR_ERR(req);
1048 tc = NULL; 1102 goto error;
1049 goto error; 1103 }
1050 }
1051 1104
1052 err = p9_client_rpc(clnt, tc, &rc); 1105 err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr);
1053 if (err) 1106 if (err)
1054 goto error; 1107 goto free_and_error;
1055 1108
1056 n = rc->params.rread.count; 1109 P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1057 if (n > count)
1058 n = count;
1059 1110
1060 if (data) { 1111 if (data) {
1061 memmove(data, rc->params.rread.data, n); 1112 memmove(data, dataptr, count);
1062 data += n; 1113 data += count;
1063 } 1114 }
1064 1115
1065 if (udata) { 1116 if (udata) {
1066 err = copy_to_user(udata, rc->params.rread.data, n); 1117 err = copy_to_user(udata, dataptr, count);
1067 if (err) { 1118 if (err) {
1068 err = -EFAULT; 1119 err = -EFAULT;
1069 goto error; 1120 goto free_and_error;
1070 }
1071 udata += n;
1072 } 1121 }
1122 }
1073 1123
1074 count -= n; 1124 p9_free_req(clnt, req);
1075 offset += n; 1125 return count;
1076 total += n;
1077 kfree(tc);
1078 tc = NULL;
1079 kfree(rc);
1080 rc = NULL;
1081 } while (count > 0 && n == rsize);
1082
1083 return total;
1084 1126
1127free_and_error:
1128 p9_free_req(clnt, req);
1085error: 1129error:
1086 kfree(tc);
1087 kfree(rc);
1088 return err; 1130 return err;
1089} 1131}
1090EXPORT_SYMBOL(p9_client_read); 1132EXPORT_SYMBOL(p9_client_read);
@@ -1093,15 +1135,13 @@ int
1093p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, 1135p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1094 u64 offset, u32 count) 1136 u64 offset, u32 count)
1095{ 1137{
1096 int err, n, rsize, total; 1138 int err, rsize, total;
1097 struct p9_fcall *tc, *rc;
1098 struct p9_client *clnt; 1139 struct p9_client *clnt;
1140 struct p9_req_t *req;
1099 1141
1100 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid, 1142 P9_DPRINTK(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n",
1101 (long long unsigned) offset, count); 1143 fid->fid, (long long unsigned) offset, count);
1102 err = 0; 1144 err = 0;
1103 tc = NULL;
1104 rc = NULL;
1105 clnt = fid->clnt; 1145 clnt = fid->clnt;
1106 total = 0; 1146 total = 0;
1107 1147
@@ -1109,129 +1149,70 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1109 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1149 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1110 rsize = clnt->msize - P9_IOHDRSZ; 1150 rsize = clnt->msize - P9_IOHDRSZ;
1111 1151
1112 do { 1152 if (count < rsize)
1113 if (count < rsize) 1153 rsize = count;
1114 rsize = count; 1154 if (data)
1115 1155 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset,
1116 if (data) 1156 rsize, data);
1117 tc = p9_create_twrite(fid->fid, offset, rsize, data); 1157 else
1118 else 1158 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset,
1119 tc = p9_create_twrite_u(fid->fid, offset, rsize, udata); 1159 rsize, udata);
1120 if (IS_ERR(tc)) { 1160 if (IS_ERR(req)) {
1121 err = PTR_ERR(tc); 1161 err = PTR_ERR(req);
1122 tc = NULL; 1162 goto error;
1123 goto error; 1163 }
1124 }
1125
1126 err = p9_client_rpc(clnt, tc, &rc);
1127 if (err)
1128 goto error;
1129
1130 n = rc->params.rread.count;
1131 count -= n;
1132
1133 if (data)
1134 data += n;
1135 else
1136 udata += n;
1137 1164
1138 offset += n; 1165 err = p9pdu_readf(req->rc, clnt->dotu, "d", &count);
1139 total += n; 1166 if (err)
1140 kfree(tc); 1167 goto free_and_error;
1141 tc = NULL; 1168 P9_DPRINTK(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
1142 kfree(rc);
1143 rc = NULL;
1144 } while (count > 0);
1145 1169
1146 return total; 1170 p9_free_req(clnt, req);
1171 return count;
1147 1172
1173free_and_error:
1174 p9_free_req(clnt, req);
1148error: 1175error:
1149 kfree(tc);
1150 kfree(rc);
1151 return err; 1176 return err;
1152} 1177}
1153EXPORT_SYMBOL(p9_client_write); 1178EXPORT_SYMBOL(p9_client_write);
1154 1179
1155static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu) 1180struct p9_wstat *p9_client_stat(struct p9_fid *fid)
1156{ 1181{
1157 int n; 1182 int err;
1158 char *p; 1183 struct p9_client *clnt;
1159 struct p9_stat *ret; 1184 struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
1160 1185 struct p9_req_t *req;
1161 n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len + 1186 u16 ignored;
1162 st->muid.len;
1163 1187
1164 if (dotu) 1188 P9_DPRINTK(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);
1165 n += st->extension.len;
1166 1189
1167 ret = kmalloc(n, GFP_KERNEL);
1168 if (!ret) 1190 if (!ret)
1169 return ERR_PTR(-ENOMEM); 1191 return ERR_PTR(-ENOMEM);
1170 1192
1171 memmove(ret, st, sizeof(struct p9_stat));
1172 p = ((char *) ret) + sizeof(struct p9_stat);
1173 memmove(p, st->name.str, st->name.len);
1174 ret->name.str = p;
1175 p += st->name.len;
1176 memmove(p, st->uid.str, st->uid.len);
1177 ret->uid.str = p;
1178 p += st->uid.len;
1179 memmove(p, st->gid.str, st->gid.len);
1180 ret->gid.str = p;
1181 p += st->gid.len;
1182 memmove(p, st->muid.str, st->muid.len);
1183 ret->muid.str = p;
1184 p += st->muid.len;
1185
1186 if (dotu) {
1187 memmove(p, st->extension.str, st->extension.len);
1188 ret->extension.str = p;
1189 p += st->extension.len;
1190 }
1191
1192 return ret;
1193}
1194
1195struct p9_stat *p9_client_stat(struct p9_fid *fid)
1196{
1197 int err;
1198 struct p9_fcall *tc, *rc;
1199 struct p9_client *clnt;
1200 struct p9_stat *ret;
1201
1202 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
1203 err = 0; 1193 err = 0;
1204 tc = NULL;
1205 rc = NULL;
1206 ret = NULL;
1207 clnt = fid->clnt; 1194 clnt = fid->clnt;
1208 1195
1209 tc = p9_create_tstat(fid->fid); 1196 req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
1210 if (IS_ERR(tc)) { 1197 if (IS_ERR(req)) {
1211 err = PTR_ERR(tc); 1198 err = PTR_ERR(req);
1212 tc = NULL;
1213 goto error; 1199 goto error;
1214 } 1200 }
1215 1201
1216 err = p9_client_rpc(clnt, tc, &rc); 1202 err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret);
1203 p9_free_req(clnt, req);
1217 if (err) 1204 if (err)
1218 goto error; 1205 goto error;
1219 1206
1220 ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu); 1207 P9_DPRINTK(P9_DEBUG_9P,
1221 if (IS_ERR(ret)) { 1208 "<<< RSTAT sz=%x type=%x dev=%x qid=%2.2x %4.4x %8.8llx"
1222 err = PTR_ERR(ret); 1209 " mode=%8.8x uid=%d gid=%d size=%lld %s\n",
1223 ret = NULL; 1210 ret->size, ret->type, ret->dev, ret->qid.type,
1224 goto error; 1211 ret->qid.version, ret->qid.path, ret->mode,
1225 } 1212 ret->n_uid, ret->n_gid, ret->length, ret->name);
1226 1213
1227 kfree(tc);
1228 kfree(rc);
1229 return ret; 1214 return ret;
1230
1231error: 1215error:
1232 kfree(tc);
1233 kfree(rc);
1234 kfree(ret);
1235 return ERR_PTR(err); 1216 return ERR_PTR(err);
1236} 1217}
1237EXPORT_SYMBOL(p9_client_stat); 1218EXPORT_SYMBOL(p9_client_stat);
@@ -1239,27 +1220,23 @@ EXPORT_SYMBOL(p9_client_stat);
1239int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) 1220int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
1240{ 1221{
1241 int err; 1222 int err;
1242 struct p9_fcall *tc, *rc; 1223 struct p9_req_t *req;
1243 struct p9_client *clnt; 1224 struct p9_client *clnt;
1244 1225
1245 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid); 1226 P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
1246 err = 0; 1227 err = 0;
1247 tc = NULL;
1248 rc = NULL;
1249 clnt = fid->clnt; 1228 clnt = fid->clnt;
1250 1229
1251 tc = p9_create_twstat(fid->fid, wst, clnt->dotu); 1230 req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, 0, wst);
1252 if (IS_ERR(tc)) { 1231 if (IS_ERR(req)) {
1253 err = PTR_ERR(tc); 1232 err = PTR_ERR(req);
1254 tc = NULL; 1233 goto error;
1255 goto done;
1256 } 1234 }
1257 1235
1258 err = p9_client_rpc(clnt, tc, &rc); 1236 P9_DPRINTK(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
1259 1237
1260done: 1238 p9_free_req(clnt, req);
1261 kfree(tc); 1239error:
1262 kfree(rc);
1263 return err; 1240 return err;
1264} 1241}
1265EXPORT_SYMBOL(p9_client_wstat); 1242EXPORT_SYMBOL(p9_client_wstat);