aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenkateswararao Jujjuri (JV) <jvrao@linux.vnet.ibm.com>2011-02-01 23:04:59 -0500
committerEric Van Hensbergen <ericvh@gmail.com>2011-03-15 10:57:36 -0400
commitca41bb3e21d7b3cb2079e225e3a7e62e6c776518 (patch)
treefa65d03bf9d4e8839631ae4a295ab3f1b7ba3e06
parent2c66523fd290edeea26cbe8cedd0af167d0f7e5f (diff)
[net/9p] Handle Zero Copy TREAD/RERROR case in !dotl case.
This takes care of copying out error buffers from user buffer payloads when we are using zero copy. This happens because the only payload buffer the server has to respond to the request is the user buffer given for the zero copy read. Because we only use zerocopy when the amount of data to transfer is greater than a certain size (currently 4K) and error strings are limited to ERRMAX (currently 128) we don't need to worry about there being sufficient space for the error to fit in the payload. Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--net/9p/client.c64
1 files changed, 41 insertions, 23 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index 6e07ef494ff2..251abb1699c4 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -443,6 +443,7 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
443{ 443{
444 int8_t type; 444 int8_t type;
445 int err; 445 int err;
446 int ecode;
446 447
447 err = p9_parse_header(req->rc, NULL, &type, NULL, 0); 448 err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
448 if (err) { 449 if (err) {
@@ -450,36 +451,53 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
450 return err; 451 return err;
451 } 452 }
452 453
453 if (type == P9_RERROR || type == P9_RLERROR) { 454 if (type != P9_RERROR && type != P9_RLERROR)
454 int ecode; 455 return 0;
455
456 if (!p9_is_proto_dotl(c)) {
457 char *ename;
458 456
459 err = p9pdu_readf(req->rc, c->proto_version, "s?d", 457 if (!p9_is_proto_dotl(c)) {
460 &ename, &ecode); 458 char *ename;
461 if (err) 459
462 goto out_err; 460 if (req->tc->pbuf_size) {
461 /* Handle user buffers */
462 size_t len = req->rc->size - req->rc->offset;
463 if (req->tc->pubuf) {
464 /* User Buffer */
465 err = copy_from_user(
466 &req->rc->sdata[req->rc->offset],
467 req->tc->pubuf, len);
468 if (err) {
469 err = -EFAULT;
470 goto out_err;
471 }
472 } else {
473 /* Kernel Buffer */
474 memmove(&req->rc->sdata[req->rc->offset],
475 req->tc->pkbuf, len);
476 }
477 }
478 err = p9pdu_readf(req->rc, c->proto_version, "s?d",
479 &ename, &ecode);
480 if (err)
481 goto out_err;
463 482
464 if (p9_is_proto_dotu(c)) 483 if (p9_is_proto_dotu(c))
465 err = -ecode; 484 err = -ecode;
466 485
467 if (!err || !IS_ERR_VALUE(err)) { 486 if (!err || !IS_ERR_VALUE(err)) {
468 err = p9_errstr2errno(ename, strlen(ename)); 487 err = p9_errstr2errno(ename, strlen(ename));
469 488
470 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); 489 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode,
490 ename);
471 491
472 kfree(ename); 492 kfree(ename);
473 }
474 } else {
475 err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
476 err = -ecode;
477
478 P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
479 } 493 }
494 } else {
495 err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
496 err = -ecode;
497
498 P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
499 }
480 500
481 } else
482 err = 0;
483 501
484 return err; 502 return err;
485 503