Cleanup XDR parsing for LAYOUTGET, GETDEVICEINFO
changes LAYOUTGET and GETDEVICEINFO XDR parsing to: - not use vmap, which doesn't work on incoherent archs - use xdr_stream parsing for all xdr Signed-off-by: Weston Andros Adamson <dros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
committed by
Trond Myklebust
parent
ef31153786
commit
35124a0994
@@ -2656,6 +2656,10 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req,
|
||||
encode_sequence(xdr, &args->seq_args, &hdr);
|
||||
encode_putfh(xdr, NFS_FH(args->inode), &hdr);
|
||||
encode_layoutget(xdr, args, &hdr);
|
||||
|
||||
xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
|
||||
args->layout.pages, 0, args->layout.pglen);
|
||||
|
||||
encode_nops(&hdr);
|
||||
}
|
||||
|
||||
@@ -5022,6 +5026,9 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
|
||||
__be32 *p;
|
||||
int status;
|
||||
u32 layout_count;
|
||||
struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
|
||||
struct kvec *iov = rcvbuf->head;
|
||||
u32 hdrlen, recvd;
|
||||
|
||||
status = decode_op_hdr(xdr, OP_LAYOUTGET);
|
||||
if (status)
|
||||
@@ -5038,17 +5045,14 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
p = xdr_inline_decode(xdr, 24);
|
||||
p = xdr_inline_decode(xdr, 28);
|
||||
if (unlikely(!p))
|
||||
goto out_overflow;
|
||||
p = xdr_decode_hyper(p, &res->range.offset);
|
||||
p = xdr_decode_hyper(p, &res->range.length);
|
||||
res->range.iomode = be32_to_cpup(p++);
|
||||
res->type = be32_to_cpup(p++);
|
||||
|
||||
status = decode_opaque_inline(xdr, &res->layout.len, (char **)&p);
|
||||
if (unlikely(status))
|
||||
return status;
|
||||
res->layoutp->len = be32_to_cpup(p);
|
||||
|
||||
dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n",
|
||||
__func__,
|
||||
@@ -5056,12 +5060,18 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
|
||||
(unsigned long)res->range.length,
|
||||
res->range.iomode,
|
||||
res->type,
|
||||
res->layout.len);
|
||||
res->layoutp->len);
|
||||
|
||||
/* nfs4_proc_layoutget allocated a single page */
|
||||
if (res->layout.len > PAGE_SIZE)
|
||||
return -ENOMEM;
|
||||
memcpy(res->layout.buf, p, res->layout.len);
|
||||
hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base;
|
||||
recvd = req->rq_rcv_buf.len - hdrlen;
|
||||
if (res->layoutp->len > recvd) {
|
||||
dprintk("NFS: server cheating in layoutget reply: "
|
||||
"layout len %u > recvd %u\n",
|
||||
res->layoutp->len, recvd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
xdr_read_pages(xdr, res->layoutp->len);
|
||||
|
||||
if (layout_count > 1) {
|
||||
/* We only handle a length one array at the moment. Any
|
||||
|
Reference in New Issue
Block a user