Skip to contentSkip to conversation

Virq for low memory conditions, V5

PATCH In review Andres Lagar-Cavilla 3 participants 6 messages Mar 6, 2012 – Mar 7, 2012

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Virq for low memory conditions, V5

Changes from previous posting, dated Feb 29th
- Added consideration for tmem-freeable pages before firing the virq
- Added Acked-by Ian Jackson for dom0 helper demo code
- Added .gitignore rune

Changes from V3 posted Feb 28th
- lowmemd is now xen-lowmemd
- .hgignore rune added for xen-lowmemd
- User can specify zero on the command line to disable the virq altogether
- Addressed two comments from Jan Beulich
+ Better detection of no user-provided command line threshold
+ Deal with the case in which the threshold may end up being zero.

Patch 1 is hypervisor (xen/common bits), patch 2 is tools.

 xen/common/page_alloc.c  |  115 ++++++++++++++++++++++++++++++++++++
 xen/include/public/xen.h |    1 +
 .gitignore               |    1 +
 .hgignore                |    1 +
 tools/misc/Makefile      |    7 +-
 tools/misc/xen-lowmemd.c |  148 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 271 insertions(+), 2 deletions(-)
#1 lore raw

PATCH 1/1 Global virq for low memory situations

 xen/common/page_alloc.c  |  115 +++++++++++++++++++++++++++++++++++++++++++++++
 xen/include/public/xen.h |    1 +
 2 files changed, 116 insertions(+), 0 deletions(-)

When a low memory threshold on the Xen heap is reached, we fire a global dom0 virq. If someone's listening, they can free up some more memory.

The low threshold is configurable via the command line token 'low_mem_virq_limit", and defaults to 64MiB. If the user specifies zero via the command line, the virq is disabled.

We define a new virq VIRQ_ENOMEM. Potential listeners include squeezed, xenballoond, or anything else that can be fired through xencommons.

We error-check the low mem virq against initial available heap (after dom0 allocation), to avoid firing immediately.

Virq issuing is controlled by a hysteresis algorithm: when memory dips below a threshold, the virq is issued and the next virq will fire when memory shrinks another order of magnitude. The virq will not fire again in the current "band" until memory grows over the next higher order of magnitude.

xen/common/page_alloc.c +115 -0
diff -r bcfd44004568 -r 8938a0111344 xen/common/page_alloc.c
@@ -35,6 +35,7 @@
 #include <xen/perfc.h>
 #include <xen/numa.h>
 #include <xen/nodemask.h>
+#include <xen/event.h>
 #include <xen/tmem.h>
 #include <xen/tmem_xen.h>
 #include <public/sysctl.h>
@@ -300,6 +301,114 @@ static unsigned long init_node_heap(int 
     return needed;
 }
 
