Commit 4e21ac4b authored by J. Bruce Fields's avatar J. Bruce Fields

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: default avatarJ. Bruce Fields <bfields@redhat.com>
parent d0a381dd
...@@ -3071,6 +3071,10 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, ...@@ -3071,6 +3071,10 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
if (!p) if (!p)
return nfserr_resource; return nfserr_resource;
/* Make sure there will be room for padding if needed: */
if (xdr->end - xdr->p < 1)
return nfserr_resource;
maxcount = svc_max_payload(resp->rqstp); maxcount = svc_max_payload(resp->rqstp);
if (maxcount > read->rd_length) if (maxcount > read->rd_length)
maxcount = read->rd_length; maxcount = read->rd_length;
...@@ -3122,8 +3126,6 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, ...@@ -3122,8 +3126,6 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
resp->xdr.buf->tail[0].iov_len = 0; resp->xdr.buf->tail[0].iov_len = 0;
if (maxcount&3) { if (maxcount&3) {
p = xdr_reserve_space(xdr, 4); p = xdr_reserve_space(xdr, 4);
if (!p)
return nfserr_resource;
WRITE32(0); WRITE32(0);
resp->xdr.buf->tail[0].iov_base += maxcount&3; resp->xdr.buf->tail[0].iov_base += maxcount&3;
resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3); 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,6 +3158,9 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
if (!p) if (!p)
return nfserr_resource; return nfserr_resource;
if (xdr->end - xdr->p < 1)
return nfserr_resource;
/* /*
* XXX: By default, the ->readlink() VFS op will truncate symlinks * XXX: By default, the ->readlink() VFS op will truncate symlinks
* if they would overflow the buffer. Is this kosher in NFSv4? If * 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,8 +3187,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
resp->xdr.buf->tail[0].iov_len = 0; resp->xdr.buf->tail[0].iov_len = 0;
if (maxcount&3) { if (maxcount&3) {
p = xdr_reserve_space(xdr, 4); p = xdr_reserve_space(xdr, 4);
if (!p)
return nfserr_resource;
WRITE32(0); WRITE32(0);
resp->xdr.buf->tail[0].iov_base += maxcount&3; resp->xdr.buf->tail[0].iov_base += maxcount&3;
resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3); resp->xdr.buf->tail[0].iov_len = 4 - (maxcount&3);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment