diff options
-rw-r--r-- | include/linux/sunrpc/xprt.h | 3 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 34 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/transport.c | 1 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 3 |
4 files changed, 27 insertions, 14 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index cff40aa7db62..bf8c49ff7530 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
@@ -114,6 +114,7 @@ struct rpc_xprt_ops { | |||
114 | void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize); | 114 | void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize); |
115 | int (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); | 115 | int (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); |
116 | void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); | 116 | void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); |
117 | void (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task); | ||
117 | void (*rpcbind)(struct rpc_task *task); | 118 | void (*rpcbind)(struct rpc_task *task); |
118 | void (*set_port)(struct rpc_xprt *xprt, unsigned short port); | 119 | void (*set_port)(struct rpc_xprt *xprt, unsigned short port); |
119 | void (*connect)(struct rpc_task *task); | 120 | void (*connect)(struct rpc_task *task); |
@@ -281,6 +282,8 @@ void xprt_connect(struct rpc_task *task); | |||
281 | void xprt_reserve(struct rpc_task *task); | 282 | void xprt_reserve(struct rpc_task *task); |
282 | int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task); | 283 | int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task); |
283 | int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); | 284 | int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); |
285 | void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); | ||
286 | void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); | ||
284 | int xprt_prepare_transmit(struct rpc_task *task); | 287 | int xprt_prepare_transmit(struct rpc_task *task); |
285 | void xprt_transmit(struct rpc_task *task); | 288 | void xprt_transmit(struct rpc_task *task); |
286 | void xprt_end_transmit(struct rpc_task *task); | 289 | void xprt_end_transmit(struct rpc_task *task); |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index a5a402a7d21f..5d7f61d7559c 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -969,11 +969,11 @@ static bool xprt_dynamic_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) | |||
969 | return false; | 969 | return false; |
970 | } | 970 | } |
971 | 971 | ||
972 | static void xprt_alloc_slot(struct rpc_task *task) | 972 | void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) |
973 | { | 973 | { |
974 | struct rpc_xprt *xprt = task->tk_xprt; | ||
975 | struct rpc_rqst *req; | 974 | struct rpc_rqst *req; |
976 | 975 | ||
976 | spin_lock(&xprt->reserve_lock); | ||
977 | if (!list_empty(&xprt->free)) { | 977 | if (!list_empty(&xprt->free)) { |
978 | req = list_entry(xprt->free.next, struct rpc_rqst, rq_list); | 978 | req = list_entry(xprt->free.next, struct rpc_rqst, rq_list); |
979 | list_del(&req->rq_list); | 979 | list_del(&req->rq_list); |
@@ -994,12 +994,29 @@ static void xprt_alloc_slot(struct rpc_task *task) | |||
994 | default: | 994 | default: |
995 | task->tk_status = -EAGAIN; | 995 | task->tk_status = -EAGAIN; |
996 | } | 996 | } |
997 | spin_unlock(&xprt->reserve_lock); | ||
997 | return; | 998 | return; |
998 | out_init_req: | 999 | out_init_req: |
999 | task->tk_status = 0; | 1000 | task->tk_status = 0; |
1000 | task->tk_rqstp = req; | 1001 | task->tk_rqstp = req; |
1001 | xprt_request_init(task, xprt); | 1002 | xprt_request_init(task, xprt); |
1003 | spin_unlock(&xprt->reserve_lock); | ||
1004 | } | ||
1005 | EXPORT_SYMBOL_GPL(xprt_alloc_slot); | ||
1006 | |||
1007 | void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) | ||
1008 | { | ||
1009 | /* Note: grabbing the xprt_lock_write() ensures that we throttle | ||
1010 | * new slot allocation if the transport is congested (i.e. when | ||
1011 | * reconnecting a stream transport or when out of socket write | ||
1012 | * buffer space). | ||
1013 | */ | ||
1014 | if (xprt_lock_write(xprt, task)) { | ||
1015 | xprt_alloc_slot(xprt, task); | ||
1016 | xprt_release_write(xprt, task); | ||
1017 | } | ||
1002 | } | 1018 | } |
1019 | EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot); | ||
1003 | 1020 | ||
1004 | static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) | 1021 | static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) |
1005 | { | 1022 | { |
@@ -1083,20 +1100,9 @@ void xprt_reserve(struct rpc_task *task) | |||
1083 | if (task->tk_rqstp != NULL) | 1100 | if (task->tk_rqstp != NULL) |
1084 | return; | 1101 | return; |
1085 | 1102 | ||
1086 | /* Note: grabbing the xprt_lock_write() here is not strictly needed, | ||
1087 | * but ensures that we throttle new slot allocation if the transport | ||
1088 | * is congested (e.g. if reconnecting or if we're out of socket | ||
1089 | * write buffer space). | ||
1090 | */ | ||
1091 | task->tk_timeout = 0; | 1103 | task->tk_timeout = 0; |
1092 | task->tk_status = -EAGAIN; | 1104 | task->tk_status = -EAGAIN; |
1093 | if (!xprt_lock_write(xprt, task)) | 1105 | xprt->ops->alloc_slot(xprt, task); |
1094 | return; | ||
1095 | |||
1096 | spin_lock(&xprt->reserve_lock); | ||
1097 | xprt_alloc_slot(task); | ||
1098 | spin_unlock(&xprt->reserve_lock); | ||
1099 | xprt_release_write(xprt, task); | ||
1100 | } | 1106 | } |
1101 | 1107 | ||
1102 | static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) | 1108 | static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) |
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 06cdbff79e4a..5d9202dc7cb1 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -713,6 +713,7 @@ static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
713 | static struct rpc_xprt_ops xprt_rdma_procs = { | 713 | static struct rpc_xprt_ops xprt_rdma_procs = { |
714 | .reserve_xprt = xprt_rdma_reserve_xprt, | 714 | .reserve_xprt = xprt_rdma_reserve_xprt, |
715 | .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ | 715 | .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ |
716 | .alloc_slot = xprt_alloc_slot, | ||
716 | .release_request = xprt_release_rqst_cong, /* ditto */ | 717 | .release_request = xprt_release_rqst_cong, /* ditto */ |
717 | .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */ | 718 | .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */ |
718 | .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ | 719 | .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 400567243f84..a35b8e52e551 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -2473,6 +2473,7 @@ static void bc_destroy(struct rpc_xprt *xprt) | |||
2473 | static struct rpc_xprt_ops xs_local_ops = { | 2473 | static struct rpc_xprt_ops xs_local_ops = { |
2474 | .reserve_xprt = xprt_reserve_xprt, | 2474 | .reserve_xprt = xprt_reserve_xprt, |
2475 | .release_xprt = xs_tcp_release_xprt, | 2475 | .release_xprt = xs_tcp_release_xprt, |
2476 | .alloc_slot = xprt_alloc_slot, | ||
2476 | .rpcbind = xs_local_rpcbind, | 2477 | .rpcbind = xs_local_rpcbind, |
2477 | .set_port = xs_local_set_port, | 2478 | .set_port = xs_local_set_port, |
2478 | .connect = xs_connect, | 2479 | .connect = xs_connect, |
@@ -2489,6 +2490,7 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
2489 | .set_buffer_size = xs_udp_set_buffer_size, | 2490 | .set_buffer_size = xs_udp_set_buffer_size, |
2490 | .reserve_xprt = xprt_reserve_xprt_cong, | 2491 | .reserve_xprt = xprt_reserve_xprt_cong, |
2491 | .release_xprt = xprt_release_xprt_cong, | 2492 | .release_xprt = xprt_release_xprt_cong, |
2493 | .alloc_slot = xprt_alloc_slot, | ||
2492 | .rpcbind = rpcb_getport_async, | 2494 | .rpcbind = rpcb_getport_async, |
2493 | .set_port = xs_set_port, | 2495 | .set_port = xs_set_port, |
2494 | .connect = xs_connect, | 2496 | .connect = xs_connect, |
@@ -2506,6 +2508,7 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
2506 | static struct rpc_xprt_ops xs_tcp_ops = { | 2508 | static struct rpc_xprt_ops xs_tcp_ops = { |
2507 | .reserve_xprt = xprt_reserve_xprt, | 2509 | .reserve_xprt = xprt_reserve_xprt, |
2508 | .release_xprt = xs_tcp_release_xprt, | 2510 | .release_xprt = xs_tcp_release_xprt, |
2511 | .alloc_slot = xprt_lock_and_alloc_slot, | ||
2509 | .rpcbind = rpcb_getport_async, | 2512 | .rpcbind = rpcb_getport_async, |
2510 | .set_port = xs_set_port, | 2513 | .set_port = xs_set_port, |
2511 | .connect = xs_connect, | 2514 | .connect = xs_connect, |