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>
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;
+}
#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;
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_ */
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++ ) {
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);