Skip to content

Commit bb1fb40

Browse files
committed
NFSD: Fix READDIR on NFSv3 mounts of ext4 exports
I noticed that recently, simple operations like "make" started failing on NFSv3 mounts of ext4 exports. Network capture shows that READDIRPLUS operated correctly but READDIR failed with NFS3ERR_INVAL. The vfs_llseek() call returned EINVAL when it is passed a non-zero starting directory cookie. I bisected to commit c689bdd ("nfsd: further centralize protocol version checks."). Turns out that nfsd3_proc_readdir() does not call fh_verify() before it calls nfsd_readdir(), so the new fhp->fh_64bit_cookies boolean is not set properly. This leaves the NFSD_MAY_64BIT_COOKIE unset when the directory is opened. For ext4, this causes the wrong "max file size" value to be used when sanity checking the incoming directory cookie (which is a seek offset value). The fhp->fh_64bit_cookies boolean is /always/ properly initialized after nfsd_open() returns. There doesn't seem to be a reason for the generic NFSD open helper to handle the f_mode fix-up for directories, so just move that to the one caller that tries to open an S_IFDIR with NFSD_MAY_64BIT_COOKIE. Suggested-by: NeilBrown <neilb@suse.de> Fixes: c689bdd ("nfsd: further centralize protocol version checks.") Reviewed-by: NeilBrown <neilb@suse.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 63a8158 commit bb1fb40

File tree

1 file changed

+5
-8
lines changed

1 file changed

+5
-8
lines changed

fs/nfsd/vfs.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -903,11 +903,6 @@ __nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
903903
goto out;
904904
}
905905

906-
if (may_flags & NFSD_MAY_64BIT_COOKIE)
907-
file->f_mode |= FMODE_64BITHASH;
908-
else
909-
file->f_mode |= FMODE_32BITHASH;
910-
911906
*filp = file;
912907
out:
913908
return host_err;
@@ -2174,13 +2169,15 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
21742169
loff_t offset = *offsetp;
21752170
int may_flags = NFSD_MAY_READ;
21762171

2177-
if (fhp->fh_64bit_cookies)
2178-
may_flags |= NFSD_MAY_64BIT_COOKIE;
2179-
21802172
err = nfsd_open(rqstp, fhp, S_IFDIR, may_flags, &file);
21812173
if (err)
21822174
goto out;
21832175

2176+
if (fhp->fh_64bit_cookies)
2177+
file->f_mode |= FMODE_64BITHASH;
2178+
else
2179+
file->f_mode |= FMODE_32BITHASH;
2180+
21842181
offset = vfs_llseek(file, offset, SEEK_SET);
21852182
if (offset < 0) {
21862183
err = nfserrno((int)offset);

0 commit comments

Comments
 (0)