Module Name:    src
Committed By:   yamt
Date:           Sun Sep 26 03:58:55 UTC 2010

Modified Files:
        src/sys/kern [yamt-nfs-mp]: vfs_syscalls.c
        src/sys/nfs [yamt-nfs-mp]: nfs_bio.c nfs_clntsubs.c nfs_subs.c
            nfs_vnops.c nfsnode.h

Log Message:
locking changes


To generate a diff of this commit:
cvs rdiff -u -r1.350.2.7 -r1.350.2.8 src/sys/kern/vfs_syscalls.c
cvs rdiff -u -r1.175.2.2 -r1.175.2.3 src/sys/nfs/nfs_bio.c
cvs rdiff -u -r1.1.2.2 -r1.1.2.3 src/sys/nfs/nfs_clntsubs.c
cvs rdiff -u -r1.201.4.5 -r1.201.4.6 src/sys/nfs/nfs_subs.c
cvs rdiff -u -r1.266.10.7 -r1.266.10.8 src/sys/nfs/nfs_vnops.c
cvs rdiff -u -r1.67.10.2 -r1.67.10.3 src/sys/nfs/nfsnode.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/vfs_syscalls.c
diff -u src/sys/kern/vfs_syscalls.c:1.350.2.7 src/sys/kern/vfs_syscalls.c:1.350.2.8
--- src/sys/kern/vfs_syscalls.c:1.350.2.7	Wed Aug 11 22:54:44 2010
+++ src/sys/kern/vfs_syscalls.c	Sun Sep 26 03:58:54 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_syscalls.c,v 1.350.2.7 2010/08/11 22:54:44 yamt Exp $	*/
+/*	$NetBSD: vfs_syscalls.c,v 1.350.2.8 2010/09/26 03:58:54 yamt Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.350.2.7 2010/08/11 22:54:44 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.350.2.8 2010/09/26 03:58:54 yamt Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_fileassoc.h"
@@ -315,8 +315,14 @@
 	 * If the user is not root, ensure that they own the directory
 	 * onto which we are attempting to mount.
 	 */
