Date: Mon, 20 Sep 2010 19:59:08 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r212930 - in stable/7/sys: nfs4client nfsclient Message-ID: <201009201959.o8KJx8aI065841@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhb Date: Mon Sep 20 19:59:08 2010 New Revision: 212930 URL: http://svn.freebsd.org/changeset/base/212930 Log: MFC 212293: Store the full timestamp when caching timestamps of files and directories for purposes of validating name cache entries. This closes races where two updates to a file or directory within the same second could result in stale entries in the name cache. To preserve the ABI of 'struct nfsnode', the existing timestamp fields are left with 'n_unusedX' placeholders along with the unused 'n_expiry' field. The larger n_ctime and n_dmtime fields are added to the end of the structure. Modified: stable/7/sys/nfs4client/nfs4_vnops.c stable/7/sys/nfsclient/nfs_vnops.c stable/7/sys/nfsclient/nfsnode.h Directory Properties: stable/7/sys/ (props changed) stable/7/sys/cddl/contrib/opensolaris/ (props changed) stable/7/sys/contrib/dev/acpica/ (props changed) stable/7/sys/contrib/pf/ (props changed) Modified: stable/7/sys/nfs4client/nfs4_vnops.c ============================================================================== --- stable/7/sys/nfs4client/nfs4_vnops.c Mon Sep 20 19:58:50 2010 (r212929) +++ stable/7/sys/nfs4client/nfs4_vnops.c Mon Sep 20 19:59:08 2010 (r212930) @@ -965,8 +965,8 @@ nfs4_lookup(struct vop_lookup_args *ap) struct vattr vattr; newvp = *vpp; - if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td) - && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { + if (VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td) == 0 && + timespeccmp(&vattr.va_ctime, &VTONFS(newvp)->n_ctime, ==)) { nfsstats.lookupcache_hits++; if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) @@ -1081,7 +1081,7 @@ nfs4_lookup(struct vop_lookup_args *ap) cnp->cn_flags |= SAVENAME; if ((cnp->cn_flags & MAKEENTRY) && (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { - np->n_ctime = np->n_vattr.va_ctime.tv_sec; + np->n_ctime = np->n_vattr.va_ctime; cache_enter(dvp, newvp, cnp); } *vpp = newvp; Modified: stable/7/sys/nfsclient/nfs_vnops.c ============================================================================== --- stable/7/sys/nfsclient/nfs_vnops.c Mon Sep 20 19:58:50 2010 (r212929) +++ stable/7/sys/nfsclient/nfs_vnops.c Mon Sep 20 19:59:08 2010 (r212930) @@ -861,7 +861,7 @@ nfs_lookup(struct vop_lookup_args *ap) struct vnode *dvp = ap->a_dvp; struct vnode **vpp = ap->a_vpp; struct vattr vattr; - time_t dmtime; + struct timespec dmtime; int flags = cnp->cn_flags; struct vnode *newvp; struct nfsmount *nmp; @@ -914,7 +914,7 @@ nfs_lookup(struct vop_lookup_args *ap) mtx_unlock(&newnp->n_mtx); } if (VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td) == 0 && - vattr.va_ctime.tv_sec == newnp->n_ctime) { + timespeccmp(&vattr.va_ctime, &newnp->n_ctime, ==)) { nfsstats.lookupcache_hits++; if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) @@ -938,13 +938,13 @@ nfs_lookup(struct vop_lookup_args *ap) */ if ((u_int)(ticks - np->n_dmtime_ticks) < (negnametimeo * hz) && VOP_GETATTR(dvp, &vattr, cnp->cn_cred, td) == 0 && - vattr.va_mtime.tv_sec == np->n_dmtime) { + timespeccmp(&vattr.va_mtime, &np->n_dmtime, ==)) { nfsstats.lookupcache_hits++; return (ENOENT); } cache_purge_negative(dvp); mtx_lock(&np->n_mtx); - np->n_dmtime = 0; + timespecclear(&np->n_dmtime); mtx_unlock(&np->n_mtx); } @@ -959,7 +959,7 @@ nfs_lookup(struct vop_lookup_args *ap) * the lookup RPC has been performed on the server but before * n_dmtime is set at the end of this function. */ - dmtime = np->n_vattr.va_mtime.tv_sec; + dmtime = np->n_vattr.va_mtime; error = 0; newvp = NULLVP; nfsstats.lookupcache_misses++; @@ -1046,7 +1046,7 @@ nfs_lookup(struct vop_lookup_args *ap) cnp->cn_flags |= SAVENAME; if ((cnp->cn_flags & MAKEENTRY) && (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { - np->n_ctime = np->n_vattr.va_ctime.tv_sec; + np->n_ctime = np->n_vattr.va_ctime; cache_enter(dvp, newvp, cnp); } *vpp = newvp; @@ -1092,8 +1092,8 @@ nfsmout: * lookup. */ mtx_lock(&np->n_mtx); - if (np->n_dmtime <= dmtime) { - if (np->n_dmtime == 0) { + if (timespeccmp(&np->n_dmtime, &dmtime, <=)) { + if (!timespecisset(&np->n_dmtime)) { np->n_dmtime = dmtime; np->n_dmtime_ticks = ticks; } @@ -2550,8 +2550,11 @@ nfs_readdirplusrpc(struct vnode *vp, str dp->d_type = IFTODT(VTTOIF(np->n_vattr.va_type)); ndp->ni_vp = newvp; - /* Update n_ctime, so subsequent lookup doesn't purge entry */ - np->n_ctime = np->n_vattr.va_ctime.tv_sec; + /* + * Update n_ctime so subsequent lookup + * doesn't purge entry. + */ + np->n_ctime = np->n_vattr.va_ctime; cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); } } else { Modified: stable/7/sys/nfsclient/nfsnode.h ============================================================================== --- stable/7/sys/nfsclient/nfsnode.h Mon Sep 20 19:58:50 2010 (r212929) +++ stable/7/sys/nfsclient/nfsnode.h Mon Sep 20 19:59:08 2010 (r212930) @@ -104,10 +104,10 @@ struct nfsnode { uid_t n_modeuid; /* credentials having mode */ time_t n_modestamp; /* mode cache timestamp */ struct timespec n_mtime; /* Prev modify time. */ - time_t n_ctime; /* Prev create time. */ - time_t n_dmtime; /* Prev dir modify time. */ + time_t n_unused0; + time_t n_unused1; int n_dmtime_ticks; /* Tick of -ve cache entry */ - time_t n_expiry; /* Lease expiry time */ + time_t n_unused2; nfsfh_t *n_fhp; /* NFS File Handle */ struct vnode *n_vnode; /* associated vnode */ struct vnode *n_dvp; /* parent vnode */ @@ -135,6 +135,8 @@ struct nfsnode { int n_directio_opens; int n_directio_asyncwr; struct nfs_attrcache_timestamp n_unused; + struct timespec n_ctime; /* Prev create time. */ + struct timespec n_dmtime; /* Prev dir modify time. */ }; #define n_atim n_un1.nf_atim
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201009201959.o8KJx8aI065841>