aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r--fs/nfs/nfs4xdr.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 207d399c8dee..40da65e8fa2a 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -2656,6 +2656,10 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req,
2656 encode_sequence(xdr, &args->seq_args, &hdr); 2656 encode_sequence(xdr, &args->seq_args, &hdr);
2657 encode_putfh(xdr, NFS_FH(args->inode), &hdr); 2657 encode_putfh(xdr, NFS_FH(args->inode), &hdr);
2658 encode_layoutget(xdr, args, &hdr); 2658 encode_layoutget(xdr, args, &hdr);
2659
2660 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
2661 args->layout.pages, 0, args->layout.pglen);
2662
2659 encode_nops(&hdr); 2663 encode_nops(&hdr);
2660} 2664}
2661 2665
@@ -5022,6 +5026,9 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
5022 __be32 *p; 5026 __be32 *p;
5023 int status; 5027 int status;
5024 u32 layout_count; 5028 u32 layout_count;
5029 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
5030 struct kvec *iov = rcvbuf->head;
5031 u32 hdrlen, recvd;
5025 5032
5026 status = decode_op_hdr(xdr, OP_LAYOUTGET); 5033 status = decode_op_hdr(xdr, OP_LAYOUTGET);
5027 if (status) 5034 if (status)
@@ -5038,17 +5045,14 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
5038 return -EINVAL; 5045 return -EINVAL;
5039 } 5046 }
5040 5047
5041 p = xdr_inline_decode(xdr, 24); 5048 p = xdr_inline_decode(xdr, 28);
5042 if (unlikely(!p)) 5049 if (unlikely(!p))
5043 goto out_overflow; 5050 goto out_overflow;
5044 p = xdr_decode_hyper(p, &res->range.offset); 5051 p = xdr_decode_hyper(p, &res->range.offset);
5045 p = xdr_decode_hyper(p, &res->range.length); 5052 p = xdr_decode_hyper(p, &res->range.length);
5046 res->range.iomode = be32_to_cpup(p++); 5053 res->range.iomode = be32_to_cpup(p++);
5047 res->type = be32_to_cpup(p++); 5054 res->type = be32_to_cpup(p++);
5048 5055 res->layoutp->len = be32_to_cpup(p);
5049 status = decode_opaque_inline(xdr, &res->layout.len, (char **)&p);
5050 if (unlikely(status))
5051 return status;
5052 5056
5053 dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", 5057 dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n",
5054 __func__, 5058 __func__,
@@ -5056,12 +5060,18 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
5056 (unsigned long)res->range.length, 5060 (unsigned long)res->range.length,
5057 res->range.iomode, 5061 res->range.iomode,
5058 res->type, 5062 res->type,
5059 res->layout.len); 5063 res->layoutp->len);
5064
5065 hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base;
5066 recvd = req->rq_rcv_buf.len - hdrlen;
5067 if (res->layoutp->len > recvd) {
5068 dprintk("NFS: server cheating in layoutget reply: "
5069 "layout len %u > recvd %u\n",
5070 res->layoutp->len, recvd);
5071 return -EINVAL;
5072 }
5060 5073
5061 /* nfs4_proc_layoutget allocated a single page */ 5074 xdr_read_pages(xdr, res->layoutp->len);
5062 if (res->layout.len > PAGE_SIZE)
5063 return -ENOMEM;
5064 memcpy(res->layout.buf, p, res->layout.len);
5065 5075
5066 if (layout_count > 1) { 5076 if (layout_count > 1) {
5067 /* We only handle a length one array at the moment. Any 5077 /* We only handle a length one array at the moment. Any