summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/uma.h12
-rw-r--r--sys/vm/uma_core.c34
-rw-r--r--sys/vm/uma_int.h4
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.
OpenPOWER on IntegriCloud