-	if ((error = VOP_GETATTR(vp, &va, l->l_cred)) != 0 ||
-	    (va.va_uid != kauth_cred_geteuid(l->l_cred) &&
+	vn_lock(vp, LK_SHARED | LK_RETRY);
+	error = VOP_GETATTR(vp, &va, l->l_cred);
+	VOP_UNLOCK(vp);
+	if (error != 0) {
+		vfs_delref(vfsops);
+		return error;
+	}
+	if ((va.va_uid != kauth_cred_geteuid(l->l_cred) &&
 	    (error = kauth_authorize_generic(l->l_cred,
 	    KAUTH_GENERIC_ISSUSER, NULL)) != 0)) {
 		vfs_delref(vfsops);

Index: src/sys/nfs/nfs_bio.c
diff -u src/sys/nfs/nfs_bio.c:1.175.2.2 src/sys/nfs/nfs_bio.c:1.175.2.3
--- src/sys/nfs/nfs_bio.c:1.175.2.2	Wed Aug 11 22:54:58 2010
+++ src/sys/nfs/nfs_bio.c	Sun Sep 26 03:58:54 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_bio.c,v 1.175.2.2 2010/08/11 22:54:58 yamt Exp $	*/
+/*	$NetBSD: nfs_bio.c,v 1.175.2.3 2010/09/26 03:58:54 yamt Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.175.2.2 2010/08/11 22:54:58 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.175.2.3 2010/09/26 03:58:54 yamt Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_nfs.h"
@@ -458,15 +458,16 @@
 	int ioflag = ap->a_ioflag;
 	int extended = 0, wrotedata = 0;
 
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
 #ifdef DIAGNOSTIC
 	if (uio->uio_rw != UIO_WRITE)
 		panic("nfs_write mode");
 #endif
 	if (vp->v_type != VREG)
 		return (EIO);
-	if (np->n_flag & NWRITEERR) {
-		np->n_flag &= ~NWRITEERR;
-		return (np->n_error);
+	error = atomic_swap_uint((unsigned int *)&np->n_error, 0);
+	if (error != 0) {
+		return error;
 	}
 #ifndef NFS_V2_ONLY
 	if ((nmp->nm_flag & NFSMNT_NFSV3) &&
@@ -1050,13 +1051,12 @@
 			}
 			mutex_exit(&uobj->vmobjlock);
 			goto out;
-		} else if (error == NFSERR_STALEWRITEVERF) {
+		} else if (error == NFSERR_STALEWRITEVERF || (random() % 10) == 0) {
 			nfs_clearcommit(vp->v_mount);
 			goto again;
 		}
 		if (error) {
 			bp->b_error = np->n_error = error;
-			np->n_flag |= NWRITEERR;
 		}
 		goto out;
 	}
@@ -1119,13 +1119,12 @@
 		 * we got an error.
 		 */
 		bp->b_error = np->n_error = error;
-		np->n_flag |= NWRITEERR;
 	}
 
 	rw_exit(&nmp->nm_writeverflock);
 
 
-	if (stalewriteverf) {
+	if (stalewriteverf || (random() % 10) == 0) {
 		nfs_clearcommit(vp->v_mount);
 	}
 #ifndef NFS_V2_ONLY
@@ -1160,7 +1159,7 @@
 		rw_enter(&nmp->nm_writeverflock, RW_READER);
 		error = nfs_writerpc(vp, uiop, &iomode, false, &stalewriteverf);
 		rw_exit(&nmp->nm_writeverflock);
-		if (stalewriteverf) {
+		if (stalewriteverf || (random() % 10) == 0) {
 			nfs_clearcommit(bp->b_vp->v_mount);
 		}
 	}

Index: src/sys/nfs/nfs_clntsubs.c
diff -u src/sys/nfs/nfs_clntsubs.c:1.1.2.2 src/sys/nfs/nfs_clntsubs.c:1.1.2.3
--- src/sys/nfs/nfs_clntsubs.c:1.1.2.2	Thu Mar 11 15:04:31 2010
+++ src/sys/nfs/nfs_clntsubs.c	Sun Sep 26 03:58:55 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_clntsubs.c,v 1.1.2.2 2010/03/11 15:04:31 yamt Exp $	*/
+/*	$NetBSD: nfs_clntsubs.c,v 1.1.2.3 2010/09/26 03:58:55 yamt Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_clntsubs.c,v 1.1.2.2 2010/03/11 15:04:31 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_clntsubs.c,v 1.1.2.3 2010/09/26 03:58:55 yamt Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_nfs.h"
@@ -302,10 +302,10 @@
 	np->n_attrstamp = time_second;
 	if (vaper != NULL) {
 		memcpy((void *)vaper, (void *)vap, sizeof(*vap));
-		if (np->n_flag & NCHG) {
-			if (np->n_flag & NACC)
+		if (np->n_specflags & NCHG) {
+			if (np->n_specflags & NACC)
 				vaper->va_atime = np->n_atim;
-			if (np->n_flag & NUPD)
+			if (np->n_specflags & NUPD)
 				vaper->va_mtime = np->n_mtim;
 		}
 	}
@@ -355,10 +355,10 @@
 			np->n_size = vap->va_size;
 	}
 	memcpy(vaper, vap, sizeof(struct vattr));
-	if (np->n_flag & NCHG) {
-		if (np->n_flag & NACC)
+	if (np->n_specflags & NCHG) {
+		if (np->n_specflags & NACC)
 			vaper->va_atime = np->n_atim;
-		if (np->n_flag & NUPD)
+		if (np->n_specflags & NUPD)
 			vaper->va_mtime = np->n_mtim;
 	}
 	mutex_exit(&np->n_attrlock);

Index: src/sys/nfs/nfs_subs.c
diff -u src/sys/nfs/nfs_subs.c:1.201.4.5 src/sys/nfs/nfs_subs.c:1.201.4.6
--- src/sys/nfs/nfs_subs.c:1.201.4.5	Thu Mar 11 15:04:31 2010
+++ src/sys/nfs/nfs_subs.c	Sun Sep 26 03:58:55 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_subs.c,v 1.201.4.5 2010/03/11 15:04:31 yamt Exp $	*/
+/*	$NetBSD: nfs_subs.c,v 1.201.4.6 2010/09/26 03:58:55 yamt Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.201.4.5 2010/03/11 15:04:31 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.201.4.6 2010/09/26 03:58:55 yamt Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_nfs.h"
@@ -1739,32 +1739,55 @@
 nfs_clearcommit(struct mount *mp)
 {
 	struct vnode *vp;
+	struct vnode *mvp;
 	struct nfsnode *np;
 	struct vm_page *pg;
 	struct nfsmount *nmp = VFSTONFS(mp);
 
+	mvp = vnalloc(mp);
 	rw_enter(&nmp->nm_writeverflock, RW_WRITER);
 	mutex_enter(&mntvnode_lock);
-	TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
+	for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp != NULL;
+	    vp = vunmark(mvp)) {
+		int error;
+
+		vmark(mvp, vp);
 		KASSERT(vp->v_mount == mp);
-		if (vp->v_type != VREG)
+		/*
+		 * skip syncer and marker vnodes
+		 */
+		if (vp->v_data == NULL || vismarker(vp)) {
 			continue;
+		}
 		mutex_enter(&vp->v_interlock);
-		if (vp->v_iflag & (VI_XLOCK | VI_CLEAN)) {
+		if (vp->v_type != VREG) {
 			mutex_exit(&vp->v_interlock);
 			continue;
 		}
+		mutex_exit(&mntvnode_lock);
+		error = vget(vp, 0);
+		if (error != 0) {
+			mutex_enter(&mntvnode_lock);
+			continue;
+		}
 		np = VTONFS(vp);
+		KASSERT(np != NULL);
+		mutex_enter(&np->n_commitlock);
 		np->n_pushlo = np->n_pushhi = np->n_pushedlo =
 		    np->n_pushedhi = 0;
 		np->n_commitflags &=
 		    ~(NFS_COMMIT_PUSH_VALID | NFS_COMMIT_PUSHED_VALID);
+		mutex_enter(&vp->v_interlock);
 		TAILQ_FOREACH(pg, &vp->v_uobj.memq, listq.queue) {
 			pg->flags &= ~PG_NEEDCOMMIT;
 		}
 		mutex_exit(&vp->v_interlock);
+		mutex_exit(&np->n_commitlock);
+		vrele(vp);
+		mutex_enter(&mntvnode_lock);
 	}
 	mutex_exit(&mntvnode_lock);
+	vnfree(mvp);
 	mutex_enter(&nmp->nm_lock);
 	nmp->nm_iflag &= ~NFSMNT_STALEWRITEVERF;
 	mutex_exit(&nmp->nm_lock);
@@ -1776,6 +1799,7 @@
 {
 	struct nfsnode *np = VTONFS(vp);
 
+	KASSERT(mutex_owned(&np->n_commitlock));
 	KASSERT(np->n_commitflags & NFS_COMMIT_PUSH_VALID);
 
 	if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
@@ -1804,6 +1828,8 @@
 	struct nfsnode *np = VTONFS(vp);
 	off_t lo, hi;
 
+	KASSERT(mutex_owned(&np->n_commitlock));
+
 	if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
 		return 0;
 	lo = off;
@@ -1818,6 +1844,8 @@
 	struct nfsnode *np = VTONFS(vp);
 	off_t lo, hi;
 
+	KASSERT(mutex_owned(&np->n_commitlock));
+
 	if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
 		return 0;
 	lo = off;
@@ -1832,6 +1860,8 @@
 	struct nfsnode *np = VTONFS(vp);
 	off_t lo, hi;
 
+	KASSERT(mutex_owned(&np->n_commitlock));
+
 	lo = off;
 	hi = lo + len;
 
@@ -1857,6 +1887,8 @@
 	struct nfsnode *np = VTONFS(vp);
 	off_t lo, hi;
 
+	KASSERT(mutex_owned(&np->n_commitlock));
+
 	if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
 		return;
 
@@ -1892,6 +1924,8 @@
 	struct nfsnode *np = VTONFS(vp);
 	off_t lo, hi;
 
+	KASSERT(mutex_owned(&np->n_commitlock));
+
 	lo = off;
 	hi = lo + len;
 
@@ -1917,6 +1951,8 @@
 	struct nfsnode *np = VTONFS(vp);
 	off_t lo, hi;
 
+	KASSERT(mutex_owned(&np->n_commitlock));
+
 	if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
 		return;
 

Index: src/sys/nfs/nfs_vnops.c
diff -u src/sys/nfs/nfs_vnops.c:1.266.10.7 src/sys/nfs/nfs_vnops.c:1.266.10.8
--- src/sys/nfs/nfs_vnops.c:1.266.10.7	Wed Aug 11 22:54:59 2010
+++ src/sys/nfs/nfs_vnops.c	Sun Sep 26 03:58:55 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_vnops.c,v 1.266.10.7 2010/08/11 22:54:59 yamt Exp $	*/
+/*	$NetBSD: nfs_vnops.c,v 1.266.10.8 2010/09/26 03:58:55 yamt Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.266.10.7 2010/08/11 22:54:59 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.266.10.8 2010/09/26 03:58:55 yamt Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_nfs.h"
@@ -462,6 +462,8 @@
 	struct nfsnode *np = VTONFS(vp);
 	int error;
 
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
 	if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
 		return (EACCES);
 	}
@@ -530,6 +532,8 @@
 	int error = 0;
 	UVMHIST_FUNC("nfs_close"); UVMHIST_CALLED(ubchist);
 
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
 	if (vp->v_type == VREG) {
 	    if (np->n_flag & NMODIFIED) {
 #ifndef NFS_V2_ONLY
@@ -541,10 +545,7 @@
 		    error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, curlwp, 1);
 		NFS_INVALIDATE_ATTRCACHE(np);
 	    }
-	    if (np->n_flag & NWRITEERR) {
-		np->n_flag &= ~NWRITEERR;
-		error = np->n_error;
-	    }
+	    error = atomic_swap_uint((unsigned int *)&np->n_error, 0);
 	}
 	UVMHIST_LOG(ubchist, "returning %d", error,0,0,0);
 	return (error);
@@ -576,8 +577,10 @@
 	/*
 	 * Update local times for special files.
 	 */
-	if (np->n_flag & (NACC | NUPD))
-		np->n_flag |= NCHG;
+	mutex_enter(&np->n_attrlock);
+	if (np->n_specflags & (NACC | NUPD))
+		np->n_specflags |= NCHG;
+	mutex_exit(&np->n_attrlock);
 
 	/*
 	 * if we have delayed truncation, do it now.
@@ -621,6 +624,8 @@
 	int error = 0;
 	u_quad_t tsize = 0;
 
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
 	/*
 	 * Setting of flags is not supported.
 	 */
@@ -793,6 +798,8 @@
 	int error = 0, attrflag, fhsize;
 	const int v3 = NFS_ISV3(dvp);
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	flags = cnp->cn_flags;
 
 	*vpp = NULLVP;
@@ -881,6 +888,7 @@
 			/* newvp has been reclaimed. */
 			vrele(newvp);
 			*vpp = NULLVP;
+			printf("%s: %p revoked\n", __func__, newvp);
 			goto dorpc;
 		}
 		if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred)
@@ -1090,6 +1098,8 @@
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
 
+	KASSERT(VOP_ISLOCKED(vp));
+
 	if (vp->v_type != VREG)
 		return EISDIR;
 	return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0));