+/* Default to 64 MiB */
+#define DEFAULT_LOW_MEM_VIRQ    (((paddr_t) 64)   << 20)
+#define MAX_LOW_MEM_VIRQ        (((paddr_t) 1024) << 20)
+
+static paddr_t __read_mostly opt_low_mem_virq = ((paddr_t) -1);
+size_param("low_mem_virq_limit", opt_low_mem_virq);
+
+/* Thresholds to control hysteresis. In pages */
+/* When memory grows above this threshold, reset hysteresis.
+ * -1 initially to not reset until at least one virq issued. */
+static unsigned long low_mem_virq_high      = -1UL;
+/* Threshold at which we issue virq */
+static unsigned long low_mem_virq_th        = 0;
+/* Original threshold after all checks completed */
+static unsigned long low_mem_virq_orig      = 0;
+/* Order for current threshold */
+static unsigned int  low_mem_virq_th_order  = 0;
+
+/* Perform bootstrapping checks and set bounds */
+static void __init setup_low_mem_virq(void)
+{
+    unsigned int order;
+    paddr_t threshold;
+    bool_t halve = 0;
+
+    /* If the user specifies zero, then he/she doesn't want this virq
+     * to ever trigger. */
+    if ( opt_low_mem_virq == 0 )
+    {
+        low_mem_virq_th = -1UL;
+        return;
+    }
+
+    /* If the user did not specify a knob, remember that */
+    if ( opt_low_mem_virq == ((paddr_t) -1) )
+    {
+        halve = 1;
+        threshold = DEFAULT_LOW_MEM_VIRQ;
+    } else
+        threshold = opt_low_mem_virq;
+
+    /* Dom0 has already been allocated by now. So check we won't be
+     * complaining immediately with whatever's left of the heap. */
+    threshold = min(threshold,
+                    ((paddr_t) total_avail_pages) << PAGE_SHIFT);
+
+    /* Then, cap to some predefined maximum */
+    threshold = min(threshold, MAX_LOW_MEM_VIRQ);
+
+    /* If the user specified no knob, and we are at the current available
+     * level, halve the threshold. */
+    if ( halve &&
+         (threshold == (((paddr_t) total_avail_pages) << PAGE_SHIFT)) )
+        threshold >>= 1;
+
+    /* Zero? Set the threshold to one page to fire immediately */
+    threshold = max(threshold, (paddr_t) PAGE_SIZE);
+
+    /* Threshold bytes -> pages */
+    low_mem_virq_th = threshold >> PAGE_SHIFT;
+
+    /* Next, round the threshold down to the next order */
+    order = get_order_from_pages(low_mem_virq_th);
+    if ( (1UL << order) > low_mem_virq_th )
+        order--;
+
+    /* Set bounds, ready to go */
+    low_mem_virq_th = low_mem_virq_orig = 1UL << order;
+    low_mem_virq_th_order = order;
+
+    printk("Initial low memory virq threshold set at 0x%lx pages.\n",
+            low_mem_virq_th);
+}
+
+static void check_low_mem_virq(void)
+{
+    unsigned long avail_pages = total_avail_pages +
+                (opt_tmem) ? tmem_freeable_pages(): 0;
+
+    if ( unlikely(avail_pages <= low_mem_virq_th) )
+    {
+        send_global_virq(VIRQ_ENOMEM);
+
+        /* Update thresholds. Next warning will be when we drop below
+         * next order. However, we wait until we grow beyond one
+         * order above us to complain again at the current order */
+        low_mem_virq_high   = 1UL << (low_mem_virq_th_order + 1);
+        if ( low_mem_virq_th_order > 0 )
+            low_mem_virq_th_order--;
+        low_mem_virq_th     = 1UL << low_mem_virq_th_order;
+        return;
+    }
+
+    if ( unlikely(avail_pages >= low_mem_virq_high) )
+    {
+        /* Reset hysteresis. Bring threshold up one order.
+         * If we are back where originally set, set high
+         * threshold to -1 to avoid further growth of
+         * virq threshold. */
+        low_mem_virq_th_order++;
+        low_mem_virq_th = 1UL << low_mem_virq_th_order;
+        if ( low_mem_virq_th == low_mem_virq_orig )
+            low_mem_virq_high = -1UL;
+        else
+            low_mem_virq_high = 1UL << (low_mem_virq_th_order + 2);
+    }
+}
+
 /* Allocate 2^@order contiguous pages. */
 static struct page_info *alloc_heap_pages(
     unsigned int zone_lo, unsigned int zone_hi,
@@ -420,6 +529,8 @@ static struct page_info *alloc_heap_page
     total_avail_pages -= request;
     ASSERT(total_avail_pages >= 0);
 
+    check_low_mem_virq();
+
     if ( d != NULL )
         d->last_alloc_node = node;
 
@@ -1022,6 +1133,10 @@ void __init scrub_heap_pages(void)
     }
 
     printk("done.\n");
+
+    /* Now that the heap is initialized, run checks and set bounds
+     * for the low mem virq algorithm. */
+    setup_low_mem_virq();
 }
 
 
xen/include/public/xen.h +1 -0
diff -r bcfd44004568 -r 8938a0111344 xen/include/public/xen.h
@@ -157,6 +157,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
 #define VIRQ_PCPU_STATE 9  /* G. (DOM0) PCPU state changed                   */
 #define VIRQ_MEM_EVENT  10 /* G. (DOM0) A memory event has occured           */
 #define VIRQ_XC_RESERVED 11 /* G. Reserved for XenClient                     */
+#define VIRQ_ENOMEM     12 /* G. (DOM0) Low on heap memory       */
 
 /* Architecture-specific VIRQ definitions. */
 #define VIRQ_ARCH_0    16
#2 lore raw

PATCH 1/1 Lowmemd: Simple demo code to show use of VIRQ_ENOMEM

In reply to Andres Lagar-Cavilla
 .gitignore               |    1 +
 .hgignore                |    1 +
 tools/misc/Makefile      |    7 +-
 tools/misc/xen-lowmemd.c |  148 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 155 insertions(+), 2 deletions(-)
.gitignore +1 -0
diff -r 8938a0111344 -r 95417b1a745d .gitignore
@@ -197,6 +197,7 @@ tools/misc/xen-hvmctx
 tools/misc/gtraceview
 tools/misc/gtracestat
 tools/misc/xenlockprof
