diff options
author | jhb <jhb@FreeBSD.org> | 2007-07-03 18:31:47 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2007-07-03 18:31:47 +0000 |
commit | 7c4c0583053f67d0ec64bf2e5a0ba9d0a802ef3c (patch) | |
tree | 5ae4f15b0a124bc9c90ecd928749f7a0e44069d9 /sys/nfsclient/nfs_subs.c | |
parent | 788b235895ff7154d4548cecaa697384662eeaaf (diff) | |
download | FreeBSD-src-7c4c0583053f67d0ec64bf2e5a0ba9d0a802ef3c.zip FreeBSD-src-7c4c0583053f67d0ec64bf2e5a0ba9d0a802ef3c.tar.gz |
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)
Diffstat (limited to 'sys/nfsclient/nfs_subs.c')
-rw-r--r-- | sys/nfsclient/nfs_subs.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c index 61a82b8..d829fde 100644 --- a/sys/nfsclient/nfs_subs.c +++ b/sys/nfsclient/nfs_subs.c @@ -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) { |