Skip to content

Commit 65866f8

Browse files
chuckleveramschuma-ntap
authored andcommitted
xprtrdma: Reduce the number of hardway buffer allocations
While marshaling an RPC/RDMA request, the inline_{rsize,wsize} settings determine whether an inline request is used, or whether read or write chunks lists are built. The current default value of these settings is 1024. Any RPC request smaller than 1024 bytes is sent to the NFS server completely inline. rpcrdma_buffer_create() allocates and pre-registers a set of RPC buffers for each transport instance, also based on the inline rsize and wsize settings. RPC/RDMA requests and replies are built in these buffers. However, if an RPC/RDMA request is expected to be larger than 1024, a buffer has to be allocated and registered for that RPC, and deregistered and released when the RPC is complete. This is known has a "hardway allocation." Since the introduction of NFSv4, the size of RPC requests has become larger, and hardway allocations are thus more frequent. Hardway allocations are significant overhead, and they waste the existing RPC buffers pre-allocated by rpcrdma_buffer_create(). We'd like fewer hardway allocations. Increasing the size of the pre-registered buffers is the most direct way to do this. However, a blanket increase of the inline thresholds has interoperability consequences. On my 64-bit system, rpcrdma_buffer_create() requests roughly 7000 bytes for each RPC request buffer, using kmalloc(). Due to internal fragmentation, this wastes nearly 1200 bytes because kmalloc() already returns an 8192-byte piece of memory for a 7000-byte allocation request, though the extra space remains unused. So let's round up the size of the pre-allocated buffers, and make use of the unused space in the kmalloc'd memory. This change reduces the amount of hardway allocated memory for an NFSv4 general connectathon run from 1322092 to 9472 bytes (99%). Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Tested-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
1 parent 8301a2c commit 65866f8

File tree

1 file changed

+13
-12
lines changed

1 file changed

+13
-12
lines changed

net/sunrpc/xprtrdma/verbs.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include <linux/interrupt.h>
5151
#include <linux/pci.h> /* for Tavor hack below */
5252
#include <linux/slab.h>
53+
#include <asm/bitops.h>
5354

5455
#include "xprt_rdma.h"
5556

@@ -1005,7 +1006,7 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
10051006
struct rpcrdma_ia *ia, struct rpcrdma_create_data_internal *cdata)
10061007
{
10071008
char *p;
1008-
size_t len;
1009+
size_t len, rlen, wlen;
10091010
int i, rc;
10101011
struct rpcrdma_mw *r;
10111012

@@ -1120,16 +1121,16 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
11201121
* Allocate/init the request/reply buffers. Doing this
11211122
* using kmalloc for now -- one for each buf.
11221123
*/
1124+
wlen = 1 << fls(cdata->inline_wsize + sizeof(struct rpcrdma_req));
1125+
rlen = 1 << fls(cdata->inline_rsize + sizeof(struct rpcrdma_rep));
1126+
dprintk("RPC: %s: wlen = %zu, rlen = %zu\n",
1127+
__func__, wlen, rlen);
1128+
11231129
for (i = 0; i < buf->rb_max_requests; i++) {
11241130
struct rpcrdma_req *req;
11251131
struct rpcrdma_rep *rep;
11261132

1127-
len = cdata->inline_wsize + sizeof(struct rpcrdma_req);
1128-
/* RPC layer requests *double* size + 1K RPC_SLACK_SPACE! */
1129-
/* Typical ~2400b, so rounding up saves work later */
1130-
if (len < 4096)
1131-
len = 4096;
1132-
req = kmalloc(len, GFP_KERNEL);
1133+
req = kmalloc(wlen, GFP_KERNEL);
11331134
if (req == NULL) {
11341135
dprintk("RPC: %s: request buffer %d alloc"
11351136
" failed\n", __func__, i);
@@ -1141,16 +1142,16 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
11411142
buf->rb_send_bufs[i]->rl_buffer = buf;
11421143

11431144
rc = rpcrdma_register_internal(ia, req->rl_base,
1144-
len - offsetof(struct rpcrdma_req, rl_base),
1145+
wlen - offsetof(struct rpcrdma_req, rl_base),
11451146
&buf->rb_send_bufs[i]->rl_handle,
11461147
&buf->rb_send_bufs[i]->rl_iov);
11471148
if (rc)
11481149
goto out;
11491150

1150-
buf->rb_send_bufs[i]->rl_size = len-sizeof(struct rpcrdma_req);
1151+
buf->rb_send_bufs[i]->rl_size = wlen -
1152+
sizeof(struct rpcrdma_req);
11511153

1152-
len = cdata->inline_rsize + sizeof(struct rpcrdma_rep);
1153-
rep = kmalloc(len, GFP_KERNEL);
1154+
rep = kmalloc(rlen, GFP_KERNEL);
11541155
if (rep == NULL) {
11551156
dprintk("RPC: %s: reply buffer %d alloc failed\n",
11561157
__func__, i);
@@ -1162,7 +1163,7 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
11621163
buf->rb_recv_bufs[i]->rr_buffer = buf;
11631164

11641165
rc = rpcrdma_register_internal(ia, rep->rr_base,
1165-
len - offsetof(struct rpcrdma_rep, rr_base),
1166+
rlen - offsetof(struct rpcrdma_rep, rr_base),
11661167
&buf->rb_recv_bufs[i]->rr_handle,
11671168
&buf->rb_recv_bufs[i]->rr_iov);
11681169
if (rc)

0 commit comments

Comments
 (0)