+tools/misc/lowmemd
 tools/pygrub/build/*
 tools/python/build/*
 tools/python/xen/util/path.py
.hgignore +1 -0
diff -r 8938a0111344 -r 95417b1a745d .hgignore
@@ -202,6 +202,7 @@
 ^tools/misc/xenperf$
 ^tools/misc/xenpm$
 ^tools/misc/xen-hvmctx$
+^tools/misc/xen-lowmemd$
 ^tools/misc/gtraceview$
 ^tools/misc/gtracestat$
 ^tools/misc/xenlockprof$
tools/misc/Makefile +5 -2
diff -r 8938a0111344 -r 95417b1a745d tools/misc/Makefile
@@ -9,7 +9,7 @@ CFLAGS += $(CFLAGS_xeninclude)
 HDRS     = $(wildcard *.h)
 
 TARGETS-y := xenperf xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd
-TARGETS-$(CONFIG_X86) += xen-detect xen-hvmctx xen-hvmcrash
+TARGETS-$(CONFIG_X86) += xen-detect xen-hvmctx xen-hvmcrash xen-lowmemd
 TARGETS-$(CONFIG_MIGRATE) += xen-hptool
 TARGETS := $(TARGETS-y)
 
@@ -21,7 +21,7 @@ INSTALL_BIN-y := xencons
 INSTALL_BIN-$(CONFIG_X86) += xen-detect
 INSTALL_BIN := $(INSTALL_BIN-y)
 
-INSTALL_SBIN-y := xm xen-bugtool xen-python-path xend xenperf xsview xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd xen-ringwatch
+INSTALL_SBIN-y := xm xen-bugtool xen-python-path xend xenperf xsview xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd xen-ringwatch xen-lowmemd
 INSTALL_SBIN-$(CONFIG_X86) += xen-hvmctx xen-hvmcrash
 INSTALL_SBIN-$(CONFIG_MIGRATE) += xen-hptool
 INSTALL_SBIN := $(INSTALL_SBIN-y)
@@ -70,6 +70,9 @@ xen-hptool: xen-hptool.o
 xenwatchdogd: xenwatchdogd.o
 	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
 
+xen-lowmemd: xen-lowmemd.o
+	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
+
 gtraceview: gtraceview.o
 	$(CC) $(LDFLAGS) -o $@ $< $(CURSES_LIBS) $(APPEND_LDFLAGS)
 
tools/misc/xen-lowmemd.c new file +148 -0

148 lines not on this page · raw message

Acked-by on v1 1/1
#3 lore raw
In reply to Andres Lagar-Cavilla
Quoted 9 lines

From: Andres Lagar-Cavilla [mailto:[email protected]]
Sent: Tuesday, March 06, 2012 1:04 PM
To: [email protected]
Cc: Dan Magenheimer; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
Subject: [Xen-devel] [PATCH 0 of 2] Virq for low memory conditions, V5

Changes from previous posting, dated Feb 29th
- Added consideration for tmem-freeable pages before firing the virq

Looks sane to me.

Quoted 28 lines

- Added Acked-by Ian Jackson for dom0 helper demo code
- Added .gitignore rune

Changes from V3 posted Feb 28th
- lowmemd is now xen-lowmemd
- .hgignore rune added for xen-lowmemd
- User can specify zero on the command line to disable the virq altogether
- Addressed two comments from Jan Beulich
+ Better detection of no user-provided command line threshold
+ Deal with the case in which the threshold may end up being zero.

Patch 1 is hypervisor (xen/common bits), patch 2 is tools.

 xen/common/page_alloc.c  |  115 ++++++++++++++++++++++++++++++++++++
 xen/include/public/xen.h |    1 +
 .gitignore               |    1 +
 .hgignore                |    1 +
 tools/misc/Makefile      |    7 +-
 tools/misc/xen-lowmemd.c |  148 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 271 insertions(+), 2 deletions(-)

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xen.org/xen-devel

#4 lore raw
In reply to Andres Lagar-Cavilla
Quoted 5 lines
Quoted 1 line
Quoted 1 line · Andres Lagar-Cavilla

Changes from previous posting, dated Feb 29th
- Added consideration for tmem-freeable pages before firing the virq
- Added Acked-by Ian Jackson for dom0 helper demo code
- Added .gitignore rune

As both patches already got committed, you'll want to supply incremental changes instead.

Jan

#5 lore raw
Quoted 9 lines
Quoted 6 lines
Quoted 2 lines
Quoted 2 lines

On 06.03.12 at 21:03, Andres Lagar-Cavilla <[email protected]> wrote:

Changes from previous posting, dated Feb 29th
- Added consideration for tmem-freeable pages before firing the virq
- Added Acked-by Ian Jackson for dom0 helper demo code
- Added .gitignore rune

As both patches already got committed, you'll want to supply incremental changes instead.

Great. I'll look into that. Thanks
Andres

Quoted 4 lines

Jan