aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2015-01-21 11:04:25 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2015-01-30 10:47:49 -0500
commit6b1184cd4fb086a826f658b02d9d9912dd0dde08 (patch)
treedf2ac783c1d016997a3230544039740090c65bea /net
parent85275c874eaeb92fb2a78a1d4ebb1ff4b0f7b732 (diff)
xprtrdma: Allocate RPC/RDMA receive buffer separately from struct rpcrdma_rep
The rr_base field is currently the buffer where RPC replies land. An RPC/RDMA reply header lands in this buffer. In some cases an RPC reply header also lands in this buffer, just after the RPC/RDMA header. The inline threshold is an agreed-on size limit for RDMA SEND operations that pass from server and client. The sum of the RPC/RDMA reply header size and the RPC reply header size must be less than this threshold. The largest RDMA RECV that the client should have to handle is the size of the inline threshold. The receive buffer should thus be the size of the inline threshold, and not related to RPCRDMA_MAX_SEGS. RPC replies received via RDMA WRITE (long replies) are caught in rq_rcv_buf, which is the second half of the RPC send buffer. Ie, such replies are not involved in any way with rr_base. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/xprtrdma/rpc_rdma.c5
-rw-r--r--net/sunrpc/xprtrdma/verbs.c27
-rw-r--r--net/sunrpc/xprtrdma/xprt_rdma.h14
3 files changed, 23 insertions, 23 deletions
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index c1d4a093b8f1..02efcaa1bbac 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -572,6 +572,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, unsigned int max, int wrchunk, __b
572{ 572{
573 unsigned int i, total_len; 573 unsigned int i, total_len;
574 struct rpcrdma_write_chunk *cur_wchunk; 574 struct rpcrdma_write_chunk *cur_wchunk;
575 char *base = (char *)rdmab_to_msg(rep->rr_rdmabuf);
575 576
576 i = be32_to_cpu(**iptrp); 577 i = be32_to_cpu(**iptrp);
577 if (i > max) 578 if (i > max)
@@ -599,7 +600,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, unsigned int max, int wrchunk, __b
599 return -1; 600 return -1;
600 cur_wchunk = (struct rpcrdma_write_chunk *) w; 601 cur_wchunk = (struct rpcrdma_write_chunk *) w;
601 } 602 }
602 if ((char *) cur_wchunk > rep->rr_base + rep->rr_len) 603 if ((char *)cur_wchunk > base + rep->rr_len)
603 return -1; 604 return -1;
604 605
605 *iptrp = (__be32 *) cur_wchunk; 606 *iptrp = (__be32 *) cur_wchunk;
@@ -753,7 +754,7 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
753 dprintk("RPC: %s: short/invalid reply\n", __func__); 754 dprintk("RPC: %s: short/invalid reply\n", __func__);
754 goto repost; 755 goto repost;
755 } 756 }
756 headerp = (struct rpcrdma_msg *) rep->rr_base; 757 headerp = rdmab_to_msg(rep->rr_rdmabuf);
757 if (headerp->rm_vers != rpcrdma_version) { 758 if (headerp->rm_vers != rpcrdma_version) {
758 dprintk("RPC: %s: invalid version %d\n", 759 dprintk("RPC: %s: invalid version %d\n",
759 __func__, be32_to_cpu(headerp->rm_vers)); 760 __func__, be32_to_cpu(headerp->rm_vers));
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index c81749b9a0de..f58521dd88e2 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -298,8 +298,9 @@ rpcrdma_recvcq_process_wc(struct ib_wc *wc, struct list_head *sched_list)
298 298
299 rep->rr_len = wc->byte_len; 299 rep->rr_len = wc->byte_len;
300 ib_dma_sync_single_for_cpu(rdmab_to_ia(rep->rr_buffer)->ri_id->device, 300 ib_dma_sync_single_for_cpu(rdmab_to_ia(rep->rr_buffer)->ri_id->device,
301 rep->rr_iov.addr, rep->rr_len, DMA_FROM_DEVICE); 301 rdmab_addr(rep->rr_rdmabuf),
302 prefetch(rep->rr_base); 302 rep->rr_len, DMA_FROM_DEVICE);
303 prefetch(rdmab_to_msg(rep->rr_rdmabuf));
303 304
304out_schedule: 305out_schedule:
305 list_add_tail(&rep->rr_list, sched_list); 306 list_add_tail(&rep->rr_list, sched_list);
@@ -1092,23 +1093,21 @@ static struct rpcrdma_rep *
1092rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt) 1093rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt)
1093{ 1094{
1094 struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data; 1095 struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data;
1095 size_t rlen = 1 << fls(cdata->inline_rsize +
1096 sizeof(struct rpcrdma_rep));
1097 struct rpcrdma_ia *ia = &r_xprt->rx_ia; 1096 struct rpcrdma_ia *ia = &r_xprt->rx_ia;
1098 struct rpcrdma_rep *rep; 1097 struct rpcrdma_rep *rep;
1099 int rc; 1098 int rc;
1100 1099
1101 rc = -ENOMEM; 1100 rc = -ENOMEM;
1102 rep = kmalloc(rlen, GFP_KERNEL); 1101 rep = kzalloc(sizeof(*rep), GFP_KERNEL);
1103 if (rep == NULL) 1102 if (rep == NULL)
1104 goto out; 1103 goto out;
1105 memset(rep, 0, sizeof(*rep));
1106 1104
1107 rc = rpcrdma_register_internal(ia, rep->rr_base, rlen - 1105 rep->rr_rdmabuf = rpcrdma_alloc_regbuf(ia, cdata->inline_rsize,
1108 offsetof(struct rpcrdma_rep, rr_base), 1106 GFP_KERNEL);
1109 &rep->rr_handle, &rep->rr_iov); 1107 if (IS_ERR(rep->rr_rdmabuf)) {
1110 if (rc) 1108 rc = PTR_ERR(rep->rr_rdmabuf);
1111 goto out_free; 1109 goto out_free;
1110 }
1112 1111
1113 rep->rr_buffer = &r_xprt->rx_buf; 1112 rep->rr_buffer = &r_xprt->rx_buf;
1114 return rep; 1113 return rep;
@@ -1306,7 +1305,7 @@ rpcrdma_destroy_rep(struct rpcrdma_ia *ia, struct rpcrdma_rep *rep)
1306 if (!rep) 1305 if (!rep)
1307 return; 1306 return;
1308 1307
1309 rpcrdma_deregister_internal(ia, rep->rr_handle, &rep->rr_iov); 1308 rpcrdma_free_regbuf(ia, rep->rr_rdmabuf);
1310 kfree(rep); 1309 kfree(rep);
1311} 1310}
1312 1311
@@ -2209,11 +2208,13 @@ rpcrdma_ep_post_recv(struct rpcrdma_ia *ia,
2209 2208
2210 recv_wr.next = NULL; 2209 recv_wr.next = NULL;
2211 recv_wr.wr_id = (u64) (unsigned long) rep; 2210 recv_wr.wr_id = (u64) (unsigned long) rep;
2212 recv_wr.sg_list = &rep->rr_iov; 2211 recv_wr.sg_list = &rep->rr_rdmabuf->rg_iov;
2213 recv_wr.num_sge = 1; 2212 recv_wr.num_sge = 1;
2214 2213
2215 ib_dma_sync_single_for_cpu(ia->ri_id->device, 2214 ib_dma_sync_single_for_cpu(ia->ri_id->device,
2216 rep->rr_iov.addr, rep->rr_iov.length, DMA_BIDIRECTIONAL); 2215 rdmab_addr(rep->rr_rdmabuf),
2216 rdmab_length(rep->rr_rdmabuf),
2217 DMA_BIDIRECTIONAL);
2217 2218
2218 rc = ib_post_recv(ia->ri_id->qp, &recv_wr, &recv_wr_fail); 2219 rc = ib_post_recv(ia->ri_id->qp, &recv_wr, &recv_wr_fail);
2219 2220
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
index 84ad863fe637..2b69316dfd11 100644
--- a/net/sunrpc/xprtrdma/xprt_rdma.h
+++ b/net/sunrpc/xprtrdma/xprt_rdma.h
@@ -180,14 +180,12 @@ enum rpcrdma_chunktype {
180struct rpcrdma_buffer; 180struct rpcrdma_buffer;
181 181
182struct rpcrdma_rep { 182struct rpcrdma_rep {
183 unsigned int rr_len; /* actual received reply length */ 183 unsigned int rr_len;
184 struct rpcrdma_buffer *rr_buffer; /* home base for this structure */ 184 struct rpcrdma_buffer *rr_buffer;
185 struct rpc_xprt *rr_xprt; /* needed for request/reply matching */ 185 struct rpc_xprt *rr_xprt;
186 void (*rr_func)(struct rpcrdma_rep *);/* called by tasklet in softint */ 186 void (*rr_func)(struct rpcrdma_rep *);
187 struct list_head rr_list; /* tasklet list */ 187 struct list_head rr_list;
188 struct ib_sge rr_iov; /* for posting */ 188 struct rpcrdma_regbuf *rr_rdmabuf;
189 struct ib_mr *rr_handle; /* handle for mem in rr_iov */
190 char rr_base[MAX_RPCRDMAHDR]; /* minimal inline receive buffer */
191}; 189};
192 190
193/* 191/*