Skip to content

Commit 756b9b3

Browse files
committed
SUNRPC: Fix callback channel
The NFSv4.1 callback channel is currently broken because the receive message will keep shrinking because the backchannel receive buffer size never gets reset. The easiest solution to this problem is instead of changing the receive buffer, to rather adjust the copied request. Fixes: 38b7631 ("nfs4: limit callback decoding to received bytes") Cc: Benjamin Coddington <[email protected]> Cc: [email protected] Signed-off-by: Trond Myklebust <[email protected]>
1 parent 527e931 commit 756b9b3

File tree

3 files changed

+14
-13
lines changed

3 files changed

+14
-13
lines changed

fs/nfs/callback_xdr.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ static __be32 *read_buf(struct xdr_stream *xdr, int nbytes)
7878

7979
p = xdr_inline_decode(xdr, nbytes);
8080
if (unlikely(p == NULL))
81-
printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed "
82-
"or truncated request.\n");
81+
printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed!\n");
8382
return p;
8483
}
8584

@@ -890,7 +889,6 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
890889
struct cb_compound_hdr_arg hdr_arg = { 0 };
891890
struct cb_compound_hdr_res hdr_res = { NULL };
892891
struct xdr_stream xdr_in, xdr_out;
893-
struct xdr_buf *rq_arg = &rqstp->rq_arg;
894892
__be32 *p, status;
895893
struct cb_process_state cps = {
896894
.drc_status = 0,
@@ -902,8 +900,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
902900

903901
dprintk("%s: start\n", __func__);
904902

905-
rq_arg->len = rq_arg->head[0].iov_len + rq_arg->page_len;
906-
xdr_init_decode(&xdr_in, rq_arg, rq_arg->head[0].iov_base);
903+
xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
907904

908905
p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
909906
xdr_init_encode(&xdr_out, &rqstp->rq_res, p);

net/sunrpc/backchannel_rqst.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -353,20 +353,12 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
353353
{
354354
struct rpc_xprt *xprt = req->rq_xprt;
355355
struct svc_serv *bc_serv = xprt->bc_serv;
356-
struct xdr_buf *rq_rcv_buf = &req->rq_rcv_buf;
357356

358357
spin_lock(&xprt->bc_pa_lock);
359358
list_del(&req->rq_bc_pa_list);
360359
xprt_dec_alloc_count(xprt, 1);
361360
spin_unlock(&xprt->bc_pa_lock);
362361

363-
if (copied <= rq_rcv_buf->head[0].iov_len) {
364-
rq_rcv_buf->head[0].iov_len = copied;
365-
rq_rcv_buf->page_len = 0;
366-
} else {
367-
rq_rcv_buf->page_len = copied - rq_rcv_buf->head[0].iov_len;
368-
}
369-
370362
req->rq_private_buf.len = copied;
371363
set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
372364

net/sunrpc/svc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,7 +1363,19 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
13631363
memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
13641364
memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg));
13651365
memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res));
1366+
1367+
/* Adjust the argument buffer length */
13661368
rqstp->rq_arg.len = req->rq_private_buf.len;
1369+
if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) {
1370+
rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len;
1371+
rqstp->rq_arg.page_len = 0;
1372+
} else if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len +
1373+
rqstp->rq_arg.page_len)
1374+
rqstp->rq_arg.page_len = rqstp->rq_arg.len -
1375+
rqstp->rq_arg.head[0].iov_len;
1376+
else
1377+
rqstp->rq_arg.len = rqstp->rq_arg.head[0].iov_len +
1378+
rqstp->rq_arg.page_len;
13671379

13681380
/* reset result send buffer "put" position */
13691381
resv->iov_len = 0;

0 commit comments

Comments
 (0)