Author: mjg
Date: Tue Nov 15 03:38:05 2016
New Revision: 308665
URL: https://svnweb.freebsd.org/changeset/base/308665

Log:
  cache: fix a race between entry removal and demotion
  
  The negative list shrinker can demote an entry with only hotlist + neglist
  locks held. On the other hand entry removal possibly sets the NCF_DVDROP
  without aformentioned locks held prior to detaching it from the respective
  netlist., which can lose the update made by the shrinker.
  
  Reported and tested by:       truckman

Modified:
  head/sys/kern/vfs_cache.c

Modified: head/sys/kern/vfs_cache.c
==============================================================================
--- head/sys/kern/vfs_cache.c   Tue Nov 15 02:36:12 2016        (r308664)
+++ head/sys/kern/vfs_cache.c   Tue Nov 15 03:38:05 2016        (r308665)
@@ -868,6 +868,13 @@ cache_zap_locked(struct namecache *ncp, 
                    nc_get_name(ncp), ncp->nc_neghits);
        }
        LIST_REMOVE(ncp, nc_hash);
+       if (!(ncp->nc_flag & NCF_NEGATIVE)) {
+               TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst);
+               if (ncp == ncp->nc_vp->v_cache_dd)
+                       ncp->nc_vp->v_cache_dd = NULL;
+       } else {
+               cache_negative_remove(ncp, neg_locked);
+       }
        if (ncp->nc_flag & NCF_ISDOTDOT) {
                if (ncp == ncp->nc_dvp->v_cache_dd)
                        ncp->nc_dvp->v_cache_dd = NULL;
@@ -878,13 +885,6 @@ cache_zap_locked(struct namecache *ncp, 
                        atomic_subtract_rel_long(&numcachehv, 1);
                }
        }
-       if (!(ncp->nc_flag & NCF_NEGATIVE)) {
-               TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst);
-               if (ncp == ncp->nc_vp->v_cache_dd)
-                       ncp->nc_vp->v_cache_dd = NULL;
-       } else {
-               cache_negative_remove(ncp, neg_locked);
-       }
        atomic_subtract_rel_long(&numcache, 1);
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to