[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 18/18] mini-os: balloon up in case of oom



If a memory shortage is detected balloon up.

Be careful to always leave some pages free as ballooning up might need
some memory, too:

- new p2m frames
- page tables for addressing new p2m frame
- new frame for page allocation bitmap
- page table for addressing new page allocation bitmap frame
- page tables for addressing new 1:1 mapped frames

For the moment we only balloon up synchronously when memory shortage
is detected in allocation routines with irqs on.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
 balloon.c         | 32 ++++++++++++++++++++++++++++++++
 include/balloon.h | 11 +++++++++++
 mm.c              |  4 +++-
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/balloon.c b/balloon.c
index 30e571c..30b338c 100644
--- a/balloon.c
+++ b/balloon.c
@@ -125,3 +125,35 @@ int balloon_up(unsigned long n_pages)
 
     return rc;
 }
+
+static int in_balloon;
+
+int chk_free_pages(unsigned long needed)
+{
+    unsigned long n_pages;
+
+    /* No need for ballooning if plenty of space available. */
+    if ( needed + BALLOON_EMERGENCY_PAGES <= nr_free_pages )
+        return 0;
+
+    /* If we are already ballooning up just hope for the best. */
+    if ( in_balloon )
+        return 0;
+
+    /* Interrupts disabled can't be handled right now. */
+    if ( irqs_disabled() )
+        return 0;
+
+    in_balloon = 1;
+
+    while ( needed + BALLOON_EMERGENCY_PAGES > nr_free_pages )
+    {
+        n_pages = needed + BALLOON_EMERGENCY_PAGES - nr_free_pages;
+        if ( !balloon_up(n_pages) )
+            break;
+    }
+
+    in_balloon = 0;
+
+    return needed > nr_free_pages;
+}
diff --git a/include/balloon.h b/include/balloon.h
index 8bf77e5..c08b3f8 100644
--- a/include/balloon.h
+++ b/include/balloon.h
@@ -26,6 +26,12 @@
 
 #ifdef CONFIG_BALLOON
 
+/*
+ * Always keep some pages free for allocations while ballooning or
+ * interrupts disabled.
+ */
+#define BALLOON_EMERGENCY_PAGES   64
+
 extern unsigned long nr_max_pages;
 extern unsigned long virt_kernel_area_end;
 extern unsigned long nr_mem_pages;
@@ -37,12 +43,17 @@ void arch_remap_p2m(unsigned long max_pfn);
 void alloc_bitmap_remap(void);
 int arch_expand_p2m(unsigned long max_pfn);
 void arch_pfn_add(unsigned long pfn, unsigned long mfn);
+int chk_free_pages(unsigned long needed);
 
 #else /* CONFIG_BALLOON */
 
 static inline void get_max_pages(void) { }
 static inline void arch_remap_p2m(unsigned long max_pfn) { }
 static inline void alloc_bitmap_remap(void) { }
+static inline int chk_free_pages(unsigned long needed)
+{
+    return needed > nr_free_pages;
+}
 
 #endif /* CONFIG_BALLOON */
 #endif /* _BALLOON_H_ */
diff --git a/mm.c b/mm.c
index 092c5f9..2b57f46 100644
--- a/mm.c
+++ b/mm.c
@@ -209,6 +209,8 @@ unsigned long alloc_pages(int order)
     chunk_head_t *alloc_ch, *spare_ch;
     chunk_tail_t            *spare_ct;
 
+    if ( chk_free_pages(1UL << order) )
+        goto no_memory;
 
     /* Find smallest order which can satisfy the request. */
     for ( i = order; i < FREELIST_SIZE; i++ ) {
@@ -343,7 +345,7 @@ void *sbrk(ptrdiff_t increment)
     if (new_brk > heap_mapped) {
         unsigned long n = (new_brk - heap_mapped + PAGE_SIZE - 1) / PAGE_SIZE;
 
-        if ( n > nr_free_pages )
+        if ( chk_free_pages(n) )
         {
             printk("Memory exhausted: want %ld pages, but only %ld are left\n",
                    n, nr_free_pages);
-- 
2.6.6


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.