diff options
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/uma.h | 12 | ||||
-rw-r--r-- | sys/vm/uma_core.c | 34 | ||||
-rw-r--r-- | sys/vm/uma_int.h | 4 |
3 files changed, 49 insertions, 1 deletions
diff --git a/sys/vm/uma.h b/sys/vm/uma.h index 8a12fe1..28d5ee0 100644 --- a/sys/vm/uma.h +++ b/sys/vm/uma.h @@ -476,6 +476,18 @@ int uma_zone_set_max(uma_zone_t zone, int nitems); int uma_zone_get_max(uma_zone_t zone); /* + * Sets a warning to be printed when limit is reached + * + * Arguments: + * zone The zone we will warn about + * warning Warning content + * + * Returns: + * Nothing + */ +void uma_zone_set_warning(uma_zone_t zone, const char *warning); + +/* * Obtains the approximate current number of items allocated from a zone * * Arguments: diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index e58a86f..36a149e 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -265,6 +265,11 @@ SYSCTL_PROC(_vm, OID_AUTO, zone_count, CTLFLAG_RD|CTLTYPE_INT, SYSCTL_PROC(_vm, OID_AUTO, zone_stats, CTLFLAG_RD|CTLTYPE_STRUCT, 0, 0, sysctl_vm_zone_stats, "s,struct uma_type_header", "Zone Stats"); +static int zone_warnings = 1; +TUNABLE_INT("vm.zone_warnings", &zone_warnings); +SYSCTL_INT(_vm, OID_AUTO, zone_warnings, CTLFLAG_RW, &zone_warnings, 0, + "Warn when UMA zones becomes full"); + /* * This routine checks to see whether or not it's safe to enable buckets. */ @@ -363,6 +368,18 @@ bucket_zone_drain(void) zone_drain(ubz->ubz_zone); } +static void +zone_log_warning(uma_zone_t zone) +{ + static const struct timeval warninterval = { 300, 0 }; + + if (!zone_warnings || zone->uz_warning == NULL) + return; + + if (ratecheck(&zone->uz_ratecheck, &warninterval)) + printf("[zone: %s] %s\n", zone->uz_name, zone->uz_warning); +} + static inline uma_keg_t zone_first_keg(uma_zone_t zone) { @@ -1432,6 +1449,8 @@ zone_ctor(void *mem, int size, void *udata, int flags) zone->uz_sleeps = 0; zone->uz_fills = zone->uz_count = 0; zone->uz_flags = 0; + zone->uz_warning = NULL; + timevalclear(&zone->uz_ratecheck); keg = arg->keg; if (arg->flags & UMA_ZONE_SECONDARY) { @@ -2191,8 +2210,10 @@ keg_fetch_slab(uma_keg_t keg, uma_zone_t zone, int flags) * If this is not a multi-zone, set the FULL bit. * Otherwise slab_multi() takes care of it. */ - if ((zone->uz_flags & UMA_ZFLAG_MULTI) == 0) + if ((zone->uz_flags & UMA_ZFLAG_MULTI) == 0) { zone->uz_flags |= UMA_ZFLAG_FULL; + zone_log_warning(zone); + } if (flags & M_NOWAIT) break; zone->uz_sleeps++; @@ -2339,6 +2360,7 @@ zone_fetch_slab_multi(uma_zone_t zone, uma_keg_t last, int rflags) if (full && !empty) { zone->uz_flags |= UMA_ZFLAG_FULL; zone->uz_sleeps++; + zone_log_warning(zone); msleep(zone, zone->uz_lock, PVM, "zonelimit", hz/100); zone->uz_flags &= ~UMA_ZFLAG_FULL; continue; @@ -2881,6 +2903,16 @@ uma_zone_get_max(uma_zone_t zone) } /* See uma.h */ +void +uma_zone_set_warning(uma_zone_t zone, const char *warning) +{ + + ZONE_LOCK(zone); + zone->uz_warning = warning; + ZONE_UNLOCK(zone); +} + +/* See uma.h */ int uma_zone_get_cur(uma_zone_t zone) { diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h index d9d5394..71788ea 100644 --- a/sys/vm/uma_int.h +++ b/sys/vm/uma_int.h @@ -331,6 +331,10 @@ struct uma_zone { uint16_t uz_fills; /* Outstanding bucket fills */ uint16_t uz_count; /* Highest value ub_ptr can have */ + /* The next three fields are used to print a rate-limited warnings. */ + const char *uz_warning; /* Warning to print on failure */ + struct timeval uz_ratecheck; /* Warnings rate-limiting */ + /* * This HAS to be the last item because we adjust the zone size * based on NCPU and then allocate the space for the zones. |