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
_______________________________________________
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