From owner-svn-src-stable@FreeBSD.ORG Mon Sep 20 19:58:51 2010 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4C3BD106566B; Mon, 20 Sep 2010 19:58:51 +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 39ACF8FC17; Mon, 20 Sep 2010 19:58:51 +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 o8KJwpqZ065799; Mon, 20 Sep 2010 19:58:51 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o8KJwpC8065793; Mon, 20 Sep 2010 19:58:51 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201009201958.o8KJwpC8065793@svn.freebsd.org> From: John Baldwin Date: Mon, 20 Sep 2010 19:58:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212929 - in stable/8/sys: fs/nfsclient nfsclient X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 20 Sep 2010 19:58:51 -0000 Author: jhb Date: Mon Sep 20 19:58:50 2010 New Revision: 212929 URL: http://svn.freebsd.org/changeset/base/212929 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/8/sys/fs/nfsclient/nfs_clrpcops.c stable/8/sys/fs/nfsclient/nfs_clvnops.c stable/8/sys/fs/nfsclient/nfsnode.h stable/8/sys/nfsclient/nfs_vnops.c stable/8/sys/nfsclient/nfsnode.h Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/fs/nfsclient/nfs_clrpcops.c ============================================================================== --- stable/8/sys/fs/nfsclient/nfs_clrpcops.c Mon Sep 20 19:47:58 2010 (r212928) +++ stable/8/sys/fs/nfsclient/nfs_clrpcops.c Mon Sep 20 19:58:50 2010 (r212929) @@ -3300,8 +3300,7 @@ nfsrpc_readdirplus(vnode_t vp, struct ui ndp->ni_vp = newvp; NFSCNHASH(cnp, HASHINIT); if (cnp->cn_namelen <= NCHNAMLEN) { - np->n_ctime = - np->n_vattr.na_ctime.tv_sec; + np->n_ctime = np->n_vattr.na_ctime; cache_enter(ndp->ni_dvp,ndp->ni_vp,cnp); } if (unlocknewvp) Modified: stable/8/sys/fs/nfsclient/nfs_clvnops.c ============================================================================== --- stable/8/sys/fs/nfsclient/nfs_clvnops.c Mon Sep 20 19:47:58 2010 (r212928) +++ stable/8/sys/fs/nfsclient/nfs_clvnops.c Mon Sep 20 19:58:50 2010 (r212929) @@ -999,7 +999,7 @@ nfs_lookup(struct vop_lookup_args *ap) struct nfsfh *nfhp; struct nfsvattr dnfsva, nfsva; struct vattr vattr; - time_t dmtime; + struct timespec dmtime; *vpp = NULLVP; if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) && @@ -1049,7 +1049,7 @@ nfs_lookup(struct vop_lookup_args *ap) } if (nfscl_nodeleg(newvp, 0) == 0 || (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 && - vattr.va_ctime.tv_sec == newnp->n_ctime)) { + timespeccmp(&vattr.va_ctime, &newnp->n_ctime, ==))) { NFSINCRGLOBAL(newnfsstats.lookupcache_hits); if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) @@ -1076,13 +1076,13 @@ nfs_lookup(struct vop_lookup_args *ap) if ((u_int)(ticks - np->n_dmtime_ticks) < (nmp->nm_negnametimeo * hz) && VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 && - vattr.va_mtime.tv_sec == np->n_dmtime) { + timespeccmp(&vattr.va_mtime, &np->n_dmtime, ==)) { NFSINCRGLOBAL(newnfsstats.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); } @@ -1097,7 +1097,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.na_mtime.tv_sec; + dmtime = np->n_vattr.na_mtime; error = 0; newvp = NULLVP; NFSINCRGLOBAL(newnfsstats.lookupcache_misses); @@ -1150,8 +1150,8 @@ nfs_lookup(struct vop_lookup_args *ap) * 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; } @@ -1252,7 +1252,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.na_vattr.va_ctime.tv_sec; + np->n_ctime = np->n_vattr.na_vattr.va_ctime; cache_enter(dvp, newvp, cnp); } *vpp = newvp; Modified: stable/8/sys/fs/nfsclient/nfsnode.h ============================================================================== --- stable/8/sys/fs/nfsclient/nfsnode.h Mon Sep 20 19:47:58 2010 (r212928) +++ stable/8/sys/fs/nfsclient/nfsnode.h Mon Sep 20 19:58:50 2010 (r212929) @@ -102,10 +102,10 @@ struct nfsnode { time_t n_attrstamp; /* Attr. cache timestamp */ struct nfs_accesscache n_accesscache[NFS_ACCESSCACHESIZE]; 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; struct nfsfh *n_fhp; /* NFS File Handle */ struct vnode *n_vnode; /* associated vnode */ struct vnode *n_dvp; /* parent vnode */ @@ -131,6 +131,8 @@ struct nfsnode { struct nfs_attrcache_timestamp n_unused; u_int64_t n_change; /* old Change attribute */ struct nfsv4node *n_v4; /* extra V4 stuff */ + struct timespec n_ctime; /* Prev create time. */ + struct timespec n_dmtime; /* Prev dir modify time. */ }; #define n_atim n_un1.nf_atim Modified: stable/8/sys/nfsclient/nfs_vnops.c ============================================================================== --- stable/8/sys/nfsclient/nfs_vnops.c Mon Sep 20 19:47:58 2010 (r212928) +++ stable/8/sys/nfsclient/nfs_vnops.c Mon Sep 20 19:58:50 2010 (r212929) @@ -916,7 +916,7 @@ nfs_lookup(struct vop_lookup_args *ap) struct vnode **vpp = ap->a_vpp; struct mount *mp = dvp->v_mount; struct vattr vattr; - time_t dmtime; + struct timespec dmtime; int flags = cnp->cn_flags; struct vnode *newvp; struct nfsmount *nmp; @@ -970,7 +970,7 @@ nfs_lookup(struct vop_lookup_args *ap) mtx_unlock(&newnp->n_mtx); } if (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 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)) @@ -997,13 +997,13 @@ nfs_lookup(struct vop_lookup_args *ap) if ((u_int)(ticks - np->n_dmtime_ticks) < (nmp->nm_negnametimeo * hz) && VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 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); } @@ -1018,7 +1018,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++; @@ -1137,7 +1137,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; @@ -1183,8 +1183,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; } @@ -2657,8 +2657,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/8/sys/nfsclient/nfsnode.h ============================================================================== --- stable/8/sys/nfsclient/nfsnode.h Mon Sep 20 19:47:58 2010 (r212928) +++ stable/8/sys/nfsclient/nfsnode.h Mon Sep 20 19:58:50 2010 (r212929) @@ -108,10 +108,10 @@ struct nfsnode { time_t n_attrstamp; /* Attr. cache timestamp */ struct nfs_accesscache n_accesscache[NFS_ACCESSCACHESIZE]; 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 */ @@ -137,6 +137,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