Commit 10715329 authored by Kendrick M. Smith's avatar Kendrick M. Smith Committed by Linus Torvalds

[PATCH] kNFSd: NFSv4: tweak nfsd_readdir() for NFSv4

This patch makes three small changes to nfsd_readdir().

First, the 'filldir' routine for NFSv4 may return an arbitrary error,
which should become the return value for nfsd_readdir().  I implemented
this by adding an 'nfserr' field to the 'struct readdir_cd'.

Second, in NFSv4 the caller of nfsd_readdir() will specify an attribute
bitmap, which must be communicated to the 'filldir' routine.  I implemented
this by adding a @bitmap parameter to nfsd_readdir() and a corresponding
field in the 'struct readdir_cd'.  (The bitmap is not interpreted in any
way by nfsd_readdir().)

Finally, NFSv4 defines a new error nfserr_readdir_nospc, which indicates
that there was not enough buffer space to encode a single entry.
parent c9f192bd
......@@ -460,7 +460,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t) argp->cookie,
nfs3svc_encode_entry,
buffer, &count, argp->verf);
buffer, &count, argp->verf, NULL);
memcpy(resp->verf, argp->verf, 8);
resp->count = count;
......@@ -495,7 +495,7 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t) argp->cookie,
nfs3svc_encode_entry_plus,
buffer, &count, argp->verf);
buffer, &count, argp->verf, NULL);
memcpy(resp->verf, argp->verf, 8);
resp->count = count;
......
......@@ -492,7 +492,7 @@ nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
/* Read directory and encode entries on the fly */
nfserr = nfsd_readdir(rqstp, &argp->fh, (loff_t) argp->cookie,
nfssvc_encode_entry,
buffer, &count, NULL);
buffer, &count, NULL, NULL);
resp->count = count;
fh_put(&argp->fh);
......
......@@ -1381,7 +1381,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
*/
int
nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
encode_dent_fn func, u32 *buffer, int *countp, u32 *verf)
encode_dent_fn func, u32 *buffer, int *countp, u32 *verf, u32 *bmval)
{
u32 *p;
int oldlen, eof, err;
......@@ -1402,6 +1402,10 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
cd.buffer = buffer;
cd.buflen = *countp; /* count of words */
cd.dirfh = fhp;
if (bmval) {
cd.bmval[0] = bmval[0];
cd.bmval[1] = bmval[1];
}
/*
* Read the directory entries. This silly loop is necessary because
......@@ -1417,8 +1421,15 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
if (err < 0)
goto out_nfserr;
err = cd.nfserr;
if (err)
goto out_close;
} while (oldlen != cd.buflen && !cd.eob);
err = nfserr_readdir_nospc;
if (rqstp->rq_vers == 4 && cd.eob && cd.buffer == buffer)
goto out_close;
/* If we didn't fill the buffer completely, we're at EOF */
eof = !cd.eob;
......
......@@ -55,6 +55,8 @@ struct readdir_cd {
char plus; /* readdirplus */
char eob; /* end of buffer */
char dotonly;
int nfserr; /* v4 only */
u32 bmval[2]; /* v4 only */
};
typedef int (*encode_dent_fn)(struct readdir_cd *, const char *,
int, loff_t, ino_t, unsigned int);
......@@ -119,7 +121,8 @@ int nfsd_truncate(struct svc_rqst *, struct svc_fh *,
unsigned long size);
int nfsd_readdir(struct svc_rqst *, struct svc_fh *,
loff_t, encode_dent_fn,
u32 *buffer, int *countp, u32 *verf);
u32 *buffer, int *countp, u32 *verf,
u32 *bmval);
int nfsd_statfs(struct svc_rqst *, struct svc_fh *,
struct statfs *);
......
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