From owner-svn-src-stable-7@FreeBSD.ORG Mon Sep 20 19:59:09 2010 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0A77B1065745; Mon, 20 Sep 2010 19:59:09 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id EC9F38FC1C; Mon, 20 Sep 2010 19:59:08 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o8KJx8rQ065845; Mon, 20 Sep 2010 19:59:08 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o8KJx8aI065841; Mon, 20 Sep 2010 19:59:08 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201009201959.o8KJx8aI065841@svn.freebsd.org> From: John Baldwin Date: Mon, 20 Sep 2010 19:59:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212930 - in stable/7/sys: nfs4client nfsclient X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 20 Sep 2010 19:59:09 -0000 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