summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2007-07-03 18:31:47 +0000
committerjhb <jhb@FreeBSD.org>2007-07-03 18:31:47 +0000
commit7c4c0583053f67d0ec64bf2e5a0ba9d0a802ef3c (patch)
tree5ae4f15b0a124bc9c90ecd928749f7a0e44069d9 /sys/nfsclient
parent788b235895ff7154d4548cecaa697384662eeaaf (diff)
downloadFreeBSD-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')
-rw-r--r--sys/nfsclient/nfs_subs.c18
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) {
OpenPOWER on IntegriCloud