kernel - Fix rare race in namecache
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 18 Feb 2013 17:50:22 +0000 (09:50 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 18 Feb 2013 17:50:22 +0000 (09:50 -0800)
* Fix a rare race in _cache_cleanneg() where the ncp being cleaned up is
  resolved during the moment between where _cache_cleanneg() accesses it
  prior to locking and removing it.

* _cache_cleanneg() needed to re-check that the ncp was still on the
  negative cache list.

Reported-by: marino
sys/kern/vfs_cache.c

index 19b44be..339c6d2 100644 (file)
@@ -2845,10 +2845,21 @@ _cache_cleanneg(int count)
                TAILQ_INSERT_TAIL(&ncneglist, ncp, nc_vnode);
                _cache_hold(ncp);
                spin_unlock(&ncspin);
+
+               /*
+                * This can race, so we must re-check that the ncp
+                * is on the ncneglist after successfully locking it.
+                */
                if (_cache_lock_special(ncp) == 0) {
-                       ncp = cache_zap(ncp, 1);
-                       if (ncp)
-                               _cache_drop(ncp);
+                       if (ncp->nc_vp == NULL &&
+                           (ncp->nc_flag & NCF_UNRESOLVED) == 0) {
+                               ncp = cache_zap(ncp, 1);
+                               if (ncp)
+                                       _cache_drop(ncp);
+                       } else {
+                               kprintf("cache_cleanneg: race avoided\n");
+                               _cache_unlock(ncp);
+                       }
                } else {
                        _cache_drop(ncp);
                }