diff options
author | jhb <jhb@FreeBSD.org> | 2010-09-07 14:29:45 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2010-09-07 14:29:45 +0000 |
commit | 0f939dc96e7e1aec8c86f3cad8891d9e3c0ffe1b (patch) | |
tree | 0a023b40473f508ea26e1ba4b2b9dfcfc657c1a4 /sys/fs | |
parent | b33adc1bec8364e4d51804534d77029137887f5d (diff) | |
download | FreeBSD-src-0f939dc96e7e1aec8c86f3cad8891d9e3c0ffe1b.zip FreeBSD-src-0f939dc96e7e1aec8c86f3cad8891d9e3c0ffe1b.tar.gz |
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. While here,
remove the 'n_expiry' field as it is no longer used.
Reviewed by: rmacklem
MFC after: 1 week
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/nfsclient/nfs_clrpcops.c | 3 | ||||
-rw-r--r-- | sys/fs/nfsclient/nfs_clvnops.c | 16 | ||||
-rw-r--r-- | sys/fs/nfsclient/nfsnode.h | 5 |
3 files changed, 11 insertions, 13 deletions
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index 89fd0a2..2512ad4 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -3293,8 +3293,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep, 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) diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 289c686..1e4e8a6 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -988,7 +988,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) && @@ -1038,7 +1038,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)) @@ -1065,13 +1065,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); } @@ -1086,7 +1086,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); @@ -1139,8 +1139,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; } @@ -1241,7 +1241,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; diff --git a/sys/fs/nfsclient/nfsnode.h b/sys/fs/nfsclient/nfsnode.h index 8bbb3bc..204b20c 100644 --- a/sys/fs/nfsclient/nfsnode.h +++ b/sys/fs/nfsclient/nfsnode.h @@ -96,10 +96,9 @@ 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. */ + struct timespec n_ctime; /* Prev create time. */ + struct timespec n_dmtime; /* Prev dir modify time. */ int n_dmtime_ticks; /* Tick of -ve cache entry */ - time_t n_expiry; /* Lease expiry time */ struct nfsfh *n_fhp; /* NFS File Handle */ struct vnode *n_vnode; /* associated vnode */ struct vnode *n_dvp; /* parent vnode */ |