diff options
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 89 |
1 files changed, 53 insertions, 36 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 62098d101a1f..a0bfe53f1621 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -152,6 +152,37 @@ out: | |||
152 | EXPORT_SYMBOL_GPL(xprt_unregister_transport); | 152 | EXPORT_SYMBOL_GPL(xprt_unregister_transport); |
153 | 153 | ||
154 | /** | 154 | /** |
155 | * xprt_load_transport - load a transport implementation | ||
156 | * @transport_name: transport to load | ||
157 | * | ||
158 | * Returns: | ||
159 | * 0: transport successfully loaded | ||
160 | * -ENOENT: transport module not available | ||
161 | */ | ||
162 | int xprt_load_transport(const char *transport_name) | ||
163 | { | ||
164 | struct xprt_class *t; | ||
165 | char module_name[sizeof t->name + 5]; | ||
166 | int result; | ||
167 | |||
168 | result = 0; | ||
169 | spin_lock(&xprt_list_lock); | ||
170 | list_for_each_entry(t, &xprt_list, list) { | ||
171 | if (strcmp(t->name, transport_name) == 0) { | ||
172 | spin_unlock(&xprt_list_lock); | ||
173 | goto out; | ||
174 | } | ||
175 | } | ||
176 | spin_unlock(&xprt_list_lock); | ||
177 | strcpy(module_name, "xprt"); | ||
178 | strncat(module_name, transport_name, sizeof t->name); | ||
179 | result = request_module(module_name); | ||
180 | out: | ||
181 | return result; | ||
182 | } | ||
183 | EXPORT_SYMBOL_GPL(xprt_load_transport); | ||
184 | |||
185 | /** | ||
155 | * xprt_reserve_xprt - serialize write access to transports | 186 | * xprt_reserve_xprt - serialize write access to transports |
156 | * @task: task that is requesting access to the transport | 187 | * @task: task that is requesting access to the transport |
157 | * | 188 | * |
@@ -580,7 +611,7 @@ void xprt_disconnect_done(struct rpc_xprt *xprt) | |||
580 | dprintk("RPC: disconnected transport %p\n", xprt); | 611 | dprintk("RPC: disconnected transport %p\n", xprt); |
581 | spin_lock_bh(&xprt->transport_lock); | 612 | spin_lock_bh(&xprt->transport_lock); |
582 | xprt_clear_connected(xprt); | 613 | xprt_clear_connected(xprt); |
583 | xprt_wake_pending_tasks(xprt, -ENOTCONN); | 614 | xprt_wake_pending_tasks(xprt, -EAGAIN); |
584 | spin_unlock_bh(&xprt->transport_lock); | 615 | spin_unlock_bh(&xprt->transport_lock); |
585 | } | 616 | } |
586 | EXPORT_SYMBOL_GPL(xprt_disconnect_done); | 617 | EXPORT_SYMBOL_GPL(xprt_disconnect_done); |
@@ -598,7 +629,7 @@ void xprt_force_disconnect(struct rpc_xprt *xprt) | |||
598 | /* Try to schedule an autoclose RPC call */ | 629 | /* Try to schedule an autoclose RPC call */ |
599 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) | 630 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) |
600 | queue_work(rpciod_workqueue, &xprt->task_cleanup); | 631 | queue_work(rpciod_workqueue, &xprt->task_cleanup); |
601 | xprt_wake_pending_tasks(xprt, -ENOTCONN); | 632 | xprt_wake_pending_tasks(xprt, -EAGAIN); |
602 | spin_unlock_bh(&xprt->transport_lock); | 633 | spin_unlock_bh(&xprt->transport_lock); |
603 | } | 634 | } |
604 | 635 | ||
@@ -625,7 +656,7 @@ void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie) | |||
625 | /* Try to schedule an autoclose RPC call */ | 656 | /* Try to schedule an autoclose RPC call */ |
626 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) | 657 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) |
627 | queue_work(rpciod_workqueue, &xprt->task_cleanup); | 658 | queue_work(rpciod_workqueue, &xprt->task_cleanup); |
628 | xprt_wake_pending_tasks(xprt, -ENOTCONN); | 659 | xprt_wake_pending_tasks(xprt, -EAGAIN); |
629 | out: | 660 | out: |
630 | spin_unlock_bh(&xprt->transport_lock); | 661 | spin_unlock_bh(&xprt->transport_lock); |
631 | } | 662 | } |
@@ -695,9 +726,8 @@ static void xprt_connect_status(struct rpc_task *task) | |||
695 | } | 726 | } |
696 | 727 | ||
697 | switch (task->tk_status) { | 728 | switch (task->tk_status) { |
698 | case -ENOTCONN: | 729 | case -EAGAIN: |
699 | dprintk("RPC: %5u xprt_connect_status: connection broken\n", | 730 | dprintk("RPC: %5u xprt_connect_status: retrying\n", task->tk_pid); |
700 | task->tk_pid); | ||
701 | break; | 731 | break; |
702 | case -ETIMEDOUT: | 732 | case -ETIMEDOUT: |
703 | dprintk("RPC: %5u xprt_connect_status: connect attempt timed " | 733 | dprintk("RPC: %5u xprt_connect_status: connect attempt timed " |
@@ -818,15 +848,8 @@ int xprt_prepare_transmit(struct rpc_task *task) | |||
818 | err = req->rq_received; | 848 | err = req->rq_received; |
819 | goto out_unlock; | 849 | goto out_unlock; |
820 | } | 850 | } |
821 | if (!xprt->ops->reserve_xprt(task)) { | 851 | if (!xprt->ops->reserve_xprt(task)) |
822 | err = -EAGAIN; | 852 | err = -EAGAIN; |
823 | goto out_unlock; | ||
824 | } | ||
825 | |||
826 | if (!xprt_connected(xprt)) { | ||
827 | err = -ENOTCONN; | ||
828 | goto out_unlock; | ||
829 | } | ||
830 | out_unlock: | 853 | out_unlock: |
831 | spin_unlock_bh(&xprt->transport_lock); | 854 | spin_unlock_bh(&xprt->transport_lock); |
832 | return err; | 855 | return err; |
@@ -870,32 +893,26 @@ void xprt_transmit(struct rpc_task *task) | |||
870 | req->rq_connect_cookie = xprt->connect_cookie; | 893 | req->rq_connect_cookie = xprt->connect_cookie; |
871 | req->rq_xtime = jiffies; | 894 | req->rq_xtime = jiffies; |
872 | status = xprt->ops->send_request(task); | 895 | status = xprt->ops->send_request(task); |
873 | if (status == 0) { | 896 | if (status != 0) { |
874 | dprintk("RPC: %5u xmit complete\n", task->tk_pid); | 897 | task->tk_status = status; |
875 | spin_lock_bh(&xprt->transport_lock); | 898 | return; |
899 | } | ||
876 | 900 | ||
877 | xprt->ops->set_retrans_timeout(task); | 901 | dprintk("RPC: %5u xmit complete\n", task->tk_pid); |
902 | spin_lock_bh(&xprt->transport_lock); | ||
878 | 903 | ||
879 | xprt->stat.sends++; | 904 | xprt->ops->set_retrans_timeout(task); |
880 | xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs; | ||
881 | xprt->stat.bklog_u += xprt->backlog.qlen; | ||
882 | 905 | ||
883 | /* Don't race with disconnect */ | 906 | xprt->stat.sends++; |
884 | if (!xprt_connected(xprt)) | 907 | xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs; |
885 | task->tk_status = -ENOTCONN; | 908 | xprt->stat.bklog_u += xprt->backlog.qlen; |
886 | else if (!req->rq_received) | ||
887 | rpc_sleep_on(&xprt->pending, task, xprt_timer); | ||
888 | spin_unlock_bh(&xprt->transport_lock); | ||
889 | return; | ||
890 | } | ||
891 | 909 | ||
892 | /* Note: at this point, task->tk_sleeping has not yet been set, | 910 | /* Don't race with disconnect */ |
893 | * hence there is no danger of the waking up task being put on | 911 | if (!xprt_connected(xprt)) |
894 | * schedq, and being picked up by a parallel run of rpciod(). | 912 | task->tk_status = -ENOTCONN; |
895 | */ | 913 | else if (!req->rq_received) |
896 | task->tk_status = status; | 914 | rpc_sleep_on(&xprt->pending, task, xprt_timer); |
897 | if (status == -ECONNREFUSED) | 915 | spin_unlock_bh(&xprt->transport_lock); |
898 | rpc_sleep_on(&xprt->sending, task, NULL); | ||
899 | } | 916 | } |
900 | 917 | ||
901 | static inline void do_xprt_reserve(struct rpc_task *task) | 918 | static inline void do_xprt_reserve(struct rpc_task *task) |