nfsd4: use xdr_truncate_encode
authorJ. Bruce Fields <bfields@redhat.com>
Thu, 27 Feb 2014 01:17:02 +0000 (20:17 -0500)
committerJ. Bruce Fields <bfields@redhat.com>
Fri, 30 May 2014 21:31:48 +0000 (17:31 -0400)
Now that lengths are reliable, we can use xdr_truncate instead of
open-coding it everywhere.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4xdr.c

index 57f60810b745bde88f01a1c938be5885852d1d37..c2815f4849bf9a05e6f3ed7b11729caf83331c6f 100644 (file)
@@ -2053,7 +2053,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
        struct svc_fh *tempfh = NULL;
        struct kstatfs statfs;
        __be32 *p;
-       __be32 *start = xdr->p;
+       int starting_len = xdr->buf->len;
        __be32 *attrlenp;
        u32 dummy;
        u64 dummy64;
@@ -2547,13 +2547,8 @@ out:
                fh_put(tempfh);
                kfree(tempfh);
        }
-       if (status) {
-               int nbytes = (char *)xdr->p - (char *)start;
-               /* open code what *should* be xdr_truncate(xdr, len); */
-               xdr->iov->iov_len -= nbytes;
-               xdr->buf->len -= nbytes;
-               xdr->p = start;
-       }
+       if (status)
+               xdr_truncate_encode(xdr, starting_len);
        return status;
 out_nfserr:
        status = nfserrno(err);
@@ -3008,6 +3003,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
        struct page *page;
        unsigned long maxcount; 
        struct xdr_stream *xdr = &resp->xdr;
+       int starting_len = xdr->buf->len;
        long len;
        __be32 *p;
 
@@ -3044,9 +3040,13 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
                        &maxcount);
 
        if (nfserr) {
-               xdr->p -= 2;
-               xdr->iov->iov_len -= 8;
-               xdr->buf->len -= 8;
+               /*
+                * nfsd_splice_actor may have already messed with the
+                * page length; reset it so as not to confuse
+                * xdr_truncate_encode:
+                */
+               xdr->buf->page_len = 0;
+               xdr_truncate_encode(xdr, starting_len);
                return nfserr;
        }
        eof = (read->rd_offset + maxcount >=
@@ -3079,6 +3079,7 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
        int maxcount;
        struct xdr_stream *xdr = &resp->xdr;
        char *page;
+       int length_offset = xdr->buf->len;
        __be32 *p;
 
        if (nfserr)
@@ -3103,9 +3104,7 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
        if (nfserr == nfserr_isdir)
                nfserr = nfserr_inval;
        if (nfserr) {
-               xdr->p--;
-               xdr->iov->iov_len -= 4;
-               xdr->buf->len -= 4;
+               xdr_truncate_encode(xdr, length_offset);
                return nfserr;
        }
 
@@ -3134,7 +3133,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
        int maxcount;
        loff_t offset;
        struct xdr_stream *xdr = &resp->xdr;
-       __be32 *page, *savep, *tailbase;
+       int starting_len = xdr->buf->len;
+       __be32 *page, *tailbase;
        __be32 *p;
 
        if (nfserr)
@@ -3145,7 +3145,6 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
                return nfserr_resource;
 
        RESERVE_SPACE(NFS4_VERIFIER_SIZE);
-       savep = p;
 
        /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
        WRITE32(0);
@@ -3207,10 +3206,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
 
        return 0;
 err_no_verf:
-       xdr->p = savep;
-       xdr->iov->iov_len = ((char *)resp->xdr.p)
-                               - (char *)resp->xdr.buf->head[0].iov_base;
-       xdr->buf->len = xdr->iov->iov_len;
+       xdr_truncate_encode(xdr, starting_len);
        return nfserr;
 }