@@ -1109,6 +1119,8 @@
 	struct vnode *vp = ap->a_vp;
 	struct nfsnode *np = VTONFS(vp);
 
+	KASSERT(VOP_ISLOCKED(vp));
+
 	if (vp->v_type != VLNK)
 		return (EPERM);
 
@@ -1523,6 +1535,8 @@
 	u_int32_t rdev;
 	const int v3 = NFS_ISV3(dvp);
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	if (vap->va_type == VCHR || vap->va_type == VBLK)
 		rdev = txdr_unsigned(vap->va_rdev);
 	else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
@@ -1608,6 +1622,8 @@
 	struct componentname *cnp = ap->a_cnp;
 	int error;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	error = nfs_mknodrpc(dvp, ap->a_vpp, cnp, ap->a_vap);
 	VN_KNOTE(dvp, NOTE_WRITE);
 	if (error == 0 || error == EEXIST)
@@ -1642,6 +1658,8 @@
 	const int v3 = NFS_ISV3(dvp);
 	u_int32_t excl_mode = NFSV3CREATE_UNCHECKED;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	/*
 	 * Oops, not for me..
 	 */
@@ -1782,6 +1800,8 @@
 	int error = 0;
 	struct vattr vattr;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 #ifndef DIAGNOSTIC
 	if ((cnp->cn_flags & HASBUF) == 0)
 		panic("nfs_remove: no name");
