diff options
author | J. Bruce Fields <bfields@redhat.com> | 2014-03-22 15:15:11 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-05-30 17:31:50 -0400 |
commit | 4e21ac4b6f1d09c56f7d10916eaa738361214ab7 (patch) | |
tree | b8ba2be1bc30afa15dd3257432004b045a8b5b82 | |
parent | d0a381dd0eda1cc769a5762d0eed4d0d662219f2 (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.c | 11 |
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); |