aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/client.c
diff options
context:
space:
mode:
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);