summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2012-12-07 22:27:13 +0000
committerpjd <pjd@FreeBSD.org>2012-12-07 22:27:13 +0000
commita585ca9ec8ad3532db09d36b1fda6a32fd732cc9 (patch)
tree3471176b32a524b1295b426d984e14fabbb45a3b /sys/vm
parent0ae3a2ffee9d425fa3561bcd043c229dd7a5c96d (diff)
downloadFreeBSD-src-a585ca9ec8ad3532db09d36b1fda6a32fd732cc9.zip
FreeBSD-src-a585ca9ec8ad3532db09d36b1fda6a32fd732cc9.tar.gz
Implemented uma_zone_set_warning(9) function that sets a warning, which
will be printed once the given zone becomes full and cannot allocate an item. The warning will not be printed more often than every five minutes. All UMA warnings can be globally turned off by setting sysctl/tunable vm.zone_warnings to 0. Discussed on: arch Obtained from: WHEEL Systems MFC after: 2 weeks
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