|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 18/19] 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>
Reviewed-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>
---
V3: Reverse chk_free_pages() return value as requested by Samuel Thibault
---
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 07ef532..afec757 100644
--- 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;
+}
diff --git a/include/balloon.h b/include/balloon.h
index 5ec1bbb..d8710ad 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 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 5364079..b1f8f34 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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |