summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2010-09-07 14:29:45 +0000
committerjhb <jhb@FreeBSD.org>2010-09-07 14:29:45 +0000
commit0f939dc96e7e1aec8c86f3cad8891d9e3c0ffe1b (patch)
tree0a023b40473f508ea26e1ba4b2b9dfcfc657c1a4 /sys/fs
parentb33adc1bec8364e4d51804534d77029137887f5d (diff)
downloadFreeBSD-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.c3
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c16
-rw-r--r--sys/fs/nfsclient/nfsnode.h5
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 */
OpenPOWER on IntegriCloud