diff options
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 80 |
1 files changed, 57 insertions, 23 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index d5553b8179f9..75d748eee0eb 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -188,9 +188,9 @@ out_sleep: | |||
188 | task->tk_timeout = 0; | 188 | task->tk_timeout = 0; |
189 | task->tk_status = -EAGAIN; | 189 | task->tk_status = -EAGAIN; |
190 | if (req && req->rq_ntrans) | 190 | if (req && req->rq_ntrans) |
191 | rpc_sleep_on(&xprt->resend, task, NULL, NULL); | 191 | rpc_sleep_on(&xprt->resend, task, NULL); |
192 | else | 192 | else |
193 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 193 | rpc_sleep_on(&xprt->sending, task, NULL); |
194 | return 0; | 194 | return 0; |
195 | } | 195 | } |
196 | EXPORT_SYMBOL_GPL(xprt_reserve_xprt); | 196 | EXPORT_SYMBOL_GPL(xprt_reserve_xprt); |
@@ -238,9 +238,9 @@ out_sleep: | |||
238 | task->tk_timeout = 0; | 238 | task->tk_timeout = 0; |
239 | task->tk_status = -EAGAIN; | 239 | task->tk_status = -EAGAIN; |
240 | if (req && req->rq_ntrans) | 240 | if (req && req->rq_ntrans) |
241 | rpc_sleep_on(&xprt->resend, task, NULL, NULL); | 241 | rpc_sleep_on(&xprt->resend, task, NULL); |
242 | else | 242 | else |
243 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 243 | rpc_sleep_on(&xprt->sending, task, NULL); |
244 | return 0; | 244 | return 0; |
245 | } | 245 | } |
246 | EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong); | 246 | EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong); |
@@ -447,13 +447,13 @@ EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks); | |||
447 | * @task: task to be put to sleep | 447 | * @task: task to be put to sleep |
448 | * | 448 | * |
449 | */ | 449 | */ |
450 | void xprt_wait_for_buffer_space(struct rpc_task *task) | 450 | void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action) |
451 | { | 451 | { |
452 | struct rpc_rqst *req = task->tk_rqstp; | 452 | struct rpc_rqst *req = task->tk_rqstp; |
453 | struct rpc_xprt *xprt = req->rq_xprt; | 453 | struct rpc_xprt *xprt = req->rq_xprt; |
454 | 454 | ||
455 | task->tk_timeout = req->rq_timeout; | 455 | task->tk_timeout = req->rq_timeout; |
456 | rpc_sleep_on(&xprt->pending, task, NULL, NULL); | 456 | rpc_sleep_on(&xprt->pending, task, action); |
457 | } | 457 | } |
458 | EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space); | 458 | EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space); |
459 | 459 | ||
@@ -472,7 +472,7 @@ void xprt_write_space(struct rpc_xprt *xprt) | |||
472 | if (xprt->snd_task) { | 472 | if (xprt->snd_task) { |
473 | dprintk("RPC: write space: waking waiting task on " | 473 | dprintk("RPC: write space: waking waiting task on " |
474 | "xprt %p\n", xprt); | 474 | "xprt %p\n", xprt); |
475 | rpc_wake_up_task(xprt->snd_task); | 475 | rpc_wake_up_queued_task(&xprt->pending, xprt->snd_task); |
476 | } | 476 | } |
477 | spin_unlock_bh(&xprt->transport_lock); | 477 | spin_unlock_bh(&xprt->transport_lock); |
478 | } | 478 | } |
@@ -602,11 +602,37 @@ void xprt_force_disconnect(struct rpc_xprt *xprt) | |||
602 | /* Try to schedule an autoclose RPC call */ | 602 | /* Try to schedule an autoclose RPC call */ |
603 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) | 603 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) |
604 | queue_work(rpciod_workqueue, &xprt->task_cleanup); | 604 | queue_work(rpciod_workqueue, &xprt->task_cleanup); |
605 | else if (xprt->snd_task != NULL) | 605 | xprt_wake_pending_tasks(xprt, -ENOTCONN); |
606 | rpc_wake_up_task(xprt->snd_task); | 606 | spin_unlock_bh(&xprt->transport_lock); |
607 | } | ||
608 | |||
609 | /** | ||
610 | * xprt_conditional_disconnect - force a transport to disconnect | ||
611 | * @xprt: transport to disconnect | ||
612 | * @cookie: 'connection cookie' | ||
613 | * | ||
614 | * This attempts to break the connection if and only if 'cookie' matches | ||
615 | * the current transport 'connection cookie'. It ensures that we don't | ||
616 | * try to break the connection more than once when we need to retransmit | ||
617 | * a batch of RPC requests. | ||
618 | * | ||
619 | */ | ||
620 | void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie) | ||
621 | { | ||
622 | /* Don't race with the test_bit() in xprt_clear_locked() */ | ||
623 | spin_lock_bh(&xprt->transport_lock); | ||
624 | if (cookie != xprt->connect_cookie) | ||
625 | goto out; | ||
626 | if (test_bit(XPRT_CLOSING, &xprt->state) || !xprt_connected(xprt)) | ||
627 | goto out; | ||
628 | set_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
629 | /* Try to schedule an autoclose RPC call */ | ||
630 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) | ||
631 | queue_work(rpciod_workqueue, &xprt->task_cleanup); | ||
632 | xprt_wake_pending_tasks(xprt, -ENOTCONN); | ||
633 | out: | ||
607 | spin_unlock_bh(&xprt->transport_lock); | 634 | spin_unlock_bh(&xprt->transport_lock); |
608 | } | 635 | } |
609 | EXPORT_SYMBOL_GPL(xprt_force_disconnect); | ||
610 | 636 | ||
611 | static void | 637 | static void |
612 | xprt_init_autodisconnect(unsigned long data) | 638 | xprt_init_autodisconnect(unsigned long data) |
@@ -653,7 +679,7 @@ void xprt_connect(struct rpc_task *task) | |||
653 | task->tk_rqstp->rq_bytes_sent = 0; | 679 | task->tk_rqstp->rq_bytes_sent = 0; |
654 | 680 | ||
655 | task->tk_timeout = xprt->connect_timeout; | 681 | task->tk_timeout = xprt->connect_timeout; |
656 | rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL); | 682 | rpc_sleep_on(&xprt->pending, task, xprt_connect_status); |
657 | xprt->stat.connect_start = jiffies; | 683 | xprt->stat.connect_start = jiffies; |
658 | xprt->ops->connect(task); | 684 | xprt->ops->connect(task); |
659 | } | 685 | } |
@@ -749,18 +775,20 @@ EXPORT_SYMBOL_GPL(xprt_update_rtt); | |||
749 | void xprt_complete_rqst(struct rpc_task *task, int copied) | 775 | void xprt_complete_rqst(struct rpc_task *task, int copied) |
750 | { | 776 | { |
751 | struct rpc_rqst *req = task->tk_rqstp; | 777 | struct rpc_rqst *req = task->tk_rqstp; |
778 | struct rpc_xprt *xprt = req->rq_xprt; | ||
752 | 779 | ||
753 | dprintk("RPC: %5u xid %08x complete (%d bytes received)\n", | 780 | dprintk("RPC: %5u xid %08x complete (%d bytes received)\n", |
754 | task->tk_pid, ntohl(req->rq_xid), copied); | 781 | task->tk_pid, ntohl(req->rq_xid), copied); |
755 | 782 | ||
756 | task->tk_xprt->stat.recvs++; | 783 | xprt->stat.recvs++; |
757 | task->tk_rtt = (long)jiffies - req->rq_xtime; | 784 | task->tk_rtt = (long)jiffies - req->rq_xtime; |
758 | 785 | ||
759 | list_del_init(&req->rq_list); | 786 | list_del_init(&req->rq_list); |
787 | req->rq_private_buf.len = copied; | ||
760 | /* Ensure all writes are done before we update req->rq_received */ | 788 | /* Ensure all writes are done before we update req->rq_received */ |
761 | smp_wmb(); | 789 | smp_wmb(); |
762 | req->rq_received = req->rq_private_buf.len = copied; | 790 | req->rq_received = copied; |
763 | rpc_wake_up_task(task); | 791 | rpc_wake_up_queued_task(&xprt->pending, task); |
764 | } | 792 | } |
765 | EXPORT_SYMBOL_GPL(xprt_complete_rqst); | 793 | EXPORT_SYMBOL_GPL(xprt_complete_rqst); |
766 | 794 | ||
@@ -769,17 +797,17 @@ static void xprt_timer(struct rpc_task *task) | |||
769 | struct rpc_rqst *req = task->tk_rqstp; | 797 | struct rpc_rqst *req = task->tk_rqstp; |
770 | struct rpc_xprt *xprt = req->rq_xprt; | 798 | struct rpc_xprt *xprt = req->rq_xprt; |
771 | 799 | ||
800 | if (task->tk_status != -ETIMEDOUT) | ||
801 | return; | ||
772 | dprintk("RPC: %5u xprt_timer\n", task->tk_pid); | 802 | dprintk("RPC: %5u xprt_timer\n", task->tk_pid); |
773 | 803 | ||
774 | spin_lock(&xprt->transport_lock); | 804 | spin_lock_bh(&xprt->transport_lock); |
775 | if (!req->rq_received) { | 805 | if (!req->rq_received) { |
776 | if (xprt->ops->timer) | 806 | if (xprt->ops->timer) |
777 | xprt->ops->timer(task); | 807 | xprt->ops->timer(task); |
778 | task->tk_status = -ETIMEDOUT; | 808 | } else |
779 | } | 809 | task->tk_status = 0; |
780 | task->tk_timeout = 0; | 810 | spin_unlock_bh(&xprt->transport_lock); |
781 | rpc_wake_up_task(task); | ||
782 | spin_unlock(&xprt->transport_lock); | ||
783 | } | 811 | } |
784 | 812 | ||
785 | /** | 813 | /** |
@@ -849,6 +877,7 @@ void xprt_transmit(struct rpc_task *task) | |||
849 | } else if (!req->rq_bytes_sent) | 877 | } else if (!req->rq_bytes_sent) |
850 | return; | 878 | return; |
851 | 879 | ||
880 | req->rq_connect_cookie = xprt->connect_cookie; | ||
852 | status = xprt->ops->send_request(task); | 881 | status = xprt->ops->send_request(task); |
853 | if (status == 0) { | 882 | if (status == 0) { |
854 | dprintk("RPC: %5u xmit complete\n", task->tk_pid); | 883 | dprintk("RPC: %5u xmit complete\n", task->tk_pid); |
@@ -864,7 +893,7 @@ void xprt_transmit(struct rpc_task *task) | |||
864 | if (!xprt_connected(xprt)) | 893 | if (!xprt_connected(xprt)) |
865 | task->tk_status = -ENOTCONN; | 894 | task->tk_status = -ENOTCONN; |
866 | else if (!req->rq_received) | 895 | else if (!req->rq_received) |
867 | rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); | 896 | rpc_sleep_on(&xprt->pending, task, xprt_timer); |
868 | spin_unlock_bh(&xprt->transport_lock); | 897 | spin_unlock_bh(&xprt->transport_lock); |
869 | return; | 898 | return; |
870 | } | 899 | } |
@@ -875,7 +904,7 @@ void xprt_transmit(struct rpc_task *task) | |||
875 | */ | 904 | */ |
876 | task->tk_status = status; | 905 | task->tk_status = status; |
877 | if (status == -ECONNREFUSED) | 906 | if (status == -ECONNREFUSED) |
878 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 907 | rpc_sleep_on(&xprt->sending, task, NULL); |
879 | } | 908 | } |
880 | 909 | ||
881 | static inline void do_xprt_reserve(struct rpc_task *task) | 910 | static inline void do_xprt_reserve(struct rpc_task *task) |
@@ -895,7 +924,7 @@ static inline void do_xprt_reserve(struct rpc_task *task) | |||
895 | dprintk("RPC: waiting for request slot\n"); | 924 | dprintk("RPC: waiting for request slot\n"); |
896 | task->tk_status = -EAGAIN; | 925 | task->tk_status = -EAGAIN; |
897 | task->tk_timeout = 0; | 926 | task->tk_timeout = 0; |
898 | rpc_sleep_on(&xprt->backlog, task, NULL, NULL); | 927 | rpc_sleep_on(&xprt->backlog, task, NULL); |
899 | } | 928 | } |
900 | 929 | ||
901 | /** | 930 | /** |
@@ -1052,6 +1081,11 @@ static void xprt_destroy(struct kref *kref) | |||
1052 | xprt->shutdown = 1; | 1081 | xprt->shutdown = 1; |
1053 | del_timer_sync(&xprt->timer); | 1082 | del_timer_sync(&xprt->timer); |
1054 | 1083 | ||
1084 | rpc_destroy_wait_queue(&xprt->binding); | ||
1085 | rpc_destroy_wait_queue(&xprt->pending); | ||
1086 | rpc_destroy_wait_queue(&xprt->sending); | ||
1087 | rpc_destroy_wait_queue(&xprt->resend); | ||
1088 | rpc_destroy_wait_queue(&xprt->backlog); | ||
1055 | /* | 1089 | /* |
1056 | * Tear down transport state and free the rpc_xprt | 1090 | * Tear down transport state and free the rpc_xprt |
1057 | */ | 1091 | */ |