mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
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 commitc689bdd3bf
("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:c689bdd3bf
("nfsd: further centralize protocol version checks.") Reviewed-by: NeilBrown <neilb@suse.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
63a81588cd
commit
bb1fb40f8b
@ -903,11 +903,6 @@ __nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (may_flags & NFSD_MAY_64BIT_COOKIE)
|
|
||||||
file->f_mode |= FMODE_64BITHASH;
|
|
||||||
else
|
|
||||||
file->f_mode |= FMODE_32BITHASH;
|
|
||||||
|
|
||||||
*filp = file;
|
*filp = file;
|
||||||
out:
|
out:
|
||||||
return host_err;
|
return host_err;
|
||||||
@ -2174,13 +2169,15 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
|
|||||||
loff_t offset = *offsetp;
|
loff_t offset = *offsetp;
|
||||||
int may_flags = NFSD_MAY_READ;
|
int may_flags = NFSD_MAY_READ;
|
||||||
|
|
||||||
if (fhp->fh_64bit_cookies)
|
|
||||||
may_flags |= NFSD_MAY_64BIT_COOKIE;
|
|
||||||
|
|
||||||
err = nfsd_open(rqstp, fhp, S_IFDIR, may_flags, &file);
|
err = nfsd_open(rqstp, fhp, S_IFDIR, may_flags, &file);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (fhp->fh_64bit_cookies)
|
||||||
|
file->f_mode |= FMODE_64BITHASH;
|
||||||
|
else
|
||||||
|
file->f_mode |= FMODE_32BITHASH;
|
||||||
|
|
||||||
offset = vfs_llseek(file, offset, SEEK_SET);
|
offset = vfs_llseek(file, offset, SEEK_SET);
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
err = nfserrno((int)offset);
|
err = nfserrno((int)offset);
|
||||||
|
Loading…
Reference in New Issue
Block a user