diff options
-rw-r--r-- | sys/kern/vfs_cache.c | 31 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 97 | ||||
-rw-r--r-- | sys/sys/vnode.h | 2 |
3 files changed, 100 insertions, 30 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 9483b9b..8301821 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -101,8 +101,10 @@ static u_long numcache; /* number of cache entries allocated */ 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_zap(ncp) } /* + * 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(-1); + } + return(0); +} + +/* * 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 @@ cache_purgevfs(mp) } } +#if 0 + /* * Flush all dirctory entries with no child directories held in * the cache. @@ -555,6 +584,8 @@ cache_purgeleafdirs(ndir) numcachepl++; } +#endif + /* * Perform canonical checks and cache lookup and pass on to filesystem * through the vop_cachedlookup only if needed. diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 8c67662..8fdd423 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -110,6 +110,8 @@ SYSCTL_LONG(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, &wantfreevnodes, 0, "" /* 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 @@ SYSCTL_LONG(_debug, OID_AUTO, vnoderecycleminfreevn, CTLFLAG_RW, &vnoderecyclemi /* 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 @@ SYSCTL_INT(_vfs, OID_AUTO, reassignbufsortbad, CTLFLAG_RW, &reassignbufsortbad, /* 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 = 0; +SYSCTL_INT(_vfs, OID_AUTO, nameileafonly, CTLFLAG_RW, &nameileafonly, 0, ""); #ifdef ENABLE_VFS_IOOPT /* See NOTES for a description of this setting. */ @@ -238,6 +243,9 @@ SYSCTL_INT(_debug, OID_AUTO, rush_requests, CTLFLAG_RW, &stat_rush_requests, 0, int desiredvnodes; SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RW, &desiredvnodes, 0, "Maximum number of vnodes"); +static int minvnodes; +SYSCTL_INT(_kern, KERN_MAXVNODES, minvnodes, CTLFLAG_RW, + &minvnodes, 0, "Minimum number of vnodes"); /* * Initialize the vnode management data structures. @@ -247,6 +255,7 @@ vntblinit(void *dummy __unused) { desiredvnodes = maxproc + cnt.v_page_count / 4; + minvnodes = desiredvnodes / 4; mtx_init(&mountlist_mtx, "mountlist", MTX_DEF); mtx_init(&mntvnode_mtx, "mntvnode", MTX_DEF); mtx_init(&mntid_mtx, "mntid", MTX_DEF); @@ -539,40 +548,68 @@ getnewvnode(tag, mp, vops, vpp) s = splbio(); mtx_lock(&vnode_free_list_mtx); - if (wantfreevnodes && freevnodes < wantfreevnodes) { - vp = NULL; - } else if (!wantfreevnodes && freevnodes <= desiredvnodes) { - /* - * XXX: this is only here to be backwards compatible - */ + if (freevnodes < wantfreevnodes) { vp = NULL; - } else for (count = 0; count < freevnodes; count++) { - vp = TAILQ_FIRST(&vnode_free_list); - if (vp == NULL || vp->v_usecount) - panic("getnewvnode: free vnode isn't"); - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + } else if (numvnodes >= minvnodes) { + for (count = 0; count < freevnodes; count++) { + vp = TAILQ_FIRST(&vnode_free_list); + if (vp == NULL || vp->v_usecount) + panic("getnewvnode: free vnode isn't"); + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - /* - * Don't recycle if active in the namecache or - * if it still has cached pages or we cannot get - * its interlock. - */ - if (LIST_FIRST(&vp->v_cache_src) != NULL || - (VOP_GETVOBJECT(vp, &object) == 0 && - (object->resident_page_count || object->ref_count)) || - !mtx_trylock(&vp->v_interlock)) { + /* + * Don't recycle if we still have cached pages or if + * we cannot get the interlock. + */ + 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)) { + /* + * note: nameileafonly sysctl is temporary, + * for debugging only, and will eventually be + * removed. + */ + if (nameileafonly > 0) { + /* + * Do not reuse namei-cached directory + * vnodes that have cached + * subdirectories. + */ + if (cache_leaf_test(vp) < 0) { + mtx_unlock(&vp->v_interlock); + vp = NULL; + continue; + } + } else if (nameileafonly < 0 || + vmiodirenable == 0) { + /* + * Do not reuse namei-cached directory + * vnodes if nameileafonly is -1 or + * if VMIO backing for directories is + * turned off (otherwise we reuse them + * too quickly). + */ + mtx_unlock(&vp->v_interlock); + vp = NULL; + continue; + } + } + /* + * Skip over it if its filesystem is being suspended. + */ + if (vn_start_write(vp, &vnmp, V_NOWAIT) == 0) + break; + mtx_unlock(&vp->v_interlock); TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); vp = NULL; - continue; } - /* - * Skip over it if its filesystem is being suspended. - */ - if (vn_start_write(vp, &vnmp, V_NOWAIT) == 0) - break; - mtx_unlock(&vp->v_interlock); - TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); - vp = NULL; } if (vp) { vp->v_flag |= VDOOMED; @@ -636,6 +673,7 @@ getnewvnode(tag, mp, vops, vpp) vfs_object_create(vp, td, td->td_proc->p_ucred); +#if 0 vnodeallocs++; if (vnodeallocs % vnoderecycleperiod == 0 && freevnodes < vnoderecycleminfreevn && @@ -643,6 +681,7 @@ getnewvnode(tag, mp, vops, vpp) /* Recycle vnodes. */ cache_purgeleafdirs(vnoderecyclenumber); } +#endif return (0); } diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index f3d0995..58221812 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -559,7 +559,7 @@ int cache_lookup __P((struct vnode *dvp, struct vnode **vpp, 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, |