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)