Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- fs/nfsd/nfs4xdr.c | 99 +++++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 48 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 44ffcaac3c8e..7ef6baf9c3b7 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1806,6 +1806,57 @@ nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp, return nfserr_bad_xdr; } +static __be32 +nfsd4_decode_layoutcommit(struct nfsd4_compoundargs *argp, + struct nfsd4_layoutcommit *lcp) +{ + __be32 *p, status; + + if (xdr_stream_decode_u64(argp->xdr, &lcp->lc_seg.offset) < 0) + goto xdr_error; + if (xdr_stream_decode_u64(argp->xdr, &lcp->lc_seg.length) < 0) + goto xdr_error; + p = xdr_inline_decode(argp->xdr, sizeof(__be32)); + if (!p) + goto xdr_error; + lcp->lc_reclaim = (*p == xdr_zero) ? 0 : 1; + status = nfsd4_decode_stateid4(argp, &lcp->lc_sid); + if (status) + goto out; + if (xdr_stream_decode_u32(argp->xdr, &lcp->lc_newoffset) < 0) + goto xdr_error; + if (lcp->lc_newoffset) { + if (xdr_stream_decode_u64(argp->xdr, &lcp->lc_last_wr) < 0) + goto xdr_error; + } else + lcp->lc_last_wr = 0; + p = xdr_inline_decode(argp->xdr, sizeof(__be32)); + if (!p) + goto xdr_error; + if (xdr_item_is_present(p)) { + status = nfsd4_decode_nfstime4(argp, &lcp->lc_mtime); + if (status) + goto out; + } else { + lcp->lc_mtime.tv_nsec = UTIME_NOW; + } + if (xdr_stream_decode_u32(argp->xdr, &lcp->lc_layout_type) < 0) + goto xdr_error; + if (xdr_stream_decode_u32(argp->xdr, &lcp->lc_up_len) < 0) + goto xdr_error; + if (lcp->lc_up_len > 0) { + lcp->lc_up_layout = xdr_inline_decode(argp->xdr, lcp->lc_up_len); + if (!lcp->lc_up_layout) + goto xdr_error; + } + + status = nfs_ok; +out: + return status; +xdr_error: + return nfserr_bad_xdr; +} + static __be32 nfsd4_decode_layoutget(struct nfsd4_compoundargs *argp, struct nfsd4_layoutget *lgp) @@ -1830,54 +1881,6 @@ nfsd4_decode_layoutget(struct nfsd4_compoundargs *argp, DECODE_TAIL; } -static __be32 -nfsd4_decode_layoutcommit(struct nfsd4_compoundargs *argp, - struct nfsd4_layoutcommit *lcp) -{ - DECODE_HEAD; - u32 timechange; - - READ_BUF(20); - p = xdr_decode_hyper(p, &lcp->lc_seg.offset); - p = xdr_decode_hyper(p, &lcp->lc_seg.length); - lcp->lc_reclaim = be32_to_cpup(p++); - - status = nfsd4_decode_stateid4(argp, &lcp->lc_sid); - if (status) - return status; - - READ_BUF(4); - lcp->lc_newoffset = be32_to_cpup(p++); - if (lcp->lc_newoffset) { - READ_BUF(8); - p = xdr_decode_hyper(p, &lcp->lc_last_wr); - } else - lcp->lc_last_wr = 0; - READ_BUF(4); - timechange = be32_to_cpup(p++); - if (timechange) { - status = nfsd4_decode_nfstime4(argp, &lcp->lc_mtime); - if (status) - return status; - } else { - lcp->lc_mtime.tv_nsec = UTIME_NOW; - } - READ_BUF(8); - lcp->lc_layout_type = be32_to_cpup(p++); - - /* - * Save the layout update in XDR format and let the layout driver deal - * with it later. - */ - lcp->lc_up_len = be32_to_cpup(p++); - if (lcp->lc_up_len > 0) { - READ_BUF(lcp->lc_up_len); - READMEM(lcp->lc_up_layout, lcp->lc_up_len); - } - - DECODE_TAIL; -} - static __be32 nfsd4_decode_layoutreturn(struct nfsd4_compoundargs *argp, struct nfsd4_layoutreturn *lrp)