diff options
-rw-r--r-- | net/sunrpc/svc_xprt.c | 103 |
1 files changed, 67 insertions, 36 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 295e6ed21ca0..6ebc9a95bbab 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -568,33 +568,12 @@ static void svc_check_conn_limits(struct svc_serv *serv) | |||
568 | } | 568 | } |
569 | } | 569 | } |
570 | 570 | ||
571 | /* | 571 | int svc_alloc_arg(struct svc_rqst *rqstp) |
572 | * Receive the next request on any transport. This code is carefully | ||
573 | * organised not to touch any cachelines in the shared svc_serv | ||
574 | * structure, only cachelines in the local svc_pool. | ||
575 | */ | ||
576 | int svc_recv(struct svc_rqst *rqstp, long timeout) | ||
577 | { | 572 | { |
578 | struct svc_xprt *xprt = NULL; | 573 | struct svc_serv *serv = rqstp->rq_server; |
579 | struct svc_serv *serv = rqstp->rq_server; | 574 | struct xdr_buf *arg; |
580 | struct svc_pool *pool = rqstp->rq_pool; | 575 | int pages; |
581 | int len, i; | 576 | int i; |
582 | int pages; | ||
583 | struct xdr_buf *arg; | ||
584 | DECLARE_WAITQUEUE(wait, current); | ||
585 | long time_left; | ||
586 | |||
587 | dprintk("svc: server %p waiting for data (to = %ld)\n", | ||
588 | rqstp, timeout); | ||
589 | |||
590 | if (rqstp->rq_xprt) | ||
591 | printk(KERN_ERR | ||
592 | "svc_recv: service %p, transport not NULL!\n", | ||
593 | rqstp); | ||
594 | if (waitqueue_active(&rqstp->rq_wait)) | ||
595 | printk(KERN_ERR | ||
596 | "svc_recv: service %p, wait queue active!\n", | ||
597 | rqstp); | ||
598 | 577 | ||
599 | /* now allocate needed pages. If we get a failure, sleep briefly */ | 578 | /* now allocate needed pages. If we get a failure, sleep briefly */ |
600 | pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; | 579 | pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; |
@@ -624,11 +603,15 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
624 | arg->page_len = (pages-2)*PAGE_SIZE; | 603 | arg->page_len = (pages-2)*PAGE_SIZE; |
625 | arg->len = (pages-1)*PAGE_SIZE; | 604 | arg->len = (pages-1)*PAGE_SIZE; |
626 | arg->tail[0].iov_len = 0; | 605 | arg->tail[0].iov_len = 0; |
606 | return 0; | ||
607 | } | ||
627 | 608 | ||
628 | try_to_freeze(); | 609 | struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) |
629 | cond_resched(); | 610 | { |
630 | if (signalled() || kthread_should_stop()) | 611 | struct svc_xprt *xprt; |
631 | return -EINTR; | 612 | struct svc_pool *pool = rqstp->rq_pool; |
613 | DECLARE_WAITQUEUE(wait, current); | ||
614 | long time_left; | ||
632 | 615 | ||
633 | /* Normally we will wait up to 5 seconds for any required | 616 | /* Normally we will wait up to 5 seconds for any required |
634 | * cache information to be provided. | 617 | * cache information to be provided. |
@@ -666,7 +649,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
666 | if (kthread_should_stop()) { | 649 | if (kthread_should_stop()) { |
667 | set_current_state(TASK_RUNNING); | 650 | set_current_state(TASK_RUNNING); |
668 | spin_unlock_bh(&pool->sp_lock); | 651 | spin_unlock_bh(&pool->sp_lock); |
669 | return -EINTR; | 652 | return ERR_PTR(-EINTR); |
670 | } | 653 | } |
671 | 654 | ||
672 | add_wait_queue(&rqstp->rq_wait, &wait); | 655 | add_wait_queue(&rqstp->rq_wait, &wait); |
@@ -687,19 +670,25 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
687 | spin_unlock_bh(&pool->sp_lock); | 670 | spin_unlock_bh(&pool->sp_lock); |
688 | dprintk("svc: server %p, no data yet\n", rqstp); | 671 | dprintk("svc: server %p, no data yet\n", rqstp); |
689 | if (signalled() || kthread_should_stop()) | 672 | if (signalled() || kthread_should_stop()) |
690 | return -EINTR; | 673 | return ERR_PTR(-EINTR); |
691 | else | 674 | else |
692 | return -EAGAIN; | 675 | return ERR_PTR(-EAGAIN); |
693 | } | 676 | } |
694 | } | 677 | } |
695 | spin_unlock_bh(&pool->sp_lock); | 678 | spin_unlock_bh(&pool->sp_lock); |
679 | return xprt; | ||
680 | } | ||
681 | |||
682 | static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt) | ||
683 | { | ||
684 | struct svc_serv *serv = rqstp->rq_server; | ||
685 | int len = 0; | ||
696 | 686 | ||
697 | len = 0; | ||
698 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { | 687 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { |
699 | dprintk("svc_recv: found XPT_CLOSE\n"); | 688 | dprintk("svc_recv: found XPT_CLOSE\n"); |
700 | svc_delete_xprt(xprt); | 689 | svc_delete_xprt(xprt); |
701 | /* Leave XPT_BUSY set on the dead xprt: */ | 690 | /* Leave XPT_BUSY set on the dead xprt: */ |
702 | goto out; | 691 | return 0; |
703 | } | 692 | } |
704 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { | 693 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { |
705 | struct svc_xprt *newxpt; | 694 | struct svc_xprt *newxpt; |
@@ -727,8 +716,9 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
727 | svc_xprt_received(newxpt); | 716 | svc_xprt_received(newxpt); |
728 | } | 717 | } |
729 | } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) { | 718 | } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) { |
719 | /* XPT_DATA|XPT_DEFERRED case: */ | ||
730 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", | 720 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", |
731 | rqstp, pool->sp_id, xprt, | 721 | rqstp, rqstp->rq_pool->sp_id, xprt, |
732 | atomic_read(&xprt->xpt_ref.refcount)); | 722 | atomic_read(&xprt->xpt_ref.refcount)); |
733 | rqstp->rq_deferred = svc_deferred_dequeue(xprt); | 723 | rqstp->rq_deferred = svc_deferred_dequeue(xprt); |
734 | if (rqstp->rq_deferred) | 724 | if (rqstp->rq_deferred) |
@@ -739,7 +729,48 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
739 | rqstp->rq_reserved = serv->sv_max_mesg; | 729 | rqstp->rq_reserved = serv->sv_max_mesg; |
740 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); | 730 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); |
741 | } | 731 | } |
732 | /* clear XPT_BUSY: */ | ||
742 | svc_xprt_received(xprt); | 733 | svc_xprt_received(xprt); |
734 | return len; | ||
735 | } | ||
736 | |||
737 | /* | ||
738 | * Receive the next request on any transport. This code is carefully | ||
739 | * organised not to touch any cachelines in the shared svc_serv | ||
740 | * structure, only cachelines in the local svc_pool. | ||
741 | */ | ||
742 | int svc_recv(struct svc_rqst *rqstp, long timeout) | ||
743 | { | ||
744 | struct svc_xprt *xprt = NULL; | ||
745 | struct svc_serv *serv = rqstp->rq_server; | ||
746 | int len, err; | ||
747 | |||
748 | dprintk("svc: server %p waiting for data (to = %ld)\n", | ||
749 | rqstp, timeout); | ||
750 | |||
751 | if (rqstp->rq_xprt) | ||
752 | printk(KERN_ERR | ||
753 | "svc_recv: service %p, transport not NULL!\n", | ||
754 | rqstp); | ||
755 | if (waitqueue_active(&rqstp->rq_wait)) | ||
756 | printk(KERN_ERR | ||
757 | "svc_recv: service %p, wait queue active!\n", | ||
758 | rqstp); | ||
759 | |||
760 | err = svc_alloc_arg(rqstp); | ||
761 | if (err) | ||
762 | return err; | ||
763 | |||
764 | try_to_freeze(); | ||
765 | cond_resched(); | ||
766 | if (signalled() || kthread_should_stop()) | ||
767 | return -EINTR; | ||
768 | |||
769 | xprt = svc_get_next_xprt(rqstp, timeout); | ||
770 | if (IS_ERR(xprt)) | ||
771 | return PTR_ERR(xprt); | ||
772 | |||
773 | len = svc_handle_xprt(rqstp, xprt); | ||
743 | 774 | ||
744 | /* No data, incomplete (TCP) read, or accept() */ | 775 | /* No data, incomplete (TCP) read, or accept() */ |
745 | if (len <= 0) | 776 | if (len <= 0) |