From: Valentine Fatiev <valentinef@nvidia.com>
Subject: [PATCH] BACKPORT: net/sunrpc/xprtrdma/backchannel.c

Change-Id: I40d3c93c9302ce89b1ec2a1f830fe78b7131a5f5
---
 net/sunrpc/xprtrdma/backchannel.c | 141 ++++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)

--- a/net/sunrpc/xprtrdma/backchannel.c
+++ b/net/sunrpc/xprtrdma/backchannel.c
@@ -11,10 +11,19 @@
 #include <linux/sunrpc/svc_rdma.h>
 
 #include "xprt_rdma.h"
+#ifdef HAVE_TRACE_RPCRDMA_H
 #include <trace/events/rpcrdma.h>
+#endif
 
 #undef RPCRDMA_BACKCHANNEL_DEBUG
 
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
+#ifndef RPCDBG_FACILITY
+#define RPCDBG_FACILITY    RPCDBG_TRANS
+#endif
+#endif
+
+#ifdef HAVE_RPC_XPRT_OPS_FREE_SLOT
 /**
  * xprt_rdma_bc_setup - Pre-allocate resources for handling backchannel requests
  * @xprt: transport associated with these backchannel resources
@@ -27,9 +36,92 @@ int xprt_rdma_bc_setup(struct rpc_xprt *
 	struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
 
 	r_xprt->rx_buf.rb_bc_srv_max_requests = RPCRDMA_BACKWARD_WRS >> 1;
+#ifdef HAVE_TRACE_RPCRDMA_H
 	trace_xprtrdma_cb_setup(r_xprt, reqs);
+#endif
+	return 0;
+}
+#else
+static void rpcrdma_bc_free_rqst(struct rpcrdma_xprt *r_xprt,
+				 struct rpc_rqst *rqst)
+{
+	struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
+	struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
+
+	spin_lock(&buf->rb_lock);
+	rpcrdma_req_destroy(req);
+	spin_unlock(&buf->rb_lock);
+
+	kfree(rqst);
+}
+
+static int rpcrdma_bc_setup_rqst(struct rpcrdma_xprt *r_xprt,
+					struct rpc_rqst *rqst);
+
+int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs)
+{
+	struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
+	struct rpcrdma_buffer *buffer = &r_xprt->rx_buf;
+	struct rpc_rqst *rqst;
+	unsigned int i;
+
+	if (reqs > RPCRDMA_BACKWARD_WRS >> 1)
+		goto out_err;
+
+	for (i = 0; i < (reqs << 1); i++) {
+		rqst = kzalloc(sizeof(*rqst), GFP_KERNEL);
+		if (!rqst)
+			goto out_free;
+
+		dprintk("RPC:       %s: new rqst %p\n", __func__, rqst);
+
+		rqst->rq_xprt = &r_xprt->rx_xprt;
+		INIT_LIST_HEAD(&rqst->rq_list);
+		INIT_LIST_HEAD(&rqst->rq_bc_list);
+		__set_bit(RPC_BC_PA_IN_USE, &rqst->rq_bc_pa_state);
+
+		if (rpcrdma_bc_setup_rqst(r_xprt, rqst))
+			goto out_free;
+
+		spin_lock_bh(&xprt->bc_pa_lock);
+		list_add(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);
+		spin_unlock_bh(&xprt->bc_pa_lock);
+	}
+
+	buffer->rb_bc_srv_max_requests = reqs;
+	request_module("svcrdma");
 	return 0;
+
+out_free:
+	xprt_rdma_bc_destroy(xprt, reqs);
+
+out_err:
+	pr_err("RPC:       %s: setup backchannel transport failed\n", __func__);
+	return -ENOMEM;
 }
+#endif
+
+#if defined(CONFIG_SUNRPC_BACKCHANNEL) && defined(HAVE_RPC_XPRT_OPS_BC_UP)
+/**
+ * xprt_rdma_bc_up - Create transport endpoint for backchannel service
+ * @serv: server endpoint
+ * @net: network namespace
+ *
+ * The "xprt" is an implied argument: it supplies the name of the
+ * backchannel transport class.
+ *
+ * Returns zero on success, negative errno on failure
+ */
+int xprt_rdma_bc_up(struct svc_serv *serv, struct net *net)
+{
+    int ret;
+
+    ret = svc_create_xprt(serv, "rdma-bc", net, PF_INET, 0, 0);
+    if (ret < 0)
+        return ret;
+    return 0;
+}
+#endif
 
 /**
  * xprt_rdma_bc_maxpayload - Return maximum backchannel message size
@@ -48,10 +140,12 @@ size_t xprt_rdma_bc_maxpayload(struct rp
 	return maxmsg - RPCRDMA_HDRLEN_MIN;
 }
 
+#ifdef HAVE_RPC_XPRT_OPS_BC_NUM_SLOTS
 unsigned int xprt_rdma_bc_max_slots(struct rpc_xprt *xprt)
 {
 	return RPCRDMA_BACKWARD_WRS >> 1;
 }
+#endif
 
 static int rpcrdma_bc_marshal_reply(struct rpc_rqst *rqst)
 {
@@ -60,8 +154,13 @@ static int rpcrdma_bc_marshal_reply(stru
 	__be32 *p;
 
 	rpcrdma_set_xdrlen(&req->rl_hdrbuf, 0);
+#ifdef HAVE_XDR_INIT_ENCODE_RQST_ARG
 	xdr_init_encode(&req->rl_stream, &req->rl_hdrbuf,
 			rdmab_data(req->rl_rdmabuf), rqst);
+#else
+	xdr_init_encode(&req->rl_stream, &req->rl_hdrbuf,
+			rdmab_data(req->rl_rdmabuf));
+#endif
 
 	p = xdr_reserve_space(&req->rl_stream, 28);
 	if (unlikely(!p))
@@ -78,7 +177,9 @@ static int rpcrdma_bc_marshal_reply(stru
 				      &rqst->rq_snd_buf, rpcrdma_noch_pullup))
 		return -EIO;
 
+#ifdef HAVE_TRACE_RPCRDMA_H
 	trace_xprtrdma_cb_reply(r_xprt, rqst);
+#endif
 	return 0;
 }
 
@@ -104,8 +205,10 @@ int xprt_rdma_bc_send_reply(struct rpc_r
 	if (!xprt_connected(xprt))
 		return -ENOTCONN;
 
+#ifdef HAVE_XPRT_REQUEST_GET_CONG
 	if (!xprt_request_get_cong(xprt, rqst))
 		return -EBADSLT;
+#endif
 
 	rc = rpcrdma_bc_marshal_reply(rqst);
 	if (rc < 0)
@@ -137,7 +240,11 @@ void xprt_rdma_bc_destroy(struct rpc_xpr
 		list_del(&rqst->rq_bc_pa_list);
 		spin_unlock(&xprt->bc_pa_lock);
 
+#ifdef HAVE_RPC_XPRT_OPS_FREE_SLOT
 		rpcrdma_req_destroy(rpcr_to_rdmar(rqst));
+#else
+		rpcrdma_bc_free_rqst(rpcx_to_rdmax(xprt), rqst);
+#endif
 
 		spin_lock(&xprt->bc_pa_lock);
 	}
@@ -164,6 +271,7 @@ void xprt_rdma_bc_free_rqst(struct rpc_r
 	xprt_put(xprt);
 }
 
+#ifdef HAVE_RPC_XPRT_OPS_FREE_SLOT
 static struct rpc_rqst *rpcrdma_bc_rqst_get(struct rpcrdma_xprt *r_xprt)
 {
 	struct rpc_xprt *xprt = &r_xprt->rx_xprt;
@@ -204,6 +312,24 @@ create_req:
 	xdr_buf_init(&rqst->rq_snd_buf, rdmab_data(req->rl_sendbuf), size);
 	return rqst;
 }
+#else
+static int rpcrdma_bc_setup_rqst(struct rpcrdma_xprt *r_xprt,
+               struct rpc_rqst *rqst)
+{
+	struct rpcrdma_req *req;
+	size_t size;
+
+	size = min_t(size_t, r_xprt->rx_ep->re_inline_recv, PAGE_SIZE);
+	req = rpcrdma_req_create(r_xprt, size, GFP_KERNEL);
+	if (!req)
+		return PTR_ERR(req);
+
+	xdr_buf_init(&rqst->rq_snd_buf, rdmab_data(req->rl_sendbuf),
+		     size);
+	rpcrdma_set_xprtdata(rqst, req);
+	return 0;
+}
+#endif
 
 /**
  * rpcrdma_bc_receive_call - Handle a reverse-direction Call
@@ -236,9 +362,22 @@ void rpcrdma_bc_receive_call(struct rpcr
 	pr_info("RPC:       %s: %*ph\n", __func__, size, p);
 #endif
 
+#ifdef HAVE_RPC_XPRT_OPS_FREE_SLOT
 	rqst = rpcrdma_bc_rqst_get(r_xprt);
 	if (!rqst)
 		goto out_overflow;
+#else
+	/* Grab a free bc rqst */
+	spin_lock(&xprt->bc_pa_lock);
+	if (list_empty(&xprt->bc_pa_list)) {
+		spin_unlock(&xprt->bc_pa_lock);
+		goto out_overflow;
+	}
+	rqst = list_first_entry(&xprt->bc_pa_list,
+				struct rpc_rqst, rq_bc_pa_list);
+	list_del(&rqst->rq_bc_pa_list);
+	spin_unlock(&xprt->bc_pa_lock);
+#endif
 
 	rqst->rq_reply_bytes_recvd = 0;
 	rqst->rq_xid = *p;
@@ -258,7 +397,9 @@ void rpcrdma_bc_receive_call(struct rpcr
 	 */
 	req = rpcr_to_rdmar(rqst);
 	req->rl_reply = rep;
+#ifdef HAVE_TRACE_RPCRDMA_H
 	trace_xprtrdma_cb_call(r_xprt, rqst);
+#endif
 
 	/* Queue rqst for ULP's callback service */
 	bc_serv = xprt->bc_serv;
