Commit fc891828 authored by Linus Torvalds's avatar Linus Torvalds

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
parents dec9cbf9 756b9b37
...@@ -78,8 +78,7 @@ static __be32 *read_buf(struct xdr_stream *xdr, int nbytes) ...@@ -78,8 +78,7 @@ static __be32 *read_buf(struct xdr_stream *xdr, int nbytes)
p = xdr_inline_decode(xdr, nbytes); p = xdr_inline_decode(xdr, nbytes);
if (unlikely(p == NULL)) if (unlikely(p == NULL))
printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed " printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed!\n");
"or truncated request.\n");
return p; return p;
} }
...@@ -890,7 +889,6 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r ...@@ -890,7 +889,6 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
struct cb_compound_hdr_arg hdr_arg = { 0 }; struct cb_compound_hdr_arg hdr_arg = { 0 };
struct cb_compound_hdr_res hdr_res = { NULL }; struct cb_compound_hdr_res hdr_res = { NULL };
struct xdr_stream xdr_in, xdr_out; struct xdr_stream xdr_in, xdr_out;
struct xdr_buf *rq_arg = &rqstp->rq_arg;
__be32 *p, status; __be32 *p, status;
struct cb_process_state cps = { struct cb_process_state cps = {
.drc_status = 0, .drc_status = 0,
...@@ -902,8 +900,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r ...@@ -902,8 +900,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
dprintk("%s: start\n", __func__); dprintk("%s: start\n", __func__);
rq_arg->len = rq_arg->head[0].iov_len + rq_arg->page_len; xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
xdr_init_decode(&xdr_in, rq_arg, rq_arg->head[0].iov_base);
p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
xdr_init_encode(&xdr_out, &rqstp->rq_res, p); xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
......
...@@ -353,20 +353,12 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied) ...@@ -353,20 +353,12 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
{ {
struct rpc_xprt *xprt = req->rq_xprt; struct rpc_xprt *xprt = req->rq_xprt;
struct svc_serv *bc_serv = xprt->bc_serv; struct svc_serv *bc_serv = xprt->bc_serv;
struct xdr_buf *rq_rcv_buf = &req->rq_rcv_buf;
spin_lock(&xprt->bc_pa_lock); spin_lock(&xprt->bc_pa_lock);
list_del(&req->rq_bc_pa_list); list_del(&req->rq_bc_pa_list);
xprt_dec_alloc_count(xprt, 1); xprt_dec_alloc_count(xprt, 1);
spin_unlock(&xprt->bc_pa_lock); spin_unlock(&xprt->bc_pa_lock);
if (copied <= rq_rcv_buf->head[0].iov_len) {
rq_rcv_buf->head[0].iov_len = copied;
rq_rcv_buf->page_len = 0;
} else {
rq_rcv_buf->page_len = copied - rq_rcv_buf->head[0].iov_len;
}
req->rq_private_buf.len = copied; req->rq_private_buf.len = copied;
set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
......
...@@ -1363,7 +1363,19 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, ...@@ -1363,7 +1363,19 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg));
memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res)); memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res));
/* Adjust the argument buffer length */
rqstp->rq_arg.len = req->rq_private_buf.len; rqstp->rq_arg.len = req->rq_private_buf.len;
if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) {
rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len;
rqstp->rq_arg.page_len = 0;
} else if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len +
rqstp->rq_arg.page_len)
rqstp->rq_arg.page_len = rqstp->rq_arg.len -
rqstp->rq_arg.head[0].iov_len;
else
rqstp->rq_arg.len = rqstp->rq_arg.head[0].iov_len +
rqstp->rq_arg.page_len;
/* reset result send buffer "put" position */ /* reset result send buffer "put" position */
resv->iov_len = 0; resv->iov_len = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment