Skip to content

Commit 9d96acb

Browse files
author
Trond Myklebust
committed
SUNRPC: Add a bvec array to struct xdr_buf for use with iovec_iter()
Add a bvec array to struct xdr_buf, and have the client allocate it when we need to receive data into pages. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent 431f6eb commit 9d96acb

File tree

5 files changed

+63
-1
lines changed

5 files changed

+63
-1
lines changed

include/linux/sunrpc/xdr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <asm/unaligned.h>
1919
#include <linux/scatterlist.h>
2020

21+
struct bio_vec;
2122
struct rpc_rqst;
2223

2324
/*
@@ -52,6 +53,7 @@ struct xdr_buf {
5253
struct kvec head[1], /* RPC header + non-page data */
5354
tail[1]; /* Appended after page data */
5455

56+
struct bio_vec *bvec;
5557
struct page ** pages; /* Array of pages */
5658
unsigned int page_base, /* Start of page data */
5759
page_len, /* Length of page data */
@@ -70,6 +72,8 @@ xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
7072
buf->head[0].iov_base = start;
7173
buf->head[0].iov_len = len;
7274
buf->tail[0].iov_len = 0;
75+
buf->bvec = NULL;
76+
buf->pages = NULL;
7377
buf->page_len = 0;
7478
buf->flags = 0;
7579
buf->len = 0;
@@ -116,6 +120,9 @@ __be32 *xdr_decode_netobj(__be32 *p, struct xdr_netobj *);
116120
void xdr_inline_pages(struct xdr_buf *, unsigned int,
117121
struct page **, unsigned int, unsigned int);
118122
void xdr_terminate_string(struct xdr_buf *, const u32);
123+
size_t xdr_buf_pagecount(struct xdr_buf *buf);
124+
int xdr_alloc_bvec(struct xdr_buf *buf, gfp_t gfp);
125+
void xdr_free_bvec(struct xdr_buf *buf);
119126

120127
static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
121128
{

include/linux/sunrpc/xprt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ struct rpc_xprt_ops {
141141
void (*connect)(struct rpc_xprt *xprt, struct rpc_task *task);
142142
int (*buf_alloc)(struct rpc_task *task);
143143
void (*buf_free)(struct rpc_task *task);
144+
void (*prepare_request)(struct rpc_rqst *req);
144145
int (*send_request)(struct rpc_rqst *req);
145146
void (*set_retrans_timeout)(struct rpc_task *task);
146147
void (*timer)(struct rpc_xprt *xprt, struct rpc_task *task);
@@ -343,6 +344,7 @@ int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
343344
void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
344345
void xprt_free_slot(struct rpc_xprt *xprt,
345346
struct rpc_rqst *req);
347+
void xprt_request_prepare(struct rpc_rqst *req);
346348
bool xprt_prepare_transmit(struct rpc_task *task);
347349
void xprt_request_enqueue_transmit(struct rpc_task *task);
348350
void xprt_request_enqueue_receive(struct rpc_task *task);

net/sunrpc/clnt.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1753,6 +1753,8 @@ rpc_xdr_encode(struct rpc_task *task)
17531753

17541754
task->tk_status = rpcauth_wrap_req(task, encode, req, p,
17551755
task->tk_msg.rpc_argp);
1756+
if (task->tk_status == 0)
1757+
xprt_request_prepare(req);
17561758
}
17571759

17581760
/*
@@ -1768,7 +1770,7 @@ call_encode(struct rpc_task *task)
17681770
/* Did the encode result in an error condition? */
17691771
if (task->tk_status != 0) {
17701772
/* Was the error nonfatal? */
1771-
if (task->tk_status == -EAGAIN)
1773+
if (task->tk_status == -EAGAIN || task->tk_status == -ENOMEM)
17721774
rpc_delay(task, HZ >> 4);
17731775
else
17741776
rpc_exit(task, task->tk_status);

net/sunrpc/xdr.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/errno.h>
1616
#include <linux/sunrpc/xdr.h>
1717
#include <linux/sunrpc/msg_prot.h>
18+
#include <linux/bvec.h>
1819

1920
/*
2021
* XDR functions for basic NFS types
@@ -128,6 +129,39 @@ xdr_terminate_string(struct xdr_buf *buf, const u32 len)
128129
}
129130
EXPORT_SYMBOL_GPL(xdr_terminate_string);
130131

132+
size_t
133+
xdr_buf_pagecount(struct xdr_buf *buf)
134+
{
135+
if (!buf->page_len)
136+
return 0;
137+
return (buf->page_base + buf->page_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
138+
}
139+
140+
int
141+
xdr_alloc_bvec(struct xdr_buf *buf, gfp_t gfp)
142+
{
143+
size_t i, n = xdr_buf_pagecount(buf);
144+
145+
if (n != 0 && buf->bvec == NULL) {
146+
buf->bvec = kmalloc_array(n, sizeof(buf->bvec[0]), gfp);
147+
if (!buf->bvec)
148+
return -ENOMEM;
149+
for (i = 0; i < n; i++) {
150+
buf->bvec[i].bv_page = buf->pages[i];
151+
buf->bvec[i].bv_len = PAGE_SIZE;
152+
buf->bvec[i].bv_offset = 0;
153+
}
154+
}
155+
return 0;
156+
}
157+
158+
void
159+
xdr_free_bvec(struct xdr_buf *buf)
160+
{
161+
kfree(buf->bvec);
162+
buf->bvec = NULL;
163+
}
164+
131165
void
132166
xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset,
133167
struct page **pages, unsigned int base, unsigned int len)

net/sunrpc/xprt.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,22 @@ xprt_request_dequeue_transmit(struct rpc_task *task)
12631263
spin_unlock(&xprt->queue_lock);
12641264
}
12651265

1266+
/**
1267+
* xprt_request_prepare - prepare an encoded request for transport
1268+
* @req: pointer to rpc_rqst
1269+
*
1270+
* Calls into the transport layer to do whatever is needed to prepare
1271+
* the request for transmission or receive.
1272+
*/
1273+
void
1274+
xprt_request_prepare(struct rpc_rqst *req)
1275+
{
1276+
struct rpc_xprt *xprt = req->rq_xprt;
1277+
1278+
if (xprt->ops->prepare_request)
1279+
xprt->ops->prepare_request(req);
1280+
}
1281+
12661282
/**
12671283
* xprt_request_need_retransmit - Test if a task needs retransmission
12681284
* @task: pointer to rpc_task
@@ -1727,6 +1743,7 @@ void xprt_release(struct rpc_task *task)
17271743
if (req->rq_buffer)
17281744
xprt->ops->buf_free(task);
17291745
xprt_inject_disconnect(xprt);
1746+
xdr_free_bvec(&req->rq_rcv_buf);
17301747
if (req->rq_cred != NULL)
17311748
put_rpccred(req->rq_cred);
17321749
task->tk_rqstp = NULL;

0 commit comments

Comments
 (0)