diff options
author | pjd <pjd@FreeBSD.org> | 2007-04-13 08:42:01 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2007-04-13 08:42:01 +0000 |
commit | aa9e6582b9f35c791921194962760619cfb2032c (patch) | |
tree | 043716f1e020704e5ae95be38a4577907b4bcafa /sys/cddl | |
parent | e140c1e4f16396661dc38b9dbc4ac9e2400b757d (diff) | |
download | FreeBSD-src-aa9e6582b9f35c791921194962760619cfb2032c.zip FreeBSD-src-aa9e6582b9f35c791921194962760619cfb2032c.tar.gz |
Fix vnodes starvation caused by DNLC (ZFS name cache):
- Tune number of namecache entires better (based on desiredvnodes).
- Handle vfs_lowvnodes event by releasing requested number of name cache
entries, but no less than 5%.
Reported by: simokawa
Diffstat (limited to 'sys/cddl')
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/dnlc.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/dnlc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/dnlc.c index 48daf36..a62e542 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/dnlc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/dnlc.c @@ -53,6 +53,7 @@ #include <sys/taskq.h> #include <sys/kernel.h> #include <sys/sysctl.h> +#include <sys/eventhandler.h> #include <vm/vm.h> #include <vm/vm_page.h> @@ -285,8 +286,10 @@ vnode_t negative_cache_vnode; static ncache_t *dnlc_get(uchar_t namlen); static ncache_t *dnlc_search(vnode_t *dp, char *name, uchar_t namlen, int hash); static void do_dnlc_reduce_cache(void *); +static void dnlc_lowvnodes(void *arg __unused, int nvnodes); static kstat_t *dnlc_ksp = NULL; +static eventhandler_tag dnlc_event_lowvnodes = NULL; /* * Initialize the directory cache. @@ -305,7 +308,7 @@ dnlc_init(void *arg __unused) #if 0 dnlc_nentries_low_water = 4 * (v.v_proc + maxusers) + 320; #else - dnlc_nentries_low_water = vm_kmem_size / 20480; + dnlc_nentries_low_water = (desiredvnodes * 49) / 100; #endif ncsize = dnlc_nentries_low_water + (dnlc_nentries_low_water / dnlc_low_water_divisor); @@ -363,6 +366,9 @@ dnlc_init(void *arg __unused) dnlc_ksp->ks_data = (void *) &ncs; kstat_install(dnlc_ksp); } + + dnlc_event_lowvnodes = EVENTHANDLER_REGISTER(vfs_lowvnodes, + dnlc_lowvnodes, NULL, EVENTHANDLER_PRI_FIRST); } static void @@ -371,6 +377,9 @@ dnlc_fini(void *arg __unused) nc_hash_t *hp; int i; + if (dnlc_event_lowvnodes != NULL) + EVENTHANDLER_DEREGISTER(vfs_lowvnodes, dnlc_event_lowvnodes); + if (dnlc_ksp != NULL) { kstat_delete(dnlc_ksp); dnlc_ksp = NULL; @@ -820,5 +829,15 @@ found: dnlc_reduce_idle = 1; } +static void +dnlc_lowvnodes(void *arg __unused, int nvnodes) +{ + + nvnodes /= ncsize_onepercent; + /* Free no less than 5%. */ + nvnodes = nvnodes < 5 * ncsize_onepercent ? 5 * ncsize_onepercent : nvnodes; + dnlc_reduce_cache((void *)(intptr_t)nvnodes); +} + SYSINIT(dnlc, SI_SUB_DRIVERS, SI_ORDER_ANY, dnlc_init, NULL); SYSUNINIT(dnlc, SI_SUB_DRIVERS, SI_ORDER_ANY, dnlc_fini, NULL); |