diff options
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 80 |
1 files changed, 51 insertions, 29 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index c64c0ef519b5..0cbcd1ab49ab 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -66,6 +66,7 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net); | |||
66 | static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); | 66 | static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); |
67 | static void xprt_connect_status(struct rpc_task *task); | 67 | static void xprt_connect_status(struct rpc_task *task); |
68 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | 68 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); |
69 | static void xprt_destroy(struct rpc_xprt *xprt); | ||
69 | 70 | ||
70 | static DEFINE_SPINLOCK(xprt_list_lock); | 71 | static DEFINE_SPINLOCK(xprt_list_lock); |
71 | static LIST_HEAD(xprt_list); | 72 | static LIST_HEAD(xprt_list); |
@@ -292,54 +293,57 @@ static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) | |||
292 | return retval; | 293 | return retval; |
293 | } | 294 | } |
294 | 295 | ||
295 | static void __xprt_lock_write_next(struct rpc_xprt *xprt) | 296 | static bool __xprt_lock_write_func(struct rpc_task *task, void *data) |
296 | { | 297 | { |
297 | struct rpc_task *task; | 298 | struct rpc_xprt *xprt = data; |
298 | struct rpc_rqst *req; | 299 | struct rpc_rqst *req; |
299 | 300 | ||
300 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
301 | return; | ||
302 | |||
303 | task = rpc_wake_up_next(&xprt->sending); | ||
304 | if (task == NULL) | ||
305 | goto out_unlock; | ||
306 | |||
307 | req = task->tk_rqstp; | 301 | req = task->tk_rqstp; |
308 | xprt->snd_task = task; | 302 | xprt->snd_task = task; |
309 | if (req) { | 303 | if (req) { |
310 | req->rq_bytes_sent = 0; | 304 | req->rq_bytes_sent = 0; |
311 | req->rq_ntrans++; | 305 | req->rq_ntrans++; |
312 | } | 306 | } |
313 | return; | 307 | return true; |
308 | } | ||
314 | 309 | ||
315 | out_unlock: | 310 | static void __xprt_lock_write_next(struct rpc_xprt *xprt) |
311 | { | ||
312 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
313 | return; | ||
314 | |||
315 | if (rpc_wake_up_first(&xprt->sending, __xprt_lock_write_func, xprt)) | ||
316 | return; | ||
316 | xprt_clear_locked(xprt); | 317 | xprt_clear_locked(xprt); |
317 | } | 318 | } |
318 | 319 | ||
319 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) | 320 | static bool __xprt_lock_write_cong_func(struct rpc_task *task, void *data) |
320 | { | 321 | { |
321 | struct rpc_task *task; | 322 | struct rpc_xprt *xprt = data; |
322 | struct rpc_rqst *req; | 323 | struct rpc_rqst *req; |
323 | 324 | ||
324 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
325 | return; | ||
326 | if (RPCXPRT_CONGESTED(xprt)) | ||
327 | goto out_unlock; | ||
328 | task = rpc_wake_up_next(&xprt->sending); | ||
329 | if (task == NULL) | ||
330 | goto out_unlock; | ||
331 | |||
332 | req = task->tk_rqstp; | 325 | req = task->tk_rqstp; |
333 | if (req == NULL) { | 326 | if (req == NULL) { |
334 | xprt->snd_task = task; | 327 | xprt->snd_task = task; |
335 | return; | 328 | return true; |
336 | } | 329 | } |
337 | if (__xprt_get_cong(xprt, task)) { | 330 | if (__xprt_get_cong(xprt, task)) { |
338 | xprt->snd_task = task; | 331 | xprt->snd_task = task; |
339 | req->rq_bytes_sent = 0; | 332 | req->rq_bytes_sent = 0; |
340 | req->rq_ntrans++; | 333 | req->rq_ntrans++; |
341 | return; | 334 | return true; |
342 | } | 335 | } |
336 | return false; | ||
337 | } | ||
338 | |||
339 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) | ||
340 | { | ||
341 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
342 | return; | ||
343 | if (RPCXPRT_CONGESTED(xprt)) | ||
344 | goto out_unlock; | ||
345 | if (rpc_wake_up_first(&xprt->sending, __xprt_lock_write_cong_func, xprt)) | ||
346 | return; | ||
343 | out_unlock: | 347 | out_unlock: |
344 | xprt_clear_locked(xprt); | 348 | xprt_clear_locked(xprt); |
345 | } | 349 | } |
@@ -712,9 +716,7 @@ void xprt_connect(struct rpc_task *task) | |||
712 | if (xprt_connected(xprt)) | 716 | if (xprt_connected(xprt)) |
713 | xprt_release_write(xprt, task); | 717 | xprt_release_write(xprt, task); |
714 | else { | 718 | else { |
715 | if (task->tk_rqstp) | 719 | task->tk_rqstp->rq_bytes_sent = 0; |
716 | task->tk_rqstp->rq_bytes_sent = 0; | ||
717 | |||
718 | task->tk_timeout = task->tk_rqstp->rq_timeout; | 720 | task->tk_timeout = task->tk_rqstp->rq_timeout; |
719 | rpc_sleep_on(&xprt->pending, task, xprt_connect_status); | 721 | rpc_sleep_on(&xprt->pending, task, xprt_connect_status); |
720 | 722 | ||
@@ -750,7 +752,7 @@ static void xprt_connect_status(struct rpc_task *task) | |||
750 | default: | 752 | default: |
751 | dprintk("RPC: %5u xprt_connect_status: error %d connecting to " | 753 | dprintk("RPC: %5u xprt_connect_status: error %d connecting to " |
752 | "server %s\n", task->tk_pid, -task->tk_status, | 754 | "server %s\n", task->tk_pid, -task->tk_status, |
753 | task->tk_client->cl_server); | 755 | xprt->servername); |
754 | xprt_release_write(xprt, task); | 756 | xprt_release_write(xprt, task); |
755 | task->tk_status = -EIO; | 757 | task->tk_status = -EIO; |
756 | } | 758 | } |
@@ -884,7 +886,7 @@ void xprt_transmit(struct rpc_task *task) | |||
884 | { | 886 | { |
885 | struct rpc_rqst *req = task->tk_rqstp; | 887 | struct rpc_rqst *req = task->tk_rqstp; |
886 | struct rpc_xprt *xprt = req->rq_xprt; | 888 | struct rpc_xprt *xprt = req->rq_xprt; |
887 | int status; | 889 | int status, numreqs; |
888 | 890 | ||
889 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); | 891 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); |
890 | 892 | ||
@@ -921,9 +923,14 @@ void xprt_transmit(struct rpc_task *task) | |||
921 | 923 | ||
922 | xprt->ops->set_retrans_timeout(task); | 924 | xprt->ops->set_retrans_timeout(task); |
923 | 925 | ||
926 | numreqs = atomic_read(&xprt->num_reqs); | ||
927 | if (numreqs > xprt->stat.max_slots) | ||
928 | xprt->stat.max_slots = numreqs; | ||
924 | xprt->stat.sends++; | 929 | xprt->stat.sends++; |
925 | xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs; | 930 | xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs; |
926 | xprt->stat.bklog_u += xprt->backlog.qlen; | 931 | xprt->stat.bklog_u += xprt->backlog.qlen; |
932 | xprt->stat.sending_u += xprt->sending.qlen; | ||
933 | xprt->stat.pending_u += xprt->pending.qlen; | ||
927 | 934 | ||
928 | /* Don't race with disconnect */ | 935 | /* Don't race with disconnect */ |
929 | if (!xprt_connected(xprt)) | 936 | if (!xprt_connected(xprt)) |
@@ -1131,7 +1138,10 @@ void xprt_release(struct rpc_task *task) | |||
1131 | return; | 1138 | return; |
1132 | 1139 | ||
1133 | xprt = req->rq_xprt; | 1140 | xprt = req->rq_xprt; |
1134 | rpc_count_iostats(task); | 1141 | if (task->tk_ops->rpc_count_stats != NULL) |
1142 | task->tk_ops->rpc_count_stats(task, task->tk_calldata); | ||
1143 | else if (task->tk_client) | ||
1144 | rpc_count_iostats(task, task->tk_client->cl_metrics); | ||
1135 | spin_lock_bh(&xprt->transport_lock); | 1145 | spin_lock_bh(&xprt->transport_lock); |
1136 | xprt->ops->release_xprt(xprt, task); | 1146 | xprt->ops->release_xprt(xprt, task); |
1137 | if (xprt->ops->release_request) | 1147 | if (xprt->ops->release_request) |
@@ -1220,6 +1230,17 @@ found: | |||
1220 | (unsigned long)xprt); | 1230 | (unsigned long)xprt); |
1221 | else | 1231 | else |
1222 | init_timer(&xprt->timer); | 1232 | init_timer(&xprt->timer); |
1233 | |||
1234 | if (strlen(args->servername) > RPC_MAXNETNAMELEN) { | ||
1235 | xprt_destroy(xprt); | ||
1236 | return ERR_PTR(-EINVAL); | ||
1237 | } | ||
1238 | xprt->servername = kstrdup(args->servername, GFP_KERNEL); | ||
1239 | if (xprt->servername == NULL) { | ||
1240 | xprt_destroy(xprt); | ||
1241 | return ERR_PTR(-ENOMEM); | ||
1242 | } | ||
1243 | |||
1223 | dprintk("RPC: created transport %p with %u slots\n", xprt, | 1244 | dprintk("RPC: created transport %p with %u slots\n", xprt, |
1224 | xprt->max_reqs); | 1245 | xprt->max_reqs); |
1225 | out: | 1246 | out: |
@@ -1242,6 +1263,7 @@ static void xprt_destroy(struct rpc_xprt *xprt) | |||
1242 | rpc_destroy_wait_queue(&xprt->sending); | 1263 | rpc_destroy_wait_queue(&xprt->sending); |
1243 | rpc_destroy_wait_queue(&xprt->backlog); | 1264 | rpc_destroy_wait_queue(&xprt->backlog); |
1244 | cancel_work_sync(&xprt->task_cleanup); | 1265 | cancel_work_sync(&xprt->task_cleanup); |
1266 | kfree(xprt->servername); | ||
1245 | /* | 1267 | /* |
1246 | * Tear down transport state and free the rpc_xprt | 1268 | * Tear down transport state and free the rpc_xprt |
1247 | */ | 1269 | */ |