Skip to content

Commit 25c307a

Browse files
committed
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: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent a1aee9a commit 25c307a

File tree

1 file changed

+55
-57
lines changed

1 file changed

+55
-57
lines changed

fs/nfsd/nfs4xdr.c

Lines changed: 55 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4452,85 +4452,83 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr,
44524452
return nfserr;
44534453
}
44544454

4455-
static __be32
4456-
nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr,
4457-
union nfsd4_op_u *u)
4455+
static __be32 nfsd4_encode_dirlist4(struct xdr_stream *xdr,
4456+
struct nfsd4_readdir *readdir,
4457+
u32 max_payload)
44584458
{
4459-
struct nfsd4_readdir *readdir = &u->readdir;
4460-
int maxcount;
4461-
int bytes_left;
4459+
int bytes_left, maxcount, starting_len = xdr->buf->len;
44624460
loff_t offset;
4463-
struct xdr_stream *xdr = resp->xdr;
4464-
int starting_len = xdr->buf->len;
4465-
__be32 *p;
4466-
4467-
nfserr = nfsd4_encode_verifier4(xdr, &readdir->rd_verf);
4468-
if (nfserr != nfs_ok)
4469-
return nfserr;
4461+
__be32 status;
44704462

44714463
/*
44724464
* Number of bytes left for directory entries allowing for the
4473-
* final 8 bytes of the readdir and a following failed op:
4465+
* final 8 bytes of the readdir and a following failed op.
44744466
*/
4475-
bytes_left = xdr->buf->buflen - xdr->buf->len
4476-
- COMPOUND_ERR_SLACK_SPACE - 8;
4477-
if (bytes_left < 0) {
4478-
nfserr = nfserr_resource;
4479-
goto err_no_verf;
4480-
}
4481-
maxcount = svc_max_payload(resp->rqstp);
4482-
maxcount = min_t(u32, readdir->rd_maxcount, maxcount);
4467+
bytes_left = xdr->buf->buflen - xdr->buf->len -
4468+
COMPOUND_ERR_SLACK_SPACE - XDR_UNIT * 2;
4469+
if (bytes_left < 0)
4470+
return nfserr_resource;
4471+
maxcount = min_t(u32, readdir->rd_maxcount, max_payload);
4472+
44834473
/*
4484-
* Note the rfc defines rd_maxcount as the size of the
4485-
* READDIR4resok structure, which includes the verifier above
4486-
* and the 8 bytes encoded at the end of this function:
4474+
* The RFC defines rd_maxcount as the size of the
4475+
* READDIR4resok structure, which includes the verifier
4476+
* and the 8 bytes encoded at the end of this function.
44874477
*/
4488-
if (maxcount < 16) {
4489-
nfserr = nfserr_toosmall;
4490-
goto err_no_verf;
4491-
}
4492-
maxcount = min_t(int, maxcount-16, bytes_left);
4478+
if (maxcount < XDR_UNIT * 4)
4479+
return nfserr_toosmall;
4480+
maxcount = min_t(int, maxcount - XDR_UNIT * 4, bytes_left);
44934481

4494-
/* RFC 3530 14.2.24 allows us to ignore dircount when it's 0: */
4482+
/* RFC 3530 14.2.24 allows us to ignore dircount when it's 0 */
44954483
if (!readdir->rd_dircount)
4496-
readdir->rd_dircount = svc_max_payload(resp->rqstp);
4484+
readdir->rd_dircount = max_payload;
44974485

4486+
/* *entries */
44984487
readdir->xdr = xdr;
44994488
readdir->rd_maxcount = maxcount;
45004489
readdir->common.err = 0;
45014490
readdir->cookie_offset = 0;
4502-
45034491
offset = readdir->rd_cookie;
4504-
nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp, &offset,
4492+
status = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp, &offset,
45054493
&readdir->common, nfsd4_encode_entry4);
4506-
if (nfserr == nfs_ok &&
4507-
readdir->common.err == nfserr_toosmall &&
4508-
xdr->buf->len == starting_len + 8) {
4509-
/* nothing encoded; which limit did we hit?: */
4510-
if (maxcount - 16 < bytes_left)
4511-
/* It was the fault of rd_maxcount: */
4512-
nfserr = nfserr_toosmall;
4513-
else
4514-
/* We ran out of buffer space: */
4515-
nfserr = nfserr_resource;
4494+
if (status)
4495+
return status;
4496+
if (readdir->common.err == nfserr_toosmall &&
4497+
xdr->buf->len == starting_len) {
4498+
/* No entries were encoded. Which limit did we hit? */
4499+
if (maxcount - XDR_UNIT * 4 < bytes_left)
4500+
/* It was the fault of rd_maxcount */
4501+
return nfserr_toosmall;
4502+
/* We ran out of buffer space */
4503+
return nfserr_resource;
45164504
}
4517-
if (nfserr)
4518-
goto err_no_verf;
4519-
45204505
/* Encode the final entry's cookie value */
45214506
nfsd4_encode_entry4_nfs_cookie4(readdir, offset);
4507+
/* No entries follow */
4508+
if (xdr_stream_encode_item_absent(xdr) != XDR_UNIT)
4509+
return nfserr_resource;
45224510

4523-
p = xdr_reserve_space(xdr, 8);
4524-
if (!p) {
4525-
WARN_ON_ONCE(1);
4526-
goto err_no_verf;
4527-
}
4528-
*p++ = 0; /* no more entries */
4529-
*p++ = htonl(readdir->common.err == nfserr_eof);
4511+
/* eof */
4512+
return nfsd4_encode_bool(xdr, readdir->common.err == nfserr_eof);
4513+
}
45304514

4531-
return 0;
4532-
err_no_verf:
4533-
xdr_truncate_encode(xdr, starting_len);
4515+
static __be32
4516+
nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr,
4517+
union nfsd4_op_u *u)
4518+
{
4519+
struct nfsd4_readdir *readdir = &u->readdir;
4520+
struct xdr_stream *xdr = resp->xdr;
4521+
int starting_len = xdr->buf->len;
4522+
4523+
/* cookieverf */
4524+
nfserr = nfsd4_encode_verifier4(xdr, &readdir->rd_verf);
4525+
if (nfserr != nfs_ok)
4526+
return nfserr;
4527+
4528+
/* reply */
4529+
nfserr = nfsd4_encode_dirlist4(xdr, readdir, svc_max_payload(resp->rqstp));
4530+
if (nfserr != nfs_ok)
4531+
xdr_truncate_encode(xdr, starting_len);
45344532
return nfserr;
45354533
}
45364534

0 commit comments

Comments
 (0)