aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorChuck Lever <cel@citi.umich.edu>2005-08-11 16:25:11 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-09-23 12:38:04 -0400
commitda35187801732397a7e05fb9e77f3700cc35f5db (patch)
tree61307975e36112fd85b98d0df824386e209a5049 /net/sunrpc
parent23475d66bd8600e0c5353f86c1b74f68df27bdb5 (diff)
[PATCH] RPC: proper soft timeout behavior for rpcbind
Implement a best practice: for soft mounts, an rpcbind timeout should cause an RPC request to fail. This also provides an FSM hook for retrying an rpcbind with a different rpcbind protocol version. We'll use this later to try multiple rpcbind protocol versions when binding. To enable this, expose the RPC error code returned during a portmap request to the FSM so it can make some decision about how to report, retry, or fail the request. Test-plan: Hundreds of passes with connectathon NFSv3 locking suite, on the client and server. Version: Thu, 11 Aug 2005 16:01:53 -0400 Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/clnt.c97
1 files changed, 77 insertions, 20 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f17e6153b688..2d3cf0a52d82 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -53,6 +53,7 @@ static void call_allocate(struct rpc_task *task);
53static void call_encode(struct rpc_task *task); 53static void call_encode(struct rpc_task *task);
54static void call_decode(struct rpc_task *task); 54static void call_decode(struct rpc_task *task);
55static void call_bind(struct rpc_task *task); 55static void call_bind(struct rpc_task *task);
56static void call_bind_status(struct rpc_task *task);
56static void call_transmit(struct rpc_task *task); 57static void call_transmit(struct rpc_task *task);
57static void call_status(struct rpc_task *task); 58static void call_status(struct rpc_task *task);
58static void call_refresh(struct rpc_task *task); 59static void call_refresh(struct rpc_task *task);
@@ -734,43 +735,94 @@ static void
734call_bind(struct rpc_task *task) 735call_bind(struct rpc_task *task)
735{ 736{
736 struct rpc_clnt *clnt = task->tk_client; 737 struct rpc_clnt *clnt = task->tk_client;
737 struct rpc_xprt *xprt = clnt->cl_xprt;
738
739 dprintk("RPC: %4d call_bind xprt %p %s connected\n", task->tk_pid,
740 xprt, (xprt_connected(xprt) ? "is" : "is not"));
741 738
742 task->tk_action = (xprt_connected(xprt)) ? call_transmit : call_connect; 739 dprintk("RPC: %4d call_bind (status %d)\n",
740 task->tk_pid, task->tk_status);
743 741
742 task->tk_action = call_connect;
744 if (!clnt->cl_port) { 743 if (!clnt->cl_port) {
745 task->tk_action = call_connect; 744 task->tk_action = call_bind_status;
746 task->tk_timeout = RPC_CONNECT_TIMEOUT; 745 task->tk_timeout = RPC_CONNECT_TIMEOUT;
747 rpc_getport(task, clnt); 746 rpc_getport(task, clnt);
748 } 747 }
749} 748}
750 749
751/* 750/*
752 * 4a. Connect to the RPC server (TCP case) 751 * 4a. Sort out bind result
752 */
753static void
754call_bind_status(struct rpc_task *task)
755{
756 int status = -EACCES;
757
758 if (task->tk_status >= 0) {
759 dprintk("RPC: %4d call_bind_status (status %d)\n",
760 task->tk_pid, task->tk_status);
761 task->tk_status = 0;
762 task->tk_action = call_connect;
763 return;
764 }
765
766 switch (task->tk_status) {
767 case -EACCES:
768 dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n",
769 task->tk_pid);
770 break;
771 case -ETIMEDOUT:
772 dprintk("RPC: %4d rpcbind request timed out\n",
773 task->tk_pid);
774 if (RPC_IS_SOFT(task)) {
775 status = -EIO;
776 break;
777 }
778 goto retry_bind;
779 case -EPFNOSUPPORT:
780 dprintk("RPC: %4d remote rpcbind service unavailable\n",
781 task->tk_pid);
782 break;
783 case -EPROTONOSUPPORT:
784 dprintk("RPC: %4d remote rpcbind version 2 unavailable\n",
785 task->tk_pid);
786 break;
787 default:
788 dprintk("RPC: %4d unrecognized rpcbind error (%d)\n",
789 task->tk_pid, -task->tk_status);
790 status = -EIO;
791 break;
792 }
793
794 rpc_exit(task, status);
795 return;
796
797retry_bind:
798 task->tk_status = 0;
799 task->tk_action = call_bind;
800 return;
801}
802
803/*
804 * 4b. Connect to the RPC server
753 */ 805 */
754static void 806static void
755call_connect(struct rpc_task *task) 807call_connect(struct rpc_task *task)
756{ 808{
757 struct rpc_clnt *clnt = task->tk_client; 809 struct rpc_xprt *xprt = task->tk_xprt;
758 810
759 dprintk("RPC: %4d call_connect status %d\n", 811 dprintk("RPC: %4d call_connect xprt %p %s connected\n",
760 task->tk_pid, task->tk_status); 812 task->tk_pid, xprt,
813 (xprt_connected(xprt) ? "is" : "is not"));
761 814
762 if (xprt_connected(clnt->cl_xprt)) { 815 task->tk_action = call_transmit;
763 task->tk_action = call_transmit; 816 if (!xprt_connected(xprt)) {
764 return; 817 task->tk_action = call_connect_status;
818 if (task->tk_status < 0)
819 return;
820 xprt_connect(task);
765 } 821 }
766 task->tk_action = call_connect_status;
767 if (task->tk_status < 0)
768 return;
769 xprt_connect(task);
770} 822}
771 823
772/* 824/*
773 * 4b. Sort out connect result 825 * 4c. Sort out connect result
774 */ 826 */
775static void 827static void
776call_connect_status(struct rpc_task *task) 828call_connect_status(struct rpc_task *task)
@@ -778,6 +830,9 @@ call_connect_status(struct rpc_task *task)
778 struct rpc_clnt *clnt = task->tk_client; 830 struct rpc_clnt *clnt = task->tk_client;
779 int status = task->tk_status; 831 int status = task->tk_status;
780 832
833 dprintk("RPC: %5u call_connect_status (status %d)\n",
834 task->tk_pid, task->tk_status);
835
781 task->tk_status = 0; 836 task->tk_status = 0;
782 if (status >= 0) { 837 if (status >= 0) {
783 clnt->cl_stats->netreconn++; 838 clnt->cl_stats->netreconn++;
@@ -785,17 +840,19 @@ call_connect_status(struct rpc_task *task)
785 return; 840 return;
786 } 841 }
787 842
788 /* Something failed: we may have to rebind */ 843 /* Something failed: remote service port may have changed */
789 if (clnt->cl_autobind) 844 if (clnt->cl_autobind)
790 clnt->cl_port = 0; 845 clnt->cl_port = 0;
846
791 switch (status) { 847 switch (status) {
792 case -ENOTCONN: 848 case -ENOTCONN:
793 case -ETIMEDOUT: 849 case -ETIMEDOUT:
794 case -EAGAIN: 850 case -EAGAIN:
795 task->tk_action = (clnt->cl_port == 0) ? call_bind : call_connect; 851 task->tk_action = call_bind;
796 break; 852 break;
797 default: 853 default:
798 rpc_exit(task, -EIO); 854 rpc_exit(task, -EIO);
855 break;
799 } 856 }
800} 857}
801 858