1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-26 11:47:31 +00:00

Fix for a race where out of order loading of NFS attrs into the

nfsnode could lead to attrs being stale. One example (that we
ran into) was a READDIR+, WRITE. The responses came back in
order, but the attrs from the WRITE were loaded before the
attrs from the READDIR+, leading to the wrong size from being
read on the next stat() call.

MFC after:	1 week
Submitted by:	mohans
Approved by:	re (kensmith)
This commit is contained in:
John Baldwin 2007-07-03 18:31:47 +00:00
parent 03e557fd5a
commit f4b65ca5d0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=171190

View File

@ -546,7 +546,7 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
struct mbuf *md;
enum vtype vtyp;
u_short vmode;
struct timespec mtime;
struct timespec mtime, mtime_save;
int v3 = NFS_ISV3(vp);
struct thread *td = curthread;
@ -615,6 +615,7 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
vap->va_type = vtyp;
vap->va_mode = (vmode & 07777);
vap->va_rdev = rdev;
mtime_save = vap->va_mtime;
vap->va_mtime = mtime;
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
if (v3) {
@ -686,6 +687,21 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
np->n_size = vap->va_size;
}
}
/*
* The following checks are added to prevent a race between (say)
* a READDIR+ and a WRITE.
* READDIR+, WRITE requests sent out.
* READDIR+ resp, WRITE resp received on client.
* However, the WRITE resp was handled before the READDIR+ resp
* causing the post op attrs from the write to be loaded first
* and the attrs from the READDIR+ to be loaded later. If this
* happens, we have stale attrs loaded into the attrcache.
* We detect this by for the mtime moving back. We invalidate the
* attrcache when this happens.
*/
if (timespeccmp(&mtime_save, &vap->va_mtime, >))
/* Size changed or mtime went backwards */
np->n_attrstamp = 0;
if (vaper != NULL) {
bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
if (np->n_flag & NCHG) {