Commit 25c307ac authored by Chuck Lever's avatar Chuck Lever

NFSD: Clean up nfsd4_encode_readdir()

Untangle nfsd4_encode_readdir() so it is more clear what XDR data
item is being encoded by which piece of code.
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent a1aee9aa
...@@ -4452,84 +4452,82 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, ...@@ -4452,84 +4452,82 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr,
return nfserr; return nfserr;
} }
static __be32 static __be32 nfsd4_encode_dirlist4(struct xdr_stream *xdr,
nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir,
union nfsd4_op_u *u) u32 max_payload)
{ {
struct nfsd4_readdir *readdir = &u->readdir; int bytes_left, maxcount, starting_len = xdr->buf->len;
int maxcount;
int bytes_left;
loff_t offset; loff_t offset;
struct xdr_stream *xdr = resp->xdr; __be32 status;
int starting_len = xdr->buf->len;
__be32 *p;
nfserr = nfsd4_encode_verifier4(xdr, &readdir->rd_verf);
if (nfserr != nfs_ok)
return nfserr;
/* /*
* Number of bytes left for directory entries allowing for the * Number of bytes left for directory entries allowing for the
* final 8 bytes of the readdir and a following failed op: * final 8 bytes of the readdir and a following failed op.
*/ */
bytes_left = xdr->buf->buflen - xdr->buf->len bytes_left = xdr->buf->buflen - xdr->buf->len -
- COMPOUND_ERR_SLACK_SPACE - 8; COMPOUND_ERR_SLACK_SPACE - XDR_UNIT * 2;
if (bytes_left < 0) { if (bytes_left < 0)
nfserr = nfserr_resource; return nfserr_resource;
goto err_no_verf; maxcount = min_t(u32, readdir->rd_maxcount, max_payload);
}
maxcount = svc_max_payload(resp->rqstp);
maxcount = min_t(u32, readdir->rd_maxcount, maxcount);
/* /*
* Note the rfc defines rd_maxcount as the size of the * The RFC defines rd_maxcount as the size of the
* READDIR4resok structure, which includes the verifier above * READDIR4resok structure, which includes the verifier
* and the 8 bytes encoded at the end of this function: * and the 8 bytes encoded at the end of this function.
*/ */
if (maxcount < 16) { if (maxcount < XDR_UNIT * 4)
nfserr = nfserr_toosmall; return nfserr_toosmall;
goto err_no_verf; maxcount = min_t(int, maxcount - XDR_UNIT * 4, bytes_left);
}
maxcount = min_t(int, maxcount-16, bytes_left);
/* RFC 3530 14.2.24 allows us to ignore dircount when it's 0: */ /* RFC 3530 14.2.24 allows us to ignore dircount when it's 0 */
if (!readdir->rd_dircount) if (!readdir->rd_dircount)
readdir->rd_dircount = svc_max_payload(resp->rqstp); readdir->rd_dircount = max_payload;
/* *entries */
readdir->xdr = xdr; readdir->xdr = xdr;
readdir->rd_maxcount = maxcount; readdir->rd_maxcount = maxcount;
readdir->common.err = 0; readdir->common.err = 0;
readdir->cookie_offset = 0; readdir->cookie_offset = 0;
offset = readdir->rd_cookie; offset = readdir->rd_cookie;
nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp, &offset, status = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp, &offset,
&readdir->common, nfsd4_encode_entry4); &readdir->common, nfsd4_encode_entry4);
if (nfserr == nfs_ok && if (status)
readdir->common.err == nfserr_toosmall && return status;
xdr->buf->len == starting_len + 8) { if (readdir->common.err == nfserr_toosmall &&
/* nothing encoded; which limit did we hit?: */ xdr->buf->len == starting_len) {
if (maxcount - 16 < bytes_left) /* No entries were encoded. Which limit did we hit? */
/* It was the fault of rd_maxcount: */ if (maxcount - XDR_UNIT * 4 < bytes_left)
nfserr = nfserr_toosmall; /* It was the fault of rd_maxcount */
else return nfserr_toosmall;
/* We ran out of buffer space: */ /* We ran out of buffer space */
nfserr = nfserr_resource; return nfserr_resource;
} }
if (nfserr)
goto err_no_verf;
/* Encode the final entry's cookie value */ /* Encode the final entry's cookie value */
nfsd4_encode_entry4_nfs_cookie4(readdir, offset); nfsd4_encode_entry4_nfs_cookie4(readdir, offset);
/* No entries follow */
if (xdr_stream_encode_item_absent(xdr) != XDR_UNIT)
return nfserr_resource;
p = xdr_reserve_space(xdr, 8); /* eof */
if (!p) { return nfsd4_encode_bool(xdr, readdir->common.err == nfserr_eof);
WARN_ON_ONCE(1); }
goto err_no_verf;
}
*p++ = 0; /* no more entries */
*p++ = htonl(readdir->common.err == nfserr_eof);
return 0; static __be32
err_no_verf: nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr,
union nfsd4_op_u *u)
{
struct nfsd4_readdir *readdir = &u->readdir;
struct xdr_stream *xdr = resp->xdr;
int starting_len = xdr->buf->len;
/* cookieverf */
nfserr = nfsd4_encode_verifier4(xdr, &readdir->rd_verf);
if (nfserr != nfs_ok)
return nfserr;
/* reply */
nfserr = nfsd4_encode_dirlist4(xdr, readdir, svc_max_payload(resp->rqstp));
if (nfserr != nfs_ok)
xdr_truncate_encode(xdr, starting_len); xdr_truncate_encode(xdr, starting_len);
return nfserr; return nfserr;
} }
......
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