Hi,
The following patch will throttle VM allocators in case we are below a
given threshold of free memory.
This will make hunger allocators throttle more page reclamation, giving us
a (hopefully) fair system wrt memory.
Please test this. I'm specially interested in interactivity during heavy
VM pressure.
Its against 2.4.12.
Thanks
diff -Nur linux.orig/mm/page_alloc.c linux/mm/page_alloc.c
--- linux.orig/mm/page_alloc.c Thu Oct 11 16:04:56 2001
+++ linux/mm/page_alloc.c Thu Oct 11 16:03:36 2001
@@ -228,6 +228,22 @@
}
#endif
+static inline int vm_throttle(zone_t *classzone, unsigned int gfp_mask, unsigned int order)
+{
+ int progress;
+ if (in_interrupt())
+ BUG();
+
+ current->allocation_order = order;
+ current->flags |= PF_MEMALLOC | PF_FREE_PAGES;
+
+ progress = try_to_free_pages(classzone, gfp_mask, order);
+
+ current->flags &= ~(PF_MEMALLOC | PF_FREE_PAGES);
+
+ return progress;
+}
+
static struct page * FASTCALL(balance_classzone(zone_t *, unsigned int, unsigned int, int *));
static struct page * balance_classzone(zone_t * classzone, unsigned int gfp_mask, unsigned int order, int * freed)
{
@@ -338,6 +354,16 @@
if (waitqueue_active(&kswapd_wait))
wake_up_interruptible(&kswapd_wait);
+ /*
+ * We're possibly going to eat memory from the min<->low
+ * "reversed" area. Throttling page reclamation using
+ * the allocators which reach this point will give us a
+ * fair system.
+ */
+
+ if ((gfp_mask & __GFP_WAIT))
+ vm_throttle(classzone, gfp_mask, order);
+
zone = zonelist->zones;
for (;;) {
unsigned long min;
@@ -386,7 +412,7 @@
if (!z)
break;
- if (zone_free_pages(z, order) > z->pages_min) {
+ if (zone_free_pages(z, order) > z->pages_low) {
page = rmqueue(z, order);
if (page)
return page;
@@ -394,7 +420,13 @@
}
/* Don't let big-order allocations loop */
- if (order)
+ /* We have one special 1-order alloc user: fork().
+ * It obviously cannot fail easily like other
+ * high order allocations. This could also be fixed
+ * by having a __GFP_LOOP flag to indicate that the
+ * high order allocation is "critical".
+ */
+ if (order > 1)
return NULL;
/* Yield for kswapd, and try again */
diff -Nur linux.orig/mm/vmscan.c linux/mm/vmscan.c
--- linux.orig/mm/vmscan.c Thu Oct 11 16:04:56 2001
+++ linux/mm/vmscan.c Thu Oct 11 15:52:36 2001
@@ -558,13 +558,14 @@
int priority = DEF_PRIORITY;
int nr_pages = SWAP_CLUSTER_MAX;
- do {
- nr_pages = shrink_caches(priority, classzone, gfp_mask, nr_pages);
- if (nr_pages <= 0)
- return 1;
+ nr_pages = shrink_caches(priority, classzone, gfp_mask, nr_pages);
+ if (nr_pages <= 0)
+ return 1;
+
+ ret = (nr_pages < SWAP_CLUSTER_MAX);
+
+ ret |= swap_out(priority, classzone, gfp_mask, SWAP_CLUSTER_MAX << 2);
- ret |= swap_out(priority, classzone, gfp_mask, SWAP_CLUSTER_MAX << 2);
- } while (--priority);
return ret;
}
On Tue, 16 Oct 2001, Marcelo Tosatti wrote:
> + /*
> + * We're possibly going to eat memory from the min<->low
> + * "reversed" area. Throttling page reclamation using
"reserved" ;)
> + * the allocators which reach this point will give us a
> + * fair system.
> + */
> +
> + if ((gfp_mask & __GFP_WAIT))
> + vm_throttle(classzone, gfp_mask, order);
It might be an idea to also test for PF_MEMALLOC here,
otherwise bad things will happen.
regards,
Rik
--
DMCA, SSSCA, W3C? Who cares? http://thefreeworld.net/ (volunteers needed)
http://www.surriel.com/ http://distro.conectiva.com/