Merge tag 'nfs-for-4.4-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfix from Trond Myklebust:
"SUNRPC: Fix a NFSv4.1 callback channel regression"

* tag 'nfs-for-4.4-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
SUNRPC: Fix callback channel

Changed files
+14 -13
fs
net
+2 -5
fs/nfs/callback_xdr.c
··· 78 78 79 79 p = xdr_inline_decode(xdr, nbytes); 80 80 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"); 83 82 return p; 84 83 } 85 84 ··· 889 890 struct cb_compound_hdr_arg hdr_arg = { 0 }; 890 891 struct cb_compound_hdr_res hdr_res = { NULL }; 891 892 struct xdr_stream xdr_in, xdr_out; 892 - struct xdr_buf *rq_arg = &rqstp->rq_arg; 893 893 __be32 *p, status; 894 894 struct cb_process_state cps = { 895 895 .drc_status = 0, ··· 900 902 901 903 dprintk("%s: start\n", __func__); 902 904 903 - rq_arg->len = rq_arg->head[0].iov_len + rq_arg->page_len; 904 - xdr_init_decode(&xdr_in, rq_arg, rq_arg->head[0].iov_base); 905 + xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base); 905 906 906 907 p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); 907 908 xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
-8
net/sunrpc/backchannel_rqst.c
··· 353 353 { 354 354 struct rpc_xprt *xprt = req->rq_xprt; 355 355 struct svc_serv *bc_serv = xprt->bc_serv; 356 - struct xdr_buf *rq_rcv_buf = &req->rq_rcv_buf; 357 356 358 357 spin_lock(&xprt->bc_pa_lock); 359 358 list_del(&req->rq_bc_pa_list); 360 359 xprt_dec_alloc_count(xprt, 1); 361 360 spin_unlock(&xprt->bc_pa_lock); 362 - 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 361 370 362 req->rq_private_buf.len = copied; 371 363 set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
+12
net/sunrpc/svc.c
··· 1363 1363 memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); 1364 1364 memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); 1365 1365 memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res)); 1366 + 1367 + /* Adjust the argument buffer length */ 1366 1368 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; 1367 1379 1368 1380 /* reset result send buffer "put" position */ 1369 1381 resv->iov_len = 0;