diff options
Diffstat (limited to 'net/9p/client.c')
-rw-r--r-- | net/9p/client.c | 391 |
1 files changed, 291 insertions, 100 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 0505a03c374c..305a4e719b03 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -203,11 +203,12 @@ free_and_return: | |||
203 | * | 203 | * |
204 | */ | 204 | */ |
205 | 205 | ||
206 | static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) | 206 | static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag, int max_size) |
207 | { | 207 | { |
208 | unsigned long flags; | 208 | unsigned long flags; |
209 | int row, col; | 209 | int row, col; |
210 | struct p9_req_t *req; | 210 | struct p9_req_t *req; |
211 | int alloc_msize = min(c->msize, max_size); | ||
211 | 212 | ||
212 | /* This looks up the original request by tag so we know which | 213 | /* This looks up the original request by tag so we know which |
213 | * buffer to read the data into */ | 214 | * buffer to read the data into */ |
@@ -245,23 +246,12 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) | |||
245 | return ERR_PTR(-ENOMEM); | 246 | return ERR_PTR(-ENOMEM); |
246 | } | 247 | } |
247 | init_waitqueue_head(req->wq); | 248 | init_waitqueue_head(req->wq); |
248 | if ((c->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) == | 249 | req->tc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, |
249 | P9_TRANS_PREF_PAYLOAD_SEP) { | 250 | GFP_NOFS); |
250 | int alloc_msize = min(c->msize, 4096); | 251 | req->tc->capacity = alloc_msize; |
251 | req->tc = kmalloc(sizeof(struct p9_fcall)+alloc_msize, | 252 | req->rc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, |
252 | GFP_NOFS); | 253 | GFP_NOFS); |
253 | req->tc->capacity = alloc_msize; | 254 | req->rc->capacity = alloc_msize; |
254 | req->rc = kmalloc(sizeof(struct p9_fcall)+alloc_msize, | ||
255 | GFP_NOFS); | ||
256 | req->rc->capacity = alloc_msize; | ||
257 | } else { | ||
258 | req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize, | ||
259 | GFP_NOFS); | ||
260 | req->tc->capacity = c->msize; | ||
261 | req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize, | ||
262 | GFP_NOFS); | ||
263 | req->rc->capacity = c->msize; | ||
264 | } | ||
265 | if ((!req->tc) || (!req->rc)) { | 255 | if ((!req->tc) || (!req->rc)) { |
266 | printk(KERN_ERR "Couldn't grow tag array\n"); | 256 | printk(KERN_ERR "Couldn't grow tag array\n"); |
267 | kfree(req->tc); | 257 | kfree(req->tc); |
@@ -485,27 +475,8 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
485 | 475 | ||
486 | if (!p9_is_proto_dotl(c)) { | 476 | if (!p9_is_proto_dotl(c)) { |
487 | char *ename; | 477 | char *ename; |
488 | |||
489 | if (req->tc->pbuf_size) { | ||
490 | /* Handle user buffers */ | ||
491 | size_t len = req->rc->size - req->rc->offset; | ||
492 | if (req->tc->pubuf) { | ||
493 | /* User Buffer */ | ||
494 | err = copy_from_user( | ||
495 | &req->rc->sdata[req->rc->offset], | ||
496 | req->tc->pubuf, len); | ||
497 | if (err) { | ||
498 | err = -EFAULT; | ||
499 | goto out_err; | ||
500 | } | ||
501 | } else { | ||
502 | /* Kernel Buffer */ | ||
503 | memmove(&req->rc->sdata[req->rc->offset], | ||
504 | req->tc->pkbuf, len); | ||
505 | } | ||
506 | } | ||
507 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", | 478 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", |
508 | &ename, &ecode); | 479 | &ename, &ecode); |
509 | if (err) | 480 | if (err) |
510 | goto out_err; | 481 | goto out_err; |
511 | 482 | ||
@@ -515,11 +486,10 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
515 | if (!err || !IS_ERR_VALUE(err)) { | 486 | if (!err || !IS_ERR_VALUE(err)) { |
516 | err = p9_errstr2errno(ename, strlen(ename)); | 487 | err = p9_errstr2errno(ename, strlen(ename)); |
517 | 488 | ||
518 | P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, | 489 | P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", |
519 | ename); | 490 | -ecode, ename); |
520 | |||
521 | kfree(ename); | ||
522 | } | 491 | } |
492 | kfree(ename); | ||
523 | } else { | 493 | } else { |
524 | err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); | 494 | err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); |
525 | err = -ecode; | 495 | err = -ecode; |
@@ -527,7 +497,6 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
527 | P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); | 497 | P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); |
528 | } | 498 | } |
529 | 499 | ||
530 | |||
531 | return err; | 500 | return err; |
532 | 501 | ||
533 | out_err: | 502 | out_err: |
@@ -536,6 +505,110 @@ out_err: | |||
536 | return err; | 505 | return err; |
537 | } | 506 | } |
538 | 507 | ||
508 | /** | ||
509 | * p9_check_zc_errors - check 9p packet for error return and process it | ||
510 | * @c: current client instance | ||
511 | * @req: request to parse and check for error conditions | ||
512 | * @in_hdrlen: Size of response protocol buffer. | ||
513 | * | ||
514 | * returns error code if one is discovered, otherwise returns 0 | ||
515 | * | ||
516 | * this will have to be more complicated if we have multiple | ||
517 | * error packet types | ||
518 | */ | ||
519 | |||
520 | static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, | ||
521 | char *uidata, int in_hdrlen, int kern_buf) | ||
522 | { | ||
523 | int err; | ||
524 | int ecode; | ||
525 | int8_t type; | ||
526 | char *ename = NULL; | ||
527 | |||
528 | err = p9_parse_header(req->rc, NULL, &type, NULL, 0); | ||
529 | if (err) { | ||
530 | P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); | ||
531 | return err; | ||
532 | } | ||
533 | |||
534 | if (type != P9_RERROR && type != P9_RLERROR) | ||
535 | return 0; | ||
536 | |||
537 | if (!p9_is_proto_dotl(c)) { | ||
538 | /* Error is reported in string format */ | ||
539 | uint16_t len; | ||
540 | /* 7 = header size for RERROR, 2 is the size of string len; */ | ||
541 | int inline_len = in_hdrlen - (7 + 2); | ||
542 | |||
543 | /* Read the size of error string */ | ||
544 | err = p9pdu_readf(req->rc, c->proto_version, "w", &len); | ||
545 | if (err) | ||
546 | goto out_err; | ||
547 | |||
548 | ename = kmalloc(len + 1, GFP_NOFS); | ||
549 | if (!ename) { | ||
550 | err = -ENOMEM; | ||
551 | goto out_err; | ||
552 | } | ||
553 | if (len <= inline_len) { | ||
554 | /* We have error in protocol buffer itself */ | ||
555 | if (pdu_read(req->rc, ename, len)) { | ||
556 | err = -EFAULT; | ||
557 | goto out_free; | ||
558 | |||
559 | } | ||
560 | } else { | ||
561 | /* | ||
562 | * Part of the data is in user space buffer. | ||
563 | */ | ||
564 | if (pdu_read(req->rc, ename, inline_len)) { | ||
565 | err = -EFAULT; | ||
566 | goto out_free; | ||
567 | |||
568 | } | ||
569 | if (kern_buf) { | ||
570 | memcpy(ename + inline_len, uidata, | ||
571 | len - inline_len); | ||
572 | } else { | ||
573 | err = copy_from_user(ename + inline_len, | ||
574 | uidata, len - inline_len); | ||
575 | if (err) { | ||
576 | err = -EFAULT; | ||
577 | goto out_free; | ||
578 | } | ||
579 | } | ||
580 | } | ||
581 | ename[len] = 0; | ||
582 | if (p9_is_proto_dotu(c)) { | ||
583 | /* For dotu we also have error code */ | ||
584 | err = p9pdu_readf(req->rc, | ||
585 | c->proto_version, "d", &ecode); | ||
586 | if (err) | ||
587 | goto out_free; | ||
588 | err = -ecode; | ||
589 | } | ||
590 | if (!err || !IS_ERR_VALUE(err)) { | ||
591 | err = p9_errstr2errno(ename, strlen(ename)); | ||
592 | |||
593 | P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", | ||
594 | -ecode, ename); | ||
595 | } | ||
596 | kfree(ename); | ||
597 | } else { | ||
598 | err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); | ||
599 | err = -ecode; | ||
600 | |||
601 | P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); | ||
602 | } | ||
603 | return err; | ||
604 | |||
605 | out_free: | ||
606 | kfree(ename); | ||
607 | out_err: | ||
608 | P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); | ||
609 | return err; | ||
610 | } | ||
611 | |||
539 | static struct p9_req_t * | 612 | static struct p9_req_t * |
540 | p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); | 613 | p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); |
541 | 614 | ||
@@ -579,23 +652,12 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) | |||
579 | return 0; | 652 | return 0; |
580 | } | 653 | } |
581 | 654 | ||
582 | /** | 655 | static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, |
583 | * p9_client_rpc - issue a request and wait for a response | 656 | int8_t type, int req_size, |
584 | * @c: client session | 657 | const char *fmt, va_list ap) |
585 | * @type: type of request | ||
586 | * @fmt: protocol format string (see protocol.c) | ||
587 | * | ||
588 | * Returns request structure (which client must free using p9_free_req) | ||
589 | */ | ||
590 | |||
591 | static struct p9_req_t * | ||
592 | p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | ||
593 | { | 658 | { |
594 | va_list ap; | ||
595 | int tag, err; | 659 | int tag, err; |
596 | struct p9_req_t *req; | 660 | struct p9_req_t *req; |
597 | unsigned long flags; | ||
598 | int sigpending; | ||
599 | 661 | ||
600 | P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); | 662 | P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); |
601 | 663 | ||
@@ -607,12 +669,6 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
607 | if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) | 669 | if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) |
608 | return ERR_PTR(-EIO); | 670 | return ERR_PTR(-EIO); |
609 | 671 | ||
610 | if (signal_pending(current)) { | ||
611 | sigpending = 1; | ||
612 | clear_thread_flag(TIF_SIGPENDING); | ||
613 | } else | ||
614 | sigpending = 0; | ||
615 | |||
616 | tag = P9_NOTAG; | 672 | tag = P9_NOTAG; |
617 | if (type != P9_TVERSION) { | 673 | if (type != P9_TVERSION) { |
618 | tag = p9_idpool_get(c->tagpool); | 674 | tag = p9_idpool_get(c->tagpool); |
@@ -620,18 +676,50 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
620 | return ERR_PTR(-ENOMEM); | 676 | return ERR_PTR(-ENOMEM); |
621 | } | 677 | } |
622 | 678 | ||
623 | req = p9_tag_alloc(c, tag); | 679 | req = p9_tag_alloc(c, tag, req_size); |
624 | if (IS_ERR(req)) | 680 | if (IS_ERR(req)) |
625 | return req; | 681 | return req; |
626 | 682 | ||
627 | /* marshall the data */ | 683 | /* marshall the data */ |
628 | p9pdu_prepare(req->tc, tag, type); | 684 | p9pdu_prepare(req->tc, tag, type); |
629 | va_start(ap, fmt); | ||
630 | err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); | 685 | err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); |
631 | va_end(ap); | ||
632 | if (err) | 686 | if (err) |
633 | goto reterr; | 687 | goto reterr; |
634 | p9pdu_finalize(req->tc); | 688 | p9pdu_finalize(req->tc); |
689 | return req; | ||
690 | reterr: | ||
691 | p9_free_req(c, req); | ||
692 | return ERR_PTR(err); | ||
693 | } | ||
694 | |||
695 | /** | ||
696 | * p9_client_rpc - issue a request and wait for a response | ||
697 | * @c: client session | ||
698 | * @type: type of request | ||
699 | * @fmt: protocol format string (see protocol.c) | ||
700 | * | ||
701 | * Returns request structure (which client must free using p9_free_req) | ||
702 | */ | ||
703 | |||
704 | static struct p9_req_t * | ||
705 | p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | ||
706 | { | ||
707 | va_list ap; | ||
708 | int sigpending, err; | ||
709 | unsigned long flags; | ||
710 | struct p9_req_t *req; | ||
711 | |||
712 | va_start(ap, fmt); | ||
713 | req = p9_client_prepare_req(c, type, c->msize, fmt, ap); | ||
714 | va_end(ap); | ||
715 | if (IS_ERR(req)) | ||
716 | return req; | ||
717 | |||
718 | if (signal_pending(current)) { | ||
719 | sigpending = 1; | ||
720 | clear_thread_flag(TIF_SIGPENDING); | ||
721 | } else | ||
722 | sigpending = 0; | ||
635 | 723 | ||
636 | err = c->trans_mod->request(c, req); | 724 | err = c->trans_mod->request(c, req); |
637 | if (err < 0) { | 725 | if (err < 0) { |
@@ -639,18 +727,14 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
639 | c->status = Disconnected; | 727 | c->status = Disconnected; |
640 | goto reterr; | 728 | goto reterr; |
641 | } | 729 | } |
642 | 730 | /* Wait for the response */ | |
643 | P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); | ||
644 | err = wait_event_interruptible(*req->wq, | 731 | err = wait_event_interruptible(*req->wq, |
645 | req->status >= REQ_STATUS_RCVD); | 732 | req->status >= REQ_STATUS_RCVD); |
646 | P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n", | ||
647 | req->wq, tag, err); | ||
648 | 733 | ||
649 | if (req->status == REQ_STATUS_ERROR) { | 734 | if (req->status == REQ_STATUS_ERROR) { |
650 | P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); | 735 | P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); |
651 | err = req->t_err; | 736 | err = req->t_err; |
652 | } | 737 | } |
653 | |||
654 | if ((err == -ERESTARTSYS) && (c->status == Connected)) { | 738 | if ((err == -ERESTARTSYS) && (c->status == Connected)) { |
655 | P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); | 739 | P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); |
656 | sigpending = 1; | 740 | sigpending = 1; |
@@ -663,13 +747,11 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
663 | if (req->status == REQ_STATUS_RCVD) | 747 | if (req->status == REQ_STATUS_RCVD) |
664 | err = 0; | 748 | err = 0; |
665 | } | 749 | } |
666 | |||
667 | if (sigpending) { | 750 | if (sigpending) { |
668 | spin_lock_irqsave(¤t->sighand->siglock, flags); | 751 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
669 | recalc_sigpending(); | 752 | recalc_sigpending(); |
670 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | 753 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
671 | } | 754 | } |
672 | |||
673 | if (err < 0) | 755 | if (err < 0) |
674 | goto reterr; | 756 | goto reterr; |
675 | 757 | ||
@@ -678,7 +760,92 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
678 | P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type); | 760 | P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type); |
679 | return req; | 761 | return req; |
680 | } | 762 | } |
763 | reterr: | ||
764 | P9_DPRINTK(P9_DEBUG_MUX, | ||
765 | "exit: client %p op %d error: %d\n", c, type, err); | ||
766 | p9_free_req(c, req); | ||
767 | return ERR_PTR(err); | ||
768 | } | ||
769 | |||
770 | /** | ||
771 | * p9_client_zc_rpc - issue a request and wait for a response | ||
772 | * @c: client session | ||
773 | * @type: type of request | ||
774 | * @uidata: user bffer that should be ued for zero copy read | ||
775 | * @uodata: user buffer that shoud be user for zero copy write | ||
776 | * @inlen: read buffer size | ||
777 | * @olen: write buffer size | ||
778 | * @hdrlen: reader header size, This is the size of response protocol data | ||
779 | * @fmt: protocol format string (see protocol.c) | ||
780 | * | ||
781 | * Returns request structure (which client must free using p9_free_req) | ||
782 | */ | ||
783 | static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, | ||
784 | char *uidata, char *uodata, | ||
785 | int inlen, int olen, int in_hdrlen, | ||
786 | int kern_buf, const char *fmt, ...) | ||
787 | { | ||
788 | va_list ap; | ||
789 | int sigpending, err; | ||
790 | unsigned long flags; | ||
791 | struct p9_req_t *req; | ||
792 | |||
793 | va_start(ap, fmt); | ||
794 | /* | ||
795 | * We allocate a inline protocol data of only 4k bytes. | ||
796 | * The actual content is passed in zero-copy fashion. | ||
797 | */ | ||
798 | req = p9_client_prepare_req(c, type, P9_ZC_HDR_SZ, fmt, ap); | ||
799 | va_end(ap); | ||
800 | if (IS_ERR(req)) | ||
801 | return req; | ||
802 | |||
803 | if (signal_pending(current)) { | ||
804 | sigpending = 1; | ||
805 | clear_thread_flag(TIF_SIGPENDING); | ||
806 | } else | ||
807 | sigpending = 0; | ||
808 | |||
809 | /* If we are called with KERNEL_DS force kern_buf */ | ||
810 | if (segment_eq(get_fs(), KERNEL_DS)) | ||
811 | kern_buf = 1; | ||
812 | |||
813 | err = c->trans_mod->zc_request(c, req, uidata, uodata, | ||
814 | inlen, olen, in_hdrlen, kern_buf); | ||
815 | if (err < 0) { | ||
816 | if (err == -EIO) | ||
817 | c->status = Disconnected; | ||
818 | goto reterr; | ||
819 | } | ||
820 | if (req->status == REQ_STATUS_ERROR) { | ||
821 | P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); | ||
822 | err = req->t_err; | ||
823 | } | ||
824 | if ((err == -ERESTARTSYS) && (c->status == Connected)) { | ||
825 | P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); | ||
826 | sigpending = 1; | ||
827 | clear_thread_flag(TIF_SIGPENDING); | ||
681 | 828 | ||
829 | if (c->trans_mod->cancel(c, req)) | ||
830 | p9_client_flush(c, req); | ||
831 | |||
832 | /* if we received the response anyway, don't signal error */ | ||
833 | if (req->status == REQ_STATUS_RCVD) | ||
834 | err = 0; | ||
835 | } | ||
836 | if (sigpending) { | ||
837 | spin_lock_irqsave(¤t->sighand->siglock, flags); | ||
838 | recalc_sigpending(); | ||
839 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
840 | } | ||
841 | if (err < 0) | ||
842 | goto reterr; | ||
843 | |||
844 | err = p9_check_zc_errors(c, req, uidata, in_hdrlen, kern_buf); | ||
845 | if (!err) { | ||
846 | P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type); | ||
847 | return req; | ||
848 | } | ||
682 | reterr: | 849 | reterr: |
683 | P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type, | 850 | P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type, |
684 | err); | 851 | err); |
@@ -1330,13 +1497,15 @@ int | |||
1330 | p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | 1497 | p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, |
1331 | u32 count) | 1498 | u32 count) |
1332 | { | 1499 | { |
1333 | int err, rsize; | ||
1334 | struct p9_client *clnt; | ||
1335 | struct p9_req_t *req; | ||
1336 | char *dataptr; | 1500 | char *dataptr; |
1501 | int kernel_buf = 0; | ||
1502 | struct p9_req_t *req; | ||
1503 | struct p9_client *clnt; | ||
1504 | int err, rsize, non_zc = 0; | ||
1505 | |||
1337 | 1506 | ||
1338 | P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid, | 1507 | P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", |
1339 | (long long unsigned) offset, count); | 1508 | fid->fid, (long long unsigned) offset, count); |
1340 | err = 0; | 1509 | err = 0; |
1341 | clnt = fid->clnt; | 1510 | clnt = fid->clnt; |
1342 | 1511 | ||
@@ -1348,13 +1517,24 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | |||
1348 | rsize = count; | 1517 | rsize = count; |
1349 | 1518 | ||
1350 | /* Don't bother zerocopy for small IO (< 1024) */ | 1519 | /* Don't bother zerocopy for small IO (< 1024) */ |
1351 | if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) == | 1520 | if (clnt->trans_mod->zc_request && rsize > 1024) { |
1352 | P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) { | 1521 | char *indata; |
1353 | req = p9_client_rpc(clnt, P9_TREAD, "dqE", fid->fid, offset, | 1522 | if (data) { |
1354 | rsize, data, udata); | 1523 | kernel_buf = 1; |
1524 | indata = data; | ||
1525 | } else | ||
1526 | indata = (char *)udata; | ||
1527 | /* | ||
1528 | * response header len is 11 | ||
1529 | * PDU Header(7) + IO Size (4) | ||
1530 | */ | ||
1531 | req = p9_client_zc_rpc(clnt, P9_TREAD, indata, NULL, rsize, 0, | ||
1532 | 11, kernel_buf, "dqd", fid->fid, | ||
1533 | offset, rsize); | ||
1355 | } else { | 1534 | } else { |
1535 | non_zc = 1; | ||
1356 | req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, | 1536 | req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, |
1357 | rsize); | 1537 | rsize); |
1358 | } | 1538 | } |
1359 | if (IS_ERR(req)) { | 1539 | if (IS_ERR(req)) { |
1360 | err = PTR_ERR(req); | 1540 | err = PTR_ERR(req); |
@@ -1370,7 +1550,7 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | |||
1370 | P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count); | 1550 | P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count); |
1371 | P9_DUMP_PKT(1, req->rc); | 1551 | P9_DUMP_PKT(1, req->rc); |
1372 | 1552 | ||
1373 | if (!req->tc->pbuf_size) { | 1553 | if (non_zc) { |
1374 | if (data) { | 1554 | if (data) { |
1375 | memmove(data, dataptr, count); | 1555 | memmove(data, dataptr, count); |
1376 | } else { | 1556 | } else { |
@@ -1396,6 +1576,7 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, | |||
1396 | u64 offset, u32 count) | 1576 | u64 offset, u32 count) |
1397 | { | 1577 | { |
1398 | int err, rsize; | 1578 | int err, rsize; |
1579 | int kernel_buf = 0; | ||
1399 | struct p9_client *clnt; | 1580 | struct p9_client *clnt; |
1400 | struct p9_req_t *req; | 1581 | struct p9_req_t *req; |
1401 | 1582 | ||
@@ -1411,19 +1592,24 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, | |||
1411 | if (count < rsize) | 1592 | if (count < rsize) |
1412 | rsize = count; | 1593 | rsize = count; |
1413 | 1594 | ||
1414 | /* Don't bother zerocopy form small IO (< 1024) */ | 1595 | /* Don't bother zerocopy for small IO (< 1024) */ |
1415 | if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) == | 1596 | if (clnt->trans_mod->zc_request && rsize > 1024) { |
1416 | P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) { | 1597 | char *odata; |
1417 | req = p9_client_rpc(clnt, P9_TWRITE, "dqE", fid->fid, offset, | 1598 | if (data) { |
1418 | rsize, data, udata); | 1599 | kernel_buf = 1; |
1600 | odata = data; | ||
1601 | } else | ||
1602 | odata = (char *)udata; | ||
1603 | req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, odata, 0, rsize, | ||
1604 | P9_ZC_HDR_SZ, kernel_buf, "dqd", | ||
1605 | fid->fid, offset, rsize); | ||
1419 | } else { | 1606 | } else { |
1420 | |||
1421 | if (data) | 1607 | if (data) |
1422 | req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, | 1608 | req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, |
1423 | offset, rsize, data); | 1609 | offset, rsize, data); |
1424 | else | 1610 | else |
1425 | req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, | 1611 | req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, |
1426 | offset, rsize, udata); | 1612 | offset, rsize, udata); |
1427 | } | 1613 | } |
1428 | if (IS_ERR(req)) { | 1614 | if (IS_ERR(req)) { |
1429 | err = PTR_ERR(req); | 1615 | err = PTR_ERR(req); |
@@ -1824,7 +2010,7 @@ EXPORT_SYMBOL_GPL(p9_client_xattrcreate); | |||
1824 | 2010 | ||
1825 | int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) | 2011 | int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) |
1826 | { | 2012 | { |
1827 | int err, rsize; | 2013 | int err, rsize, non_zc = 0; |
1828 | struct p9_client *clnt; | 2014 | struct p9_client *clnt; |
1829 | struct p9_req_t *req; | 2015 | struct p9_req_t *req; |
1830 | char *dataptr; | 2016 | char *dataptr; |
@@ -1842,13 +2028,18 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) | |||
1842 | if (count < rsize) | 2028 | if (count < rsize) |
1843 | rsize = count; | 2029 | rsize = count; |
1844 | 2030 | ||
1845 | if ((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) == | 2031 | /* Don't bother zerocopy for small IO (< 1024) */ |
1846 | P9_TRANS_PREF_PAYLOAD_SEP) { | 2032 | if (clnt->trans_mod->zc_request && rsize > 1024) { |
1847 | req = p9_client_rpc(clnt, P9_TREADDIR, "dqF", fid->fid, | 2033 | /* |
1848 | offset, rsize, data); | 2034 | * response header len is 11 |
2035 | * PDU Header(7) + IO Size (4) | ||
2036 | */ | ||
2037 | req = p9_client_zc_rpc(clnt, P9_TREADDIR, data, NULL, rsize, 0, | ||
2038 | 11, 1, "dqd", fid->fid, offset, rsize); | ||
1849 | } else { | 2039 | } else { |
2040 | non_zc = 1; | ||
1850 | req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, | 2041 | req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, |
1851 | offset, rsize); | 2042 | offset, rsize); |
1852 | } | 2043 | } |
1853 | if (IS_ERR(req)) { | 2044 | if (IS_ERR(req)) { |
1854 | err = PTR_ERR(req); | 2045 | err = PTR_ERR(req); |
@@ -1863,7 +2054,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) | |||
1863 | 2054 | ||
1864 | P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); | 2055 | P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); |
1865 | 2056 | ||
1866 | if (!req->tc->pbuf_size && data) | 2057 | if (non_zc) |
1867 | memmove(data, dataptr, count); | 2058 | memmove(data, dataptr, count); |
1868 | 2059 | ||
1869 | p9_free_req(clnt, req); | 2060 | p9_free_req(clnt, req); |