aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sunrpc/xprt.h3
-rw-r--r--net/sunrpc/xprt.c34
-rw-r--r--net/sunrpc/xprtrdma/transport.c1
-rw-r--r--net/sunrpc/xprtsock.c3
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);
281void xprt_reserve(struct rpc_task *task); 282void xprt_reserve(struct rpc_task *task);
282int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task); 283int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
283int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); 284int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
285void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
286void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
284int xprt_prepare_transmit(struct rpc_task *task); 287int xprt_prepare_transmit(struct rpc_task *task);
285void xprt_transmit(struct rpc_task *task); 288void xprt_transmit(struct rpc_task *task);
286void xprt_end_transmit(struct rpc_task *task); 289void 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
972static void xprt_alloc_slot(struct rpc_task *task) 972void 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;
998out_init_req: 999out_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}
1005EXPORT_SYMBOL_GPL(xprt_alloc_slot);
1006
1007void 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}
1019EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot);
1003 1020
1004static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) 1021static 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
1102static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) 1108static 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)
713static struct rpc_xprt_ops xprt_rdma_procs = { 713static 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)
2473static struct rpc_xprt_ops xs_local_ops = { 2473static 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 = {
2506static struct rpc_xprt_ops xs_tcp_ops = { 2508static 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,