Author: jhb
Date: Tue Sep  7 14:29:45 2010
New Revision: 212293
URL: http://svn.freebsd.org/changeset/base/212293

Log:
  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

Modified:
  head/sys/fs/nfsclient/nfs_clrpcops.c
  head/sys/fs/nfsclient/nfs_clvnops.c
  head/sys/fs/nfsclient/nfsnode.h
  head/sys/nfsclient/nfs_vnops.c
  head/sys/nfsclient/nfsnode.h

Modified: head/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clrpcops.c        Tue Sep  7 13:50:02 2010        
(r212292)
+++ head/sys/fs/nfsclient/nfs_clrpcops.c        Tue Sep  7 14:29:45 2010        
(r212293)
@@ -3293,8 +3293,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: head/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clvnops.c Tue Sep  7 13:50:02 2010        
(r212292)
+++ head/sys/fs/nfsclient/nfs_clvnops.c Tue Sep  7 14:29:45 2010        
(r212293)
@@ -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;

Modified: head/sys/fs/nfsclient/nfsnode.h
==============================================================================
--- head/sys/fs/nfsclient/nfsnode.h     Tue Sep  7 13:50:02 2010        
(r212292)
+++ head/sys/fs/nfsclient/nfsnode.h     Tue Sep  7 14:29:45 2010        
(r212293)
@@ -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 */

Modified: head/sys/nfsclient/nfs_vnops.c
==============================================================================
--- head/sys/nfsclient/nfs_vnops.c      Tue Sep  7 13:50:02 2010        
(r212292)
+++ head/sys/nfsclient/nfs_vnops.c      Tue Sep  7 14:29:45 2010        
(r212293)
@@ -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: head/sys/nfsclient/nfsnode.h
==============================================================================
--- head/sys/nfsclient/nfsnode.h        Tue Sep  7 13:50:02 2010        
(r212292)
+++ head/sys/nfsclient/nfsnode.h        Tue Sep  7 14:29:45 2010        
(r212293)
@@ -102,10 +102,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 */
        nfsfh_t                 *n_fhp;         /* NFS File Handle */
        struct vnode            *n_vnode;       /* associated vnode */
        struct vnode            *n_dvp;         /* parent vnode */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to