]> xenbits.xensource.com Git - mini-os.git/commitdiff
mini-os: balloon up in case of oom
authorJuergen Gross <jgross@suse.com>
Fri, 5 Aug 2016 14:27:53 +0000 (16:27 +0200)
committerWei Liu <wei.liu2@citrix.com>
Thu, 11 Aug 2016 12:09:59 +0000 (13:09 +0100)
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@suse.com>
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
balloon.c
include/balloon.h
mm.c

index e1af7787c22be8d7ff06b856f850739a2f877282..608492a9b8eb9b8137265b116615d8067b76acf6 100644 (file)
--- a/balloon.c
+++ b/balloon.c
@@ -126,3 +126,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 1;
+
+    /* If we are already ballooning up just hope for the best. */
+    if ( in_balloon )
+        return 1;
+
+    /* Interrupts disabled can't be handled right now. */
+    if ( irqs_disabled() )
+        return 1;
+
+    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;
+}
index 5ec1bbb0f2c83c962fa360746ed9478353fb0efb..d8710ade88b7ef20ac38fbe9234694ba7775beae 100644 (file)
 
 #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 mm_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 mm_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 9a048c300ec9e3e62e25fcf071b7ab1436aee1c7..ca0b9be7113ce7f1328c9a79cd74496f23d4ed38 100644 (file)
--- a/mm.c
+++ b/mm.c
@@ -210,6 +210,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++ ) {
@@ -344,7 +346,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);