@@ -1859,6 +1879,8 @@
 	int rexmit = 0;
 	struct nfsnode *dnp = VTONFS(dvp);
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	nfsstats.rpccnt[NFSPROC_REMOVE]++;
 	nfsm_reqhead(dnp, NFSPROC_REMOVE,
 		NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
@@ -1906,6 +1928,8 @@
 	struct componentname *fcnp = ap->a_fcnp;
 	int error;
 
+	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
+
 #ifndef DIAGNOSTIC
 	if ((tcnp->cn_flags & HASBUF) == 0 ||
 	    (fcnp->cn_flags & HASBUF) == 0)
@@ -2044,6 +2068,8 @@
 	int rexmit = 0;
 	struct nfsnode *np = VTONFS(vp);
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	nfsstats.rpccnt[NFSPROC_LINK]++;
 	nfsm_reqhead(np, NFSPROC_LINK,
 	    NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(namelen));
@@ -2090,6 +2116,8 @@
 	struct componentname *cnp = ap->a_cnp;
 	int error = 0;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	if (dvp->v_mount != vp->v_mount) {
 		VOP_ABORTOP(dvp, cnp);
 		vput(dvp);
@@ -2245,6 +2273,8 @@
 	struct mbuf *mreq, *mrep, *md, *mb;
 	const int v3 = NFS_ISV3(dvp);
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	len = cnp->cn_namelen;
 	nfsstats.rpccnt[NFSPROC_MKDIR]++;
 	nfsm_reqhead(dnp, NFSPROC_MKDIR,
@@ -2337,6 +2367,8 @@
 	const int v3 = NFS_ISV3(dvp);
 	struct nfsnode *dnp;
 
+	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
 	if (dvp == vp) {
 		vrele(dvp);
 		vput(dvp);
@@ -3193,6 +3225,13 @@
 
 	struct vnode *vp = ap->a_vp;
 
+	/*
+	 * XXX currently we can be called with the vnode only
+	 * LK_SHARED-locked.  it violates the vnode locking protocol.
+	 *
+	 * eg. nfs_read -> nfs_flushstalebuf -> vinvalbuf -> VOP_FSYNC
+	 */
+
 	if (vp->v_type != VREG)
 		return 0;
 
@@ -3209,14 +3248,16 @@
 {
 	struct nfsnode *np = VTONFS(vp);
 	int error;
+	int error2;
 	int flushflags = PGO_ALLPAGES|PGO_CLEANIT|PGO_SYNCIO;
 	UVMHIST_FUNC("nfs_flush"); UVMHIST_CALLED(ubchist);
 
+	KASSERT(vp->v_type == VREG);
 	mutex_enter(&vp->v_interlock);
 	error = VOP_PUTPAGES(vp, 0, 0, flushflags);
-	if (np->n_flag & NWRITEERR) {
-		error = np->n_error;
-		np->n_flag &= ~NWRITEERR;
+	error2 = atomic_swap_uint((unsigned int *)&np->n_error, 0);
+	if (error2 != 0) {
+		error = error2;
 	}
 	UVMHIST_LOG(ubchist, "returning %d", error,0,0,0);
 	return (error);
@@ -3445,8 +3486,10 @@
 	/*
 	 * Set access flag.
 	 */
-	np->n_flag |= NACC;
+	mutex_enter(&np->n_attrlock);
+	np->n_specflags |= NACC;
 	getnanotime(&np->n_atim);
+	mutex_exit(&np->n_attrlock);
 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
 }
 
@@ -3467,8 +3510,10 @@
 	/*
 	 * Set update flag.
 	 */
-	np->n_flag |= NUPD;
+	mutex_enter(&np->n_attrlock);
+	np->n_specflags |= NUPD;
 	getnanotime(&np->n_mtim);
+	mutex_exit(&np->n_attrlock);
 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
 }
 
@@ -3490,18 +3535,22 @@
 	struct nfsnode *np = VTONFS(vp);
 	struct vattr vattr;
 
-	if (np->n_flag & (NACC | NUPD)) {
-		np->n_flag |= NCHG;
+	mutex_enter(&np->n_attrlock);
+	if (np->n_specflags & (NACC | NUPD)) {
+		np->n_specflags |= NCHG;
 		if (vp->v_usecount == 1 &&
 		    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
 			vattr_null(&vattr);
-			if (np->n_flag & NACC)
+			if (np->n_specflags & NACC)
 				vattr.va_atime = np->n_atim;
-			if (np->n_flag & NUPD)
+			if (np->n_specflags & NUPD)
 				vattr.va_mtime = np->n_mtim;
+			mutex_exit(&np->n_attrlock);
 			(void)VOP_SETATTR(vp, &vattr, ap->a_cred);
+			mutex_enter(&np->n_attrlock);
 		}
 	}
+	mutex_exit(&np->n_attrlock);
 	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
 }
 
@@ -3522,8 +3571,10 @@
 	/*
 	 * Set access flag.
 	 */
-	np->n_flag |= NACC;
+	mutex_enter(&np->n_attrlock);
+	np->n_specflags |= NACC;
 	getnanotime(&np->n_atim);
+	mutex_exit(&np->n_attrlock);
 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
 }
 
@@ -3544,8 +3595,10 @@
 	/*
 	 * Set update flag.
 	 */
-	np->n_flag |= NUPD;
+	mutex_enter(&np->n_attrlock);
+	np->n_specflags |= NUPD;
 	getnanotime(&np->n_mtim);
+	mutex_exit(&np->n_attrlock);
 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
 }
 
@@ -3567,24 +3620,28 @@
 	struct nfsnode *np = VTONFS(vp);
 	struct vattr vattr;
 
-	if (np->n_flag & (NACC | NUPD)) {
+	mutex_enter(&np->n_attrlock);
+	if (np->n_specflags & (NACC | NUPD)) {
 		struct timespec ts;
 
 		getnanotime(&ts);
-		if (np->n_flag & NACC)
+		if (np->n_specflags & NACC)
 			np->n_atim = ts;
-		if (np->n_flag & NUPD)
+		if (np->n_specflags & NUPD)
 			np->n_mtim = ts;
-		np->n_flag |= NCHG;
+		np->n_specflags |= NCHG;
 		if (vp->v_usecount == 1 &&
 		    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
 			vattr_null(&vattr);
-			if (np->n_flag & NACC)
+			if (np->n_specflags & NACC)
 				vattr.va_atime = np->n_atim;
-			if (np->n_flag & NUPD)
+			if (np->n_specflags & NUPD)
 				vattr.va_mtime = np->n_mtim;
+			mutex_exit(&np->n_attrlock);
 			(void)VOP_SETATTR(vp, &vattr, ap->a_cred);
+			mutex_enter(&np->n_attrlock);
 		}
 	}
+	mutex_exit(&np->n_attrlock);
 	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
 }

Index: src/sys/nfs/nfsnode.h
diff -u src/sys/nfs/nfsnode.h:1.67.10.2 src/sys/nfs/nfsnode.h:1.67.10.3
--- src/sys/nfs/nfsnode.h:1.67.10.2	Mon May  4 08:14:22 2009
+++ src/sys/nfs/nfsnode.h	Sun Sep 26 03:58:55 2010
@@ -1,4 +1,4 @@
-/*	 $NetBSD: nfsnode.h,v 1.67.10.2 2009/05/04 08:14:22 yamt Exp $	*/
+/*	 $NetBSD: nfsnode.h,v 1.67.10.3 2010/09/26 03:58:55 yamt Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -49,6 +49,13 @@
 #include <miscfs/genfs/genfs_node.h>
 
 /*
+ * protected by:
+ *	a: n_attrlock
+ *	c: n_commitlock
+ *	v: vnode lock
+ */
+
+/*
  * Definitions for the directory cache. Because directory cookies
  * are an opaque 64 bit entity, we need to provide some sort of
  * mapping between cookies and logical blocknumbers. Also,
@@ -94,18 +101,18 @@
  */
 
 struct nfsnode_spec {
-	struct timespec	nspec_mtim;	/* local mtime */
-	struct timespec	nspec_atim;	/* local atime */
+	struct timespec	nspec_mtim;	/* a: local mtime */
+	struct timespec	nspec_atim;	/* a: local atime */
 };
 
 struct nfsnode_reg {
-	off_t nreg_pushedlo;		/* 1st blk in commited range */
-	off_t nreg_pushedhi;		/* Last block in range */
-	off_t nreg_pushlo;		/* 1st block in commit range */
-	off_t nreg_pushhi;		/* Last block in range */
+	off_t nreg_pushedlo;		/* c: 1st blk in commited range */
+	off_t nreg_pushedhi;		/* c: Last block in range */
+	off_t nreg_pushlo;		/* c: 1st block in commit range */
+	off_t nreg_pushhi;		/* c: Last block in range */
 	kmutex_t nreg_commitlock;	/* Serialize commits XXX */
-	int nreg_commitflags;
-	int nreg_error;			/* Save write error value */
+	int nreg_commitflags;		/* c: */
+	int nreg_error;			/* v: Save write error value */
 };
 
 struct nfsnode_dir {
@@ -171,7 +178,8 @@
 	time_t			n_accstamp;	/* Access cache timestamp */
 	uid_t			n_accuid;	/* Last access requester */
 	int			n_accmode;	/* Mode last requested */
-	int			n_accerror;	/* Error last returned */
+	int			n_accerror;	/* a: Error last returned */
+	unsigned int		n_specflags;	/* a: */
 };
 
 /*
@@ -186,10 +194,6 @@
 #define	NFLUSHWANT	0x0001	/* Want wakeup from a flush in prog. */
 #define	NFLUSHINPROG	0x0002	/* Avoid multiple calls to vinvalbuf() */
 #define	NMODIFIED	0x0004	/* Might have a modified buffer in bio */
-#define	NWRITEERR	0x0008	/* Flag write errors so close will know */
-#define	NACC		0x0100	/* Special file accessed */
-#define	NUPD		0x0200	/* Special file updated */
-#define	NCHG		0x0400	/* Special file times changed */
 #define	NTRUNCDELAYED	0x1000	/* Should be truncated later;
 				   implies stale cache */
 #define	NREMOVED	0x2000	/* Has been removed */
@@ -199,6 +203,13 @@
 #define	NFS_EOFVALID(ndp)	((ndp)->n_flag & NEOFVALID)
 
 /*
+ * n_specflags
+ */
+#define	NACC		0x0100	/* Special file accessed */
+#define	NUPD		0x0200	/* Special file updated */
+#define	NCHG		0x0400	/* Special file times changed */
+
+/*
  * Convert between nfsnode pointers and vnode pointers
  */
 #define VTONFS(vp)	((struct nfsnode *)(vp)->v_data)

Reply via email to