Here is the latest patch for -current.  vmiodirenable is turned on by
    default, the cache purge code is enabled based on vmiodirenable, and
    I added a new sysctl called nameileafonly which defaults to ON (1).
    The old cache_purgeleafdirs() stuff is #if 0'd out.

    nameileafonly vmiodirenable action
        1               1       (DEFAULT) purge leaf dirs on vnode reclaim
        0               1       purge any dir on vnode reclaim
        1               0       purge leaf dirs on vnode reclaim
        0               0       do not purge dirs on vnode reclaim
        -1              0       puger any dir on vnode reclaim

Index: sys/vnode.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/vnode.h,v
retrieving revision 1.157
diff -u -r1.157 vnode.h
--- sys/vnode.h 2001/09/13 22:52:42     1.157
+++ sys/vnode.h 2001/09/23 21:17:23
@@ -559,7 +559,7 @@
            struct componentname *cnp));
 void   cache_purge __P((struct vnode *vp));
 void   cache_purgevfs __P((struct mount *mp));
-void   cache_purgeleafdirs __P((int ndir));
+int    cache_leaf_test __P((struct vnode *vp));
 void   cvtstat __P((struct stat *st, struct ostat *ost));
 void   cvtnstat __P((struct stat *sb, struct nstat *nsb));
 int    getnewvnode __P((enum vtagtype tag,
Index: kern/vfs_bio.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v
retrieving revision 1.288
diff -u -r1.288 vfs_bio.c
--- kern/vfs_bio.c      2001/09/12 08:37:46     1.288
+++ kern/vfs_bio.c      2001/09/23 21:13:02
@@ -90,7 +90,7 @@
  * but the code is intricate enough already.
  */
 vm_page_t bogus_page;
-int vmiodirenable = FALSE;
+int vmiodirenable = TRUE;
 int runningbufspace;
 static vm_offset_t bogus_offset;
 
Index: kern/vfs_cache.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_cache.c,v
retrieving revision 1.61
diff -u -r1.61 vfs_cache.c
--- kern/vfs_cache.c    2001/09/12 08:37:46     1.61
+++ kern/vfs_cache.c    2001/09/23 21:17:47
@@ -101,8 +101,10 @@
 SYSCTL_ULONG(_debug, OID_AUTO, numcache, CTLFLAG_RD, &numcache, 0, "");
 static u_long  numcachehv;             /* number of cache entries with vnodes held */
 SYSCTL_ULONG(_debug, OID_AUTO, numcachehv, CTLFLAG_RD, &numcachehv, 0, "");
+#if 0
 static u_long  numcachepl;             /* number of cache purge for leaf entries */
 SYSCTL_ULONG(_debug, OID_AUTO, numcachepl, CTLFLAG_RD, &numcachepl, 0, "");
+#endif
 struct nchstats nchstats;              /* cache effectiveness statistics */
 
 static int     doingcache = 1;         /* 1 => enable the cache */
@@ -247,6 +249,31 @@
 }
 
 /*
+ * cache_leaf_test()
+ * 
+ *      Test whether this (directory) vnode's namei cache entry contains
+ *      subdirectories or not.  Used to determine whether the directory is
+ *      a leaf in the namei cache or not.  Note: the directory may still   
+ *      contain files in the namei cache.
+ *
+ *      Returns 0 if the directory is a leaf, -1 if it isn't.
+ */
+int
+cache_leaf_test(struct vnode *vp)
+{
+       struct namecache *ncpc;
+
+       for (ncpc = LIST_FIRST(&vp->v_cache_src);
+            ncpc != NULL;
+            ncpc = LIST_NEXT(ncpc, nc_src)
+       ) {
+               if (ncpc->nc_vp != NULL && ncpc->nc_vp->v_type == VDIR)
+                       return(0);
+       }
+       return(-1);
+}
+
+/*
  * Lookup an entry in the cache
  *
  * We don't do this if the segment name is long, simply so the cache
@@ -499,6 +526,8 @@
        }
 }
 
+#if 0
+
 /*
  * Flush all dirctory entries with no child directories held in
  * the cache.
@@ -554,6 +583,8 @@
        }
        numcachepl++;
 }
+
+#endif
 
 /*
  * Perform canonical checks and cache lookup and pass on to filesystem
Index: kern/vfs_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.319
diff -u -r1.319 vfs_subr.c
--- kern/vfs_subr.c     2001/09/12 08:37:47     1.319
+++ kern/vfs_subr.c     2001/09/23 21:19:26
@@ -110,6 +110,8 @@
 /* Number of vnodes in the free list. */
 static u_long freevnodes = 0;
 SYSCTL_LONG(_debug, OID_AUTO, freevnodes, CTLFLAG_RD, &freevnodes, 0, "");
+
+#if 0
 /* Number of vnode allocation. */
 static u_long vnodeallocs = 0;
 SYSCTL_LONG(_debug, OID_AUTO, vnodeallocs, CTLFLAG_RD, &vnodeallocs, 0, "");
@@ -125,6 +127,7 @@
 /* Number of vnodes attempted to recycle at a time. */
 static u_long vnoderecyclenumber = 3000;
 SYSCTL_LONG(_debug, OID_AUTO, vnoderecyclenumber, CTLFLAG_RW, &vnoderecyclenumber, 0, 
"");
+#endif
 
 /*
  * Various variables used for debugging the new implementation of
@@ -142,6 +145,8 @@
 /* Set to 0 for old insertion-sort based reassignbuf, 1 for modern method. */
 static int reassignbufmethod = 1;
 SYSCTL_INT(_vfs, OID_AUTO, reassignbufmethod, CTLFLAG_RW, &reassignbufmethod, 0, "");
+static int nameileafonly = 1;
+SYSCTL_INT(_vfs, OID_AUTO, nameileafonly, CTLFLAG_RW, &nameileafonly, 0, "");
 
 #ifdef ENABLE_VFS_IOOPT
 /* See NOTES for a description of this setting. */
@@ -556,15 +561,46 @@
                 * Don't recycle if active in the namecache or
                 * if it still has cached pages or we cannot get
                 * its interlock.
+                *
+                * XXX the namei cache can hold onto vnodes too long,
+                * causing us to run out of MALLOC space.  Instead, we 
+                * should make path lookups requeue any vnodes on the free
+                * list.
                 */
-               if (LIST_FIRST(&vp->v_cache_src) != NULL ||
-                   (VOP_GETVOBJECT(vp, &object) == 0 &&
+               if ((VOP_GETVOBJECT(vp, &object) == 0 &&
                     (object->resident_page_count || object->ref_count)) ||
                    !mtx_trylock(&vp->v_interlock)) {
                        TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
                        vp = NULL;
                        continue;
                }
+               if (LIST_FIRST(&vp->v_cache_src)) {
+                       /*
+                        * If nameileafonly is set, do not throw
+                        * away directory vnodes unless they are
+                        * leaf nodes in the namecache.
+                        *
+                        * If nameileafonly is not set then throw-aways
+                        * are based on vmiodirenable.  If
+                        * vmiodirenable is turned off we do not throw
+                        * away directory vnodes active in the
+                        * namecache.  The (nameileafonly < 0) test
+                        * is for further debugging only.
+                        */
+                       if (nameileafonly > 0) {
+                               if (cache_leaf_test(vp) == 0) {
+                                       mtx_unlock(&vp->v_interlock);
+                                       vp = NULL;
+                                       continue;
+                               }
+                       } else if (nameileafonly < 0 ||
+                                   vmiodirenable == 0) {
+                               mtx_unlock(&vp->v_interlock);
+                               vp = NULL;
+                               continue;
+                       }
+               }
+
                /*
                 * Skip over it if its filesystem is being suspended.
                 */
@@ -636,6 +672,7 @@
 
        vfs_object_create(vp, td, td->td_proc->p_ucred);
 
+#if 0
        vnodeallocs++;
        if (vnodeallocs % vnoderecycleperiod == 0 &&
            freevnodes < vnoderecycleminfreevn &&
@@ -643,6 +680,7 @@
                /* Recycle vnodes. */
                cache_purgeleafdirs(vnoderecyclenumber);
        }
+#endif
 
        return (0);
 }

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to