diff options
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 66 |
1 files changed, 25 insertions, 41 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 6dda3860351f..8ff2c8acb223 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -119,6 +119,17 @@ out_sleep: | |||
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | static void xprt_clear_locked(struct rpc_xprt *xprt) | ||
123 | { | ||
124 | xprt->snd_task = NULL; | ||
125 | if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state) || xprt->shutdown) { | ||
126 | smp_mb__before_clear_bit(); | ||
127 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
128 | smp_mb__after_clear_bit(); | ||
129 | } else | ||
130 | schedule_work(&xprt->task_cleanup); | ||
131 | } | ||
132 | |||
122 | /* | 133 | /* |
123 | * xprt_reserve_xprt_cong - serialize write access to transports | 134 | * xprt_reserve_xprt_cong - serialize write access to transports |
124 | * @task: task that is requesting access to the transport | 135 | * @task: task that is requesting access to the transport |
@@ -145,9 +156,7 @@ int xprt_reserve_xprt_cong(struct rpc_task *task) | |||
145 | } | 156 | } |
146 | return 1; | 157 | return 1; |
147 | } | 158 | } |
148 | smp_mb__before_clear_bit(); | 159 | xprt_clear_locked(xprt); |
149 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
150 | smp_mb__after_clear_bit(); | ||
151 | out_sleep: | 160 | out_sleep: |
152 | dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt); | 161 | dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt); |
153 | task->tk_timeout = 0; | 162 | task->tk_timeout = 0; |
@@ -193,9 +202,7 @@ static void __xprt_lock_write_next(struct rpc_xprt *xprt) | |||
193 | return; | 202 | return; |
194 | 203 | ||
195 | out_unlock: | 204 | out_unlock: |
196 | smp_mb__before_clear_bit(); | 205 | xprt_clear_locked(xprt); |
197 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
198 | smp_mb__after_clear_bit(); | ||
199 | } | 206 | } |
200 | 207 | ||
201 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) | 208 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) |
@@ -222,9 +229,7 @@ static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) | |||
222 | return; | 229 | return; |
223 | } | 230 | } |
224 | out_unlock: | 231 | out_unlock: |
225 | smp_mb__before_clear_bit(); | 232 | xprt_clear_locked(xprt); |
226 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
227 | smp_mb__after_clear_bit(); | ||
228 | } | 233 | } |
229 | 234 | ||
230 | /** | 235 | /** |
@@ -237,10 +242,7 @@ out_unlock: | |||
237 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | 242 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) |
238 | { | 243 | { |
239 | if (xprt->snd_task == task) { | 244 | if (xprt->snd_task == task) { |
240 | xprt->snd_task = NULL; | 245 | xprt_clear_locked(xprt); |
241 | smp_mb__before_clear_bit(); | ||
242 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
243 | smp_mb__after_clear_bit(); | ||
244 | __xprt_lock_write_next(xprt); | 246 | __xprt_lock_write_next(xprt); |
245 | } | 247 | } |
246 | } | 248 | } |
@@ -256,10 +258,7 @@ void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | |||
256 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) | 258 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) |
257 | { | 259 | { |
258 | if (xprt->snd_task == task) { | 260 | if (xprt->snd_task == task) { |
259 | xprt->snd_task = NULL; | 261 | xprt_clear_locked(xprt); |
260 | smp_mb__before_clear_bit(); | ||
261 | clear_bit(XPRT_LOCKED, &xprt->state); | ||
262 | smp_mb__after_clear_bit(); | ||
263 | __xprt_lock_write_next_cong(xprt); | 262 | __xprt_lock_write_next_cong(xprt); |
264 | } | 263 | } |
265 | } | 264 | } |
@@ -535,10 +534,6 @@ void xprt_connect(struct rpc_task *task) | |||
535 | dprintk("RPC: %4d xprt_connect xprt %p %s connected\n", task->tk_pid, | 534 | dprintk("RPC: %4d xprt_connect xprt %p %s connected\n", task->tk_pid, |
536 | xprt, (xprt_connected(xprt) ? "is" : "is not")); | 535 | xprt, (xprt_connected(xprt) ? "is" : "is not")); |
537 | 536 | ||
538 | if (xprt->shutdown) { | ||
539 | task->tk_status = -EIO; | ||
540 | return; | ||
541 | } | ||
542 | if (!xprt->addr.sin_port) { | 537 | if (!xprt->addr.sin_port) { |
543 | task->tk_status = -EIO; | 538 | task->tk_status = -EIO; |
544 | return; | 539 | return; |
@@ -687,9 +682,6 @@ int xprt_prepare_transmit(struct rpc_task *task) | |||
687 | 682 | ||
688 | dprintk("RPC: %4d xprt_prepare_transmit\n", task->tk_pid); | 683 | dprintk("RPC: %4d xprt_prepare_transmit\n", task->tk_pid); |
689 | 684 | ||
690 | if (xprt->shutdown) | ||
691 | return -EIO; | ||
692 | |||
693 | spin_lock_bh(&xprt->transport_lock); | 685 | spin_lock_bh(&xprt->transport_lock); |
694 | if (req->rq_received && !req->rq_bytes_sent) { | 686 | if (req->rq_received && !req->rq_bytes_sent) { |
695 | err = req->rq_received; | 687 | err = req->rq_received; |
@@ -814,11 +806,9 @@ void xprt_reserve(struct rpc_task *task) | |||
814 | struct rpc_xprt *xprt = task->tk_xprt; | 806 | struct rpc_xprt *xprt = task->tk_xprt; |
815 | 807 | ||
816 | task->tk_status = -EIO; | 808 | task->tk_status = -EIO; |
817 | if (!xprt->shutdown) { | 809 | spin_lock(&xprt->reserve_lock); |
818 | spin_lock(&xprt->reserve_lock); | 810 | do_xprt_reserve(task); |
819 | do_xprt_reserve(task); | 811 | spin_unlock(&xprt->reserve_lock); |
820 | spin_unlock(&xprt->reserve_lock); | ||
821 | } | ||
822 | } | 812 | } |
823 | 813 | ||
824 | static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt) | 814 | static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt) |
@@ -838,6 +828,8 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) | |||
838 | req->rq_timeout = xprt->timeout.to_initval; | 828 | req->rq_timeout = xprt->timeout.to_initval; |
839 | req->rq_task = task; | 829 | req->rq_task = task; |
840 | req->rq_xprt = xprt; | 830 | req->rq_xprt = xprt; |
831 | req->rq_buffer = NULL; | ||
832 | req->rq_bufsize = 0; | ||
841 | req->rq_xid = xprt_alloc_xid(xprt); | 833 | req->rq_xid = xprt_alloc_xid(xprt); |
842 | req->rq_release_snd_buf = NULL; | 834 | req->rq_release_snd_buf = NULL; |
843 | dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid, | 835 | dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid, |
@@ -863,10 +855,11 @@ void xprt_release(struct rpc_task *task) | |||
863 | if (!list_empty(&req->rq_list)) | 855 | if (!list_empty(&req->rq_list)) |
864 | list_del(&req->rq_list); | 856 | list_del(&req->rq_list); |
865 | xprt->last_used = jiffies; | 857 | xprt->last_used = jiffies; |
866 | if (list_empty(&xprt->recv) && !xprt->shutdown) | 858 | if (list_empty(&xprt->recv)) |
867 | mod_timer(&xprt->timer, | 859 | mod_timer(&xprt->timer, |
868 | xprt->last_used + xprt->idle_timeout); | 860 | xprt->last_used + xprt->idle_timeout); |
869 | spin_unlock_bh(&xprt->transport_lock); | 861 | spin_unlock_bh(&xprt->transport_lock); |
862 | xprt->ops->buf_free(task); | ||
870 | task->tk_rqstp = NULL; | 863 | task->tk_rqstp = NULL; |
871 | if (req->rq_release_snd_buf) | 864 | if (req->rq_release_snd_buf) |
872 | req->rq_release_snd_buf(req); | 865 | req->rq_release_snd_buf(req); |
@@ -974,16 +967,6 @@ struct rpc_xprt *xprt_create_proto(int proto, struct sockaddr_in *sap, struct rp | |||
974 | return xprt; | 967 | return xprt; |
975 | } | 968 | } |
976 | 969 | ||
977 | static void xprt_shutdown(struct rpc_xprt *xprt) | ||
978 | { | ||
979 | xprt->shutdown = 1; | ||
980 | rpc_wake_up(&xprt->sending); | ||
981 | rpc_wake_up(&xprt->resend); | ||
982 | xprt_wake_pending_tasks(xprt, -EIO); | ||
983 | rpc_wake_up(&xprt->backlog); | ||
984 | del_timer_sync(&xprt->timer); | ||
985 | } | ||
986 | |||
987 | /** | 970 | /** |
988 | * xprt_destroy - destroy an RPC transport, killing off all requests. | 971 | * xprt_destroy - destroy an RPC transport, killing off all requests. |
989 | * @xprt: transport to destroy | 972 | * @xprt: transport to destroy |
@@ -992,7 +975,8 @@ static void xprt_shutdown(struct rpc_xprt *xprt) | |||
992 | int xprt_destroy(struct rpc_xprt *xprt) | 975 | int xprt_destroy(struct rpc_xprt *xprt) |
993 | { | 976 | { |
994 | dprintk("RPC: destroying transport %p\n", xprt); | 977 | dprintk("RPC: destroying transport %p\n", xprt); |
995 | xprt_shutdown(xprt); | 978 | xprt->shutdown = 1; |
979 | del_timer_sync(&xprt->timer); | ||
996 | xprt->ops->destroy(xprt); | 980 | xprt->ops->destroy(xprt); |
997 | kfree(xprt); | 981 | kfree(xprt); |
998 | 982 | ||