aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2014-03-22 15:15:11 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-05-30 17:31:50 -0400
commit4e21ac4b6f1d09c56f7d10916eaa738361214ab7 (patch)
treeb8ba2be1bc30afa15dd3257432004b045a8b5b82
parentd0a381dd0eda1cc769a5762d0eed4d0d662219f2 (diff)
nfsd4: reserve space before inlining 0-copy pages
Once we've included page-cache pages in the encoding it's difficult to remove them and restart encoding. (xdr_truncate_encode doesn't handle that case.) So, make sure we'll have adequate space to finish the operation first. For now COMPOUND_SLACK_SPACE checks should prevent this case happening, but we want to remove those checks. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/nfsd/nfs4xdr.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 799a90479487..8728715cd6e8 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3071,6 +3071,10 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
3071 if (!p) 3071 if (!p)
3072 return nfserr_resource; 3072 return nfserr_resource;
3073 3073
3074 /* Make sure there will be room for padding if needed: */
3075 if (xdr->end - xdr->p < 1)
3076 return nfserr_resource;
3077
3074 maxcount = svc_max_payload(resp->rqstp); 3078 maxcount = svc_max_payload(resp->rqstp);
3075 if (maxcount > read->rd_length) 3079 if (maxcount > read->rd_length)
3076 maxcount = read->rd_length; 3080 maxcount = read->rd_length;
@@ -3122,8 +3126,6 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
3122 resp->xdr.buf->tail[0].iov_len = 0; 3126 resp->xdr.buf->tail[0].iov_len = 0;
3123 if (maxcount&3) { 3127 if (maxcount&3) {
3124 p = xdr_reserve_space(xdr, 4); 3128 p = xdr_reserve_space(xdr, 4);
3125 if (!p)
3126 return nfserr_resource;
3127 WRITE32(0); 3129 WRITE32(0);
3128 resp->xdr.buf->tail[0].iov_base += maxcount&3; 3130 resp->xdr.buf->tail[0].iov_base += maxcount&3;
3129 resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3); 3131 resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3);
@@ -3156,6 +3158,9 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
3156 if (!p) 3158 if (!p)
3157 return nfserr_resource; 3159 return nfserr_resource;
3158 3160
3161 if (xdr->end - xdr->p < 1)
3162 return nfserr_resource;
3163
3159 /* 3164 /*
3160 * XXX: By default, the ->readlink() VFS op will truncate symlinks 3165 * XXX: By default, the ->readlink() VFS op will truncate symlinks
3161 * if they would overflow the buffer. Is this kosher in NFSv4? If 3166 * if they would overflow the buffer. Is this kosher in NFSv4? If
@@ -3182,8 +3187,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
3182 resp->xdr.buf->tail[0].iov_len = 0; 3187 resp->xdr.buf->tail[0].iov_len = 0;
3183 if (maxcount&3) { 3188 if (maxcount&3) {
3184 p = xdr_reserve_space(xdr, 4); 3189 p = xdr_reserve_space(xdr, 4);
3185 if (!p)
3186 return nfserr_resource;
3187 WRITE32(0); 3190 WRITE32(0);
3188 resp->xdr.buf->tail[0].iov_base += maxcount&3; 3191 resp->xdr.buf->tail[0].iov_base += maxcount&3;
3189 resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3); 3192 resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3);