Skip to contentSkip to conversation

teach kswapd about higher order allocations

PATCH In review Nick Piggin 3 participants 17 messages Oct 27, 2004 – Nov 11, 2004

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover teach kswapd about higher order allocations

Hi Andrew,

Can this get into mm please?

I haven't been able to do a huge amount of testing, because there aren't many higher order allocations these days.

However:
I have got into situations where memory becomes completely fragmented and the Gbe network card starts spewing a lot of allocations failures. In some cases (eg. ifup) it will just sit there indefinitely cranking out order:2 allocation failures. These patches definitely fix those situations by having kswapd free some higher order areas.

Higher order area watermarks are enforced lazily - that is, if nobody is doing order 1 allocations, no attempt is ever made to free order 1 areas, even if none are available. Also, if kswapd can't free up the right amount of higher order areas, it eventually gives up on them until being kicked again.

In this way, I don't think this patch has any overscanning failure cases.

Note:
It generally doesn't take much work to free up memory to get networking going because the skb allocations are transient, so you only need some set number of higher order areas free, and the network buffers just keep reusing them. Other allocations don't tend to touch them much because the buddy allocator takes low order pages first.

Linus was the only one with any real objections, but once I explained myself better he thought this was fairly reasonable (I think).

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#1 lore raw

PATCH 1/3 keep count of free areas

1/3

Keep track of the number of free pages of each order in the buddy allocator.

---

 linux-2.6-npiggin/include/linux/mmzone.h |    1 +
 linux-2.6-npiggin/mm/page_alloc.c        |   23 +++++++++--------------
 2 files changed, 10 insertions(+), 14 deletions(-)
mm/page_alloc.c renamed from mm/page_alloc.c~vm-free-order-pages +9 -14
diff -puN mm/page_alloc.c~vm-free-order-pages mm/page_alloc.c
@@ -209,6 +209,7 @@ static inline void __free_pages_bulk (st
 		BUG_ON(bad_range(zone, buddy1));
 		BUG_ON(bad_range(zone, buddy2));
 		list_del(&buddy1->lru);
+		area->nr_free--;
 		mask <<= 1;
 		order++;
 		area++;
@@ -216,6 +217,7 @@ static inline void __free_pages_bulk (st
 		page_idx &= mask;
 	}
 	list_add(&(base + page_idx)->lru, &area->free_list);
+	area->nr_free++;
 }
 
 static inline void free_pages_check(const char *function, struct page *page)
@@ -317,6 +319,7 @@ expand(struct zone *zone, struct page *p
 		size >>= 1;
 		BUG_ON(bad_range(zone, &page[size]));
 		list_add(&page[size].lru, &area->free_list);
+		area->nr_free++;
 		MARK_USED(index + size, high, area);
 	}
 	return page;
@@ -380,6 +383,7 @@ static struct page *__rmqueue(struct zon
 
 		page = list_entry(area->free_list.next, struct page, lru);
 		list_del(&page->lru);
+		area->nr_free--;
 		index = page - zone->zone_mem_map;
 		if (current_order != MAX_ORDER-1)
 			MARK_USED(index, current_order, area);
@@ -1120,7 +1124,6 @@ void show_free_areas(void)
 	}
 
 	for_each_zone(zone) {
-		struct list_head *elem;
  		unsigned long nr, flags, order, total = 0;
 
 		show_node(zone);
@@ -1132,9 +1135,7 @@ void show_free_areas(void)
 
 		spin_lock_irqsave(&zone->lock, flags);
 		for (order = 0; order < MAX_ORDER; order++) {
-			nr = 0;
-			list_for_each(elem, &zone->free_area[order].free_list)
-				++nr;
+			nr = zone->free_area[order].nr_free;
 			total += nr << order;
 			printk("%lu*%lukB ", nr, K(1UL) << order);
 		}
@@ -1460,6 +1461,7 @@ void zone_init_free_lists(struct pglist_
 		bitmap_size = pages_to_bitmap_size(order, size);
 		zone->free_area[order].map =
 		  (unsigned long *) alloc_bootmem_node(pgdat, bitmap_size);
+		zone->free_area[order].nr_free = 0;
 	}
 }
 
@@ -1647,8 +1649,7 @@ static void frag_stop(struct seq_file *m
 }
 
 /* 
- * This walks the freelist for each zone. Whilst this is slow, I'd rather 
- * be slow here than slow down the fast path by keeping stats - mjbligh
+ * This walks the free areas for each zone.
  */
 static int frag_show(struct seq_file *m, void *arg)
 {
@@ -1664,14 +1665,8 @@ static int frag_show(struct seq_file *m,
 
 		spin_lock_irqsave(&zone->lock, flags);
 		seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name);
-		for (order = 0; order < MAX_ORDER; ++order) {
-			unsigned long nr_bufs = 0;
-			struct list_head *elem;
-
-			list_for_each(elem, &(zone->free_area[order].free_list))
-				++nr_bufs;
-			seq_printf(m, "%6lu ", nr_bufs);
-		}
+		for (order = 0; order < MAX_ORDER; ++order)
+			seq_printf(m, "%6lu ", zone->free_area[order].nr_free);
 		spin_unlock_irqrestore(&zone->lock, flags);
 		seq_putc(m, '\n');
 	}
include/linux/mmzone.h renamed from include/linux/mmzone.h~vm-free-order-pages +1 -0
diff -puN include/linux/mmzone.h~vm-free-order-pages include/linux/mmzone.h
@@ -23,6 +23,7 @@
 struct free_area {
 	struct list_head	free_list;
 	unsigned long		*map;
+	unsigned long		nr_free;
 };
 
 struct pglist_data;

_

#2 lore raw

PATCH 2/3 higher order watermarks

2/3

Move the watermark checking code into a single function. Extend it to account for the order of the allocation and the number of free pages that could satisfy such a request.

---

 linux-2.6-npiggin/include/linux/mmzone.h |    2 +
 linux-2.6-npiggin/mm/page_alloc.c        |   58 ++++++++++++++++++++-----------
 2 files changed, 41 insertions(+), 19 deletions(-)
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +39 -19
diff -puN mm/page_alloc.c~vm-alloc-order-watermarks mm/page_alloc.c
@@ -586,6 +586,37 @@ buffered_rmqueue(struct zone *zone, int 
 }
 
 /*
+ * Return 1 if free pages are above 'mark'. This takes into account the order
+ * of the allocation.
+ */
+int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
+		int alloc_type, int can_try_harder, int gfp_high)
+{
+	/* free_pages my go negative - that's OK */
+	long min = mark, free_pages = z->free_pages - (1 << order) + 1;
+	int o;
+
+	if (gfp_high)
+		min -= min / 2;
+	if (can_try_harder)
+		min -= min / 4;
+
+	if (free_pages <= min + z->protection[alloc_type])
+		return 0;
+	for (o = 0; o < order; o++) {
+		/* At the next order, this order's pages become unavailable */
+		free_pages -= z->free_area[order].nr_free << o;
+
+		/* Require fewer higher order pages to be free */
+		min >>= 1;
+
+		if (free_pages <= min)
+			return 0;
+	}
+	return 1;
+}
+
+/*
  * This is the 'heart' of the zoned buddy allocator.
  *
  * Herein lies the mysterious "incremental min".  That's the
@@ -606,7 +637,6 @@ __alloc_pages(unsigned int gfp_mask, uns
 		struct zonelist *zonelist)
 {
 	const int wait = gfp_mask & __GFP_WAIT;
-	unsigned long min;
 	struct zone **zones, *z;
 	struct page *page;
 	struct reclaim_state reclaim_state;
@@ -636,9 +666,9 @@ __alloc_pages(unsigned int gfp_mask, uns
 
 	/* Go through the zonelist once, looking for a zone with enough free */
 	for (i = 0; (z = zones[i]) != NULL; i++) {
-		min = z->pages_low + (1<<order) + z->protection[alloc_type];
 
-		if (z->free_pages < min)
+		if (!zone_watermark_ok(z, order, z->pages_low,
+				alloc_type, 0, 0))
 			continue;
 
 		page = buffered_rmqueue(z, order, gfp_mask);
@@ -654,14 +684,9 @@ __alloc_pages(unsigned int gfp_mask, uns
 	 * coming from realtime tasks to go deeper into reserves
 	 */
 	for (i = 0; (z = zones[i]) != NULL; i++) {
-		min = z->pages_min;
-		if (gfp_mask & __GFP_HIGH)
-			min /= 2;
-		if (can_try_harder)
-			min -= min / 4;
-		min += (1<<order) + z->protection[alloc_type];
-
-		if (z->free_pages < min)
+		if (!zone_watermark_ok(z, order, z->pages_min,
+				alloc_type, can_try_harder,
+				gfp_mask & __GFP_HIGH))
 			continue;
 
 		page = buffered_rmqueue(z, order, gfp_mask);
@@ -697,14 +722,9 @@ rebalance:
 
 	/* go through the zonelist yet one more time */
 	for (i = 0; (z = zones[i]) != NULL; i++) {
-		min = z->pages_min;
-		if (gfp_mask & __GFP_HIGH)
-			min /= 2;
-		if (can_try_harder)
-			min -= min / 4;
-		min += (1<<order) + z->protection[alloc_type];
-
-		if (z->free_pages < min)
+		if (!zone_watermark_ok(z, order, z->pages_min,
+				alloc_type, can_try_harder,
+				gfp_mask & __GFP_HIGH))
 			continue;
 
 		page = buffered_rmqueue(z, order, gfp_mask);
include/linux/mmzone.h renamed from include/linux/mmzone.h~vm-alloc-order-watermarks +2 -0
diff -puN include/linux/mmzone.h~vm-alloc-order-watermarks include/linux/mmzone.h
@@ -279,6 +279,8 @@ void get_zone_counts(unsigned long *acti
 			unsigned long *free);
 void build_all_zonelists(void);
 void wakeup_kswapd(struct zone *zone);
+int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
+		int alloc_type, int can_try_harder, int gfp_high);
 
 /*
  * zone_idx() returns 0 for the ZONE_DMA zone, 1 for the ZONE_NORMAL zone, etc.

_

#3 lore raw

PATCH 3/3 teach kswapd about higher order areas

3/3

Teach kswapd to free memory on behalf of higher order allocators. This could be important for higher order atomic allocations because they otherwise have no means to free the memory themselves.

---

 linux-2.6-npiggin/include/linux/mmzone.h |    5 +--
 linux-2.6-npiggin/mm/page_alloc.c        |    3 +
 linux-2.6-npiggin/mm/vmscan.c            |   48 ++++++++++++++++++-------------
 3 files changed, 34 insertions(+), 22 deletions(-)
mm/vmscan.c renamed from mm/vmscan.c~vm-kswapd-heed-order-watermarks +29 -19
diff -puN mm/vmscan.c~vm-kswapd-heed-order-watermarks mm/vmscan.c
@@ -851,9 +851,6 @@ shrink_caches(struct zone **zones, struc
 	for (i = 0; zones[i] != NULL; i++) {
 		struct zone *zone = zones[i];
 
-		if (zone->present_pages == 0)
-			continue;
-
 		zone->temp_priority = sc->priority;
 		if (zone->prev_priority > sc->priority)
 			zone->prev_priority = sc->priority;
@@ -968,7 +965,7 @@ out:
  * the page allocator fallback scheme to ensure that aging of pages is balanced
  * across the zones.
  */
-static int balance_pgdat(pg_data_t *pgdat, int nr_pages)
+static int balance_pgdat(pg_data_t *pgdat, int nr_pages, int order)
 {
 	int to_free = nr_pages;
 	int all_zones_ok;
@@ -1007,14 +1004,12 @@ loop_again:
 			for (i = pgdat->nr_zones - 1; i >= 0; i--) {
 				struct zone *zone = pgdat->node_zones + i;
 
-				if (zone->present_pages == 0)
-					continue;
-
 				if (zone->all_unreclaimable &&
 						priority != DEF_PRIORITY)
 					continue;
 
-				if (zone->free_pages <= zone->pages_high) {
+				if (!zone_watermark_ok(zone, order,
+						zone->pages_high, 0, 0, 0)) {
 					end_zone = i;
 					goto scan;
 				}
@@ -1042,14 +1037,12 @@ scan:
 		for (i = 0; i <= end_zone; i++) {
 			struct zone *zone = pgdat->node_zones + i;
 
-			if (zone->present_pages == 0)
-				continue;
-
 			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
 				continue;
 
 			if (nr_pages == 0) {	/* Not software suspend */
-				if (zone->free_pages <= zone->pages_high)
+				if (!zone_watermark_ok(zone, order,
+						zone->pages_high, end_zone, 0, 0))
 					all_zones_ok = 0;
 			}
 			zone->temp_priority = priority;
@@ -1126,6 +1119,7 @@ out:
  */
 static int kswapd(void *p)
 {
+	unsigned long order;
 	pg_data_t *pgdat = (pg_data_t*)p;
 	struct task_struct *tsk = current;
 	DEFINE_WAIT(wait);
@@ -1154,14 +1148,28 @@ static int kswapd(void *p)
 	 */
 	tsk->flags |= PF_MEMALLOC|PF_KSWAPD;
 
+	order = 0;
 	for ( ; ; ) {
+		unsigned long new_order;
 		if (current->flags & PF_FREEZE)
 			refrigerator(PF_FREEZE);
+
 		prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
-		schedule();
+		new_order = pgdat->kswapd_max_order;
+		pgdat->kswapd_max_order = 0;
+		if (order < new_order) {
+			/*
+			 * Don't sleep if someone wants a larger 'order'
+			 * allocation
+			 */
+			order = new_order;
+		} else {
+			schedule();
+			order = pgdat->kswapd_max_order;
+		}
 		finish_wait(&pgdat->kswapd_wait, &wait);
 
-		balance_pgdat(pgdat, 0);
+		balance_pgdat(pgdat, 0, order);
 	}
 	return 0;
 }
@@ -1169,12 +1177,14 @@ static int kswapd(void *p)
 /*
  * A zone is low on free memory, so wake its kswapd task to service it.
  */
-void wakeup_kswapd(struct zone *zone)
+void wakeup_kswapd(struct zone *zone, int order)
 {
-	if (zone->present_pages == 0)
-		return;
-	if (zone->free_pages > zone->pages_low)
+	pg_data_t *pgdat = zone->zone_pgdat;
+
+	if (zone_watermark_ok(zone, order, zone->pages_low, 0, 0, 0))
 		return;
+	if (pgdat->kswapd_max_order < order)
+		pgdat->kswapd_max_order = order;
 	if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
 		return;
 	wake_up_interruptible(&zone->zone_pgdat->kswapd_wait);
@@ -1197,7 +1207,7 @@ int shrink_all_memory(int nr_pages)
 	current->reclaim_state = &reclaim_state;
 	for_each_pgdat(pgdat) {
 		int freed;
-		freed = balance_pgdat(pgdat, nr_to_free);
+		freed = balance_pgdat(pgdat, nr_to_free, 0);
 		ret += freed;
 		nr_to_free -= freed;
 		if (nr_to_free <= 0)
mm/page_alloc.c renamed from mm/page_alloc.c~vm-kswapd-heed-order-watermarks +2 -1
diff -puN mm/page_alloc.c~vm-kswapd-heed-order-watermarks mm/page_alloc.c
@@ -677,7 +677,7 @@ __alloc_pages(unsigned int gfp_mask, uns
 	}
 
 	for (i = 0; (z = zones[i]) != NULL; i++)
-		wakeup_kswapd(z);
+		wakeup_kswapd(z, order);
 
 	/*
 	 * Go through the zonelist again. Let __GFP_HIGH and allocations
@@ -1506,6 +1506,7 @@ static void __init free_area_init_core(s
 
 	pgdat->nr_zones = 0;
 	init_waitqueue_head(&pgdat->kswapd_wait);
+	pgdat->kswapd_max_order = 0;
 	
 	for (j = 0; j < MAX_NR_ZONES; j++) {
 		struct zone *zone = pgdat->node_zones + j;
include/linux/mmzone.h renamed from include/linux/mmzone.h~vm-kswapd-heed-order-watermarks +3 -2
diff -puN include/linux/mmzone.h~vm-kswapd-heed-order-watermarks include/linux/mmzone.h
@@ -263,8 +263,9 @@ typedef struct pglist_data {
 					     range, including holes */
 	int node_id;
 	struct pglist_data *pgdat_next;
-	wait_queue_head_t       kswapd_wait;
+	wait_queue_head_t kswapd_wait;
 	struct task_struct *kswapd;
+	int kswapd_max_order;
 } pg_data_t;
 
 #define node_present_pages(nid)	(NODE_DATA(nid)->node_present_pages)
@@ -278,7 +279,7 @@ void __get_zone_counts(unsigned long *ac
 void get_zone_counts(unsigned long *active, unsigned long *inactive,
 			unsigned long *free);
 void build_all_zonelists(void);
-void wakeup_kswapd(struct zone *zone);
+void wakeup_kswapd(struct zone *zone, int order);
 int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
 		int alloc_type, int can_try_harder, int gfp_high);
 

_

#4 lore raw

Re: [PATCH 3/3] teach kswapd about higher order areas

Quoted 25 lines · Nick Piggin

3/3

------------------------------------------------------------------------

Teach kswapd to free memory on behalf of higher order allocators. This could be important for higher order atomic allocations because they otherwise have no means to free the memory themselves.

---

 linux-2.6-npiggin/include/linux/mmzone.h |    5 +--
 linux-2.6-npiggin/mm/page_alloc.c        |    3 +
 linux-2.6-npiggin/mm/vmscan.c            |   48 ++++++++++++++++++-------------
 3 files changed, 34 insertions(+), 22 deletions(-)

diff -puN mm/vmscan.c~vm-kswapd-heed-order-watermarks mm/vmscan.c

mm/vmscan.c shrink_caches(struct zone **zones, struc · line 856

Quoted 6 lines
mm/vmscan.c renamed from mm/vmscan.c~vm-kswapd-heed-order-watermarks +0 -3
@@ -851,9 +851,6 @@ shrink_caches(struct zone **zones, struc
 	for (i = 0; zones[i] != NULL; i++) {
 		struct zone *zone = zones[i];
 
-		if (zone->present_pages == 0)
-			continue;
-

Sorry, slight mismerge - this gets rid of thse new fangled checks (which it shouldn't). Other than that it looks ok though.

Let me know if you want a fixed up patch.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw

Re: [PATCH 2/3] higher order watermarks

In reply to Nick Piggin
Quoted 9 lines · Nick Piggin

2/3

Move the watermark checking code into a single function. Extend it to account for the order of the allocation and the number of free pages that could satisfy such a request.

Hi Nick,

I have a few comments and doubts.

Quoted 24 lines
 linux-2.6-npiggin/include/linux/mmzone.h |    2 +
 linux-2.6-npiggin/mm/page_alloc.c        |   58 ++++++++++++++++++++-----------
 2 files changed, 41 insertions(+), 19 deletions(-)

diff -puN mm/page_alloc.c~vm-alloc-order-watermarks mm/page_alloc.c

mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +13 -0
@@ -586,6 +586,37 @@ buffered_rmqueue(struct zone *zone, int 
 }
 
 /*
+ * Return 1 if free pages are above 'mark'. This takes into account the order
+ * of the allocation.
+ */
+int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
+		int alloc_type, int can_try_harder, int gfp_high)
+{
+	/* free_pages my go negative - that's OK */
+	long min = mark, free_pages = z->free_pages - (1 << order) + 1;
+	int o;
+
+	if (gfp_high)
+		min -= min / 2;
+	if (can_try_harder)

mm/page_alloc.c buffered_rmqueue(struct zone *zone, int · line 611

Quoted 10 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +10 -0
+		min -= min / 4;
+
+	if (free_pages <= min + z->protection[alloc_type])
+		return 0;
+	for (o = 0; o < order; o++) {
+		/* At the next order, this order's pages become unavailable */
+		free_pages -= z->free_area[order].nr_free << o;
+
+		/* Require fewer higher order pages to be free */
+		min >>= 1;

I can't understand this. You decrease from free_pages nr_order_free_pages << o, in a loop, and divide min by two.

What is the meaning of "nr_free_pages[order] << o" ? Its only meaningful when o == order?

You're multiplying the number of free pages of the order the allocation wants by "0, 1..order". The two values have different meanings, until
o == order.

In the first iteration of the loop, order is 0, so you decrease from free_pages "z->free_area[order].nr_free". Again, the two values mean different things.

Can you enlight me?

I see you're trying to have some kind of extra protection, but the calculation is difficult to understand for me.

Quoted 20 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +8 -1
+
+		if (free_pages <= min)
+			return 0;
+	}
+	return 1;
+}
+
+/*
  * This is the 'heart' of the zoned buddy allocator.
  *
  * Herein lies the mysterious "incremental min".  That's the
@@ -606,7 +637,6 @@ __alloc_pages(unsigned int gfp_mask, uns
 		struct zonelist *zonelist)
 {
 	const int wait = gfp_mask & __GFP_WAIT;
-	unsigned long min;
 	struct zone **zones, *z;
 	struct page *page;
 	struct reclaim_state reclaim_state;

mm/page_alloc.c __alloc_pages(unsigned int gfp_mask, uns · line 671

Quoted 8 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +2 -2
@@ -636,9 +666,9 @@ __alloc_pages(unsigned int gfp_mask, uns
 
 	/* Go through the zonelist once, looking for a zone with enough free */
 	for (i = 0; (z = zones[i]) != NULL; i++) {
-		min = z->pages_low + (1<<order) + z->protection[alloc_type];
 
-		if (z->free_pages < min)
+		if (!zone_watermark_ok(z, order, z->pages_low,
+				alloc_type, 0, 0))

The original code didnt had the can_try_harder/gfp_high decrease which is now on zone_watermark_ok.

Means that those allocations will now be successful earlier, instead of going to the next zonelist iteration. kswapd will not be awake when it used to be.

Hopefully it doesnt matter that much. You did this by intention?

TIA

Quoted 52 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +6 -16
 			continue;
 
 		page = buffered_rmqueue(z, order, gfp_mask);
@@ -654,14 +684,9 @@ __alloc_pages(unsigned int gfp_mask, uns
 	 * coming from realtime tasks to go deeper into reserves
 	 */
 	for (i = 0; (z = zones[i]) != NULL; i++) {
-		min = z->pages_min;
-		if (gfp_mask & __GFP_HIGH)
-			min /= 2;
-		if (can_try_harder)
-			min -= min / 4;
-		min += (1<<order) + z->protection[alloc_type];
-
-		if (z->free_pages < min)
+		if (!zone_watermark_ok(z, order, z->pages_min,
+				alloc_type, can_try_harder,
+				gfp_mask & __GFP_HIGH))
 			continue;
 
 		page = buffered_rmqueue(z, order, gfp_mask);
@@ -697,14 +722,9 @@ rebalance:
 
 	/* go through the zonelist yet one more time */
 	for (i = 0; (z = zones[i]) != NULL; i++) {
-		min = z->pages_min;
-		if (gfp_mask & __GFP_HIGH)
-			min /= 2;
-		if (can_try_harder)
-			min -= min / 4;
-		min += (1<<order) + z->protection[alloc_type];
-
-		if (z->free_pages < min)
+		if (!zone_watermark_ok(z, order, z->pages_min,
+				alloc_type, can_try_harder,
+				gfp_mask & __GFP_HIGH))
 			continue;
 
 		page = buffered_rmqueue(z, order, gfp_mask);

diff -puN include/linux/mmzone.h~vm-alloc-order-watermarks include/linux/mmzone.h

include/linux/mmzone.h renamed from include/linux/mmzone.h~vm-alloc-order-watermarks +2 -0
@@ -279,6 +279,8 @@ void get_zone_counts(unsigned long *acti
 			unsigned long *free);
 void build_all_zonelists(void);
 void wakeup_kswapd(struct zone *zone);
+int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
+		int alloc_type, int can_try_harder, int gfp_high);
 
 /*
  * zone_idx() returns 0 for the ZONE_DMA zone, 1 for the ZONE_NORMAL zone, etc.
Quoted 1 line

_

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#6 lore raw

Re: [PATCH 2/3] higher order watermarks

Quoted 10 lines · Marcelo Tosatti
Quoted 8 lines · Nick Piggin

2/3

Move the watermark checking code into a single function. Extend it to account for the order of the allocation and the number of free pages that could satisfy such a request.

Quoted 7 lines
Quoted 1 line

Hi Nick,

I have a few comments and doubts.

Hi Marcelo,
Thanks for the comments and review. It is always very helpful to have more eyes on this area of code especially. Let's see...

Quoted 42 lines
Quoted 25 lines

linux-2.6-npiggin/include/linux/mmzone.h | 2 +
linux-2.6-npiggin/mm/page_alloc.c | 58 ++++++++++++++++++++-----------

2 files changed, 41 insertions(+), 19 deletions(-)

diff -puN mm/page_alloc.c~vm-alloc-order-watermarks mm/page_alloc.c

mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +13 -0
@@ -586,6 +586,37 @@ buffered_rmqueue(struct zone *zone, int 
 }
 
 /*
+ * Return 1 if free pages are above 'mark'. This takes into account the order
+ * of the allocation.
+ */
+int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
+		int alloc_type, int can_try_harder, int gfp_high)
+{
+	/* free_pages my go negative - that's OK */
+	long min = mark, free_pages = z->free_pages - (1 << order) + 1;
+	int o;
+
+	if (gfp_high)
+		min -= min / 2;
+	if (can_try_harder)

mm/page_alloc.c buffered_rmqueue(struct zone *zone, int · line 611

Quoted 10 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +10 -0
+		min -= min / 4;
+
+	if (free_pages <= min + z->protection[alloc_type])
+		return 0;
+	for (o = 0; o < order; o++) {
+		/* At the next order, this order's pages become unavailable */
+		free_pages -= z->free_area[order].nr_free << o;
+
+		/* Require fewer higher order pages to be free */
+		min >>= 1;

I can't understand this. You decrease from free_pages nr_order_free_pages << o, in a loop, and divide min by two.

What is the meaning of "nr_free_pages[order] << o" ? Its only meaningful when o == order?

Quoted 9 lines

You're multiplying the number of free pages of the order the allocation wants by "0, 1..order". The two values have different meanings, until o == order.

In the first iteration of the loop, order is 0, so you decrease from free_pages "z->free_area[order].nr_free". Again, the two values mean different things.

Can you enlight me?

I see you're trying to have some kind of extra protection, but the calculation is difficult to understand for me.

OK, we store the number of "order-pages" free for each order, so for example, 16K worth of order-2 pages (on a 4K page architecture) will count towards just 1 nr_free.

So now what we need to do in order to calculate, say the amount of memory that will satisfy order-2 *and above* (this is important) is the following:

	z->free_pages - (order[0].nr_free << 0) - (order[1].nr_free << 1)

to find order-3 and above, you also need to subtract (order[2].nr_free << 2).

I quite liked this method because it has progressively less cost on lower order allocations, and for order-0 we don't need to do any calculation.

Of course it is slightly racy, which is why I say free_pages can go negative, but that should be OK.

Probably the comment there is woefully inadequate? - I sometimes forget that people can't read my mind :\

Quoted 34 lines
Quoted 21 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +8 -1
+
+		if (free_pages <= min)
+			return 0;
+	}
+	return 1;
+}
+
+/*
 * This is the 'heart' of the zoned buddy allocator.
 *
 * Herein lies the mysterious "incremental min".  That's the
@@ -606,7 +637,6 @@ __alloc_pages(unsigned int gfp_mask, uns
 		struct zonelist *zonelist)
 {
 	const int wait = gfp_mask & __GFP_WAIT;
-	unsigned long min;
 	struct zone **zones, *z;
 	struct page *page;
 	struct reclaim_state reclaim_state;

mm/page_alloc.c __alloc_pages(unsigned int gfp_mask, uns · line 671

Quoted 8 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +2 -2
@@ -636,9 +666,9 @@ __alloc_pages(unsigned int gfp_mask, uns
 
 	/* Go through the zonelist once, looking for a zone with enough free */
 	for (i = 0; (z = zones[i]) != NULL; i++) {
-		min = z->pages_low + (1<<order) + z->protection[alloc_type];
 
-		if (z->free_pages < min)
+		if (!zone_watermark_ok(z, order, z->pages_low,
+				alloc_type, 0, 0))

The original code didnt had the can_try_harder/gfp_high decrease which is now on zone_watermark_ok.

Quoted 6 lines

Means that those allocations will now be successful earlier, instead of going to the next zonelist iteration. kswapd will not be awake when it used to be.

Hopefully it doesnt matter that much. You did this by intention?

That should be OK: the last two zero arguments mean that doesn't get evaluated; so it should work as you'd expect I think?

Thanks,
Nick
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw

Re: [PATCH 2/3] higher order watermarks

Hi Nick!

Quoted 87 lines · Nick Piggin
Quoted 12 lines · Marcelo Tosatti
Quoted 10 lines · Nick Piggin

2/3

Move the watermark checking code into a single function. Extend it to account
for the order of the allocation and the number of free pages that could satisfy
such a request.

Quoted 7 lines
Quoted 1 line

Hi Nick,

I have a few comments and doubts.

Hi Marcelo,
Thanks for the comments and review. It is always very helpful to have more eyes on this area of code especially. Let's see...

Quoted 52 lines
Quoted 36 lines

linux-2.6-npiggin/include/linux/mmzone.h | 2 +
linux-2.6-npiggin/mm/page_alloc.c | 58
++++++++++++++++++++-----------

2 files changed, 41 insertions(+), 19 deletions(-)

diff -puN mm/page_alloc.c~vm-alloc-order-watermarks mm/page_alloc.c
--- linux-2.6/mm/page_alloc.c~vm-alloc-order-watermarks 2004-10-27
16:41:32.000000000 +1000
+++ linux-2.6-npiggin/mm/page_alloc.c 2004-10-27
17:53:33.000000000 +1000

(quoted diff) +1 -0
@@ -586,6 +586,37 @@ buffered_rmqueue(struct zone *zone, int 
 }
 
 /*
+ * Return 1 if free pages are above 'mark'. This takes into account the 

order
+ * of the allocation.
+ */

mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +16 -0
+int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
+		int alloc_type, int can_try_harder, int gfp_high)
+{
+	/* free_pages my go negative - that's OK */
+	long min = mark, free_pages = z->free_pages - (1 << order) + 1;
+	int o;
+
+	if (gfp_high)
+		min -= min / 2;
+	if (can_try_harder)
+		min -= min / 4;
+
+	if (free_pages <= min + z->protection[alloc_type])
+		return 0;
+	for (o = 0; o < order; o++) {
+		/* At the next order, this order's pages become unavailable 

*/

mm/page_alloc.c buffered_rmqueue(struct zone *zone, int · line 611

Quoted 4 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +4 -0
+		free_pages -= z->free_area[order].nr_free << o;
+
+		/* Require fewer higher order pages to be free */
+		min >>= 1;

I can't understand this. You decrease from free_pages nr_order_free_pages << o, in a loop, and divide min by two.

What is the meaning of "nr_free_pages[order] << o" ? Its only meaningful when o == order?

You're multiplying the number of free pages of the order the allocation wants by "0, 1..order". The two values have different meanings, until
o == order.

Quoted 9 lines

In the first iteration of the loop, order is 0, so you decrease from free_pages "z->free_area[order].nr_free". Again, the two values mean different things.

Can you enlight me?

I see you're trying to have some kind of extra protection, but the calculation is difficult to understand for me.

Quoted 8 lines

OK, we store the number of "order-pages" free for each order, so for example, 16K worth of order-2 pages (on a 4K page architecture) will count towards just 1 nr_free.

So now what we need to do in order to calculate, say the amount of memory that will satisfy order-2 *and above* (this is important) is the following:

	z->free_pages - (order[0].nr_free << 0) - (order[1].nr_free << 1)

Shouldnt that be then

free_pages -= z->free_area[o].nr_free << o;

instead of the current

free_pages -= z->free_area[order].nr_free << o;

No?

Quoted 5 lines

to find order-3 and above, you also need to subtract (order[2].nr_free << 2).

I quite liked this method because it has progressively less cost on lower order allocations, and for order-0 we don't need to do any calculation.

OK, now I get it. The only think which bugs me is the multiplication of values with different meanings.

Quoted 3 lines

Of course it is slightly racy, which is why I say free_pages can go negative,
but that should be OK.

Yeap.

Quoted 44 lines

Probably the comment there is woefully inadequate? - I sometimes forget that people can't read my mind :\

Quoted 40 lines
Quoted 21 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +8 -0
+
+		if (free_pages <= min)
+			return 0;
+	}
+	return 1;
+}
+
+/*

* This is the 'heart' of the zoned buddy allocator. *
* Herein lies the mysterious "incremental min". That's the

mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +0 -1
@@ -606,7 +637,6 @@ __alloc_pages(unsigned int gfp_mask, uns
 		struct zonelist *zonelist)
 {
 	const int wait = gfp_mask & __GFP_WAIT;
-	unsigned long min;
 	struct zone **zones, *z;
 	struct page *page;
 	struct reclaim_state reclaim_state;

mm/page_alloc.c __alloc_pages(unsigned int gfp_mask, uns · line 672

Quoted 9 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +2 -2
@@ -636,9 +666,9 @@ __alloc_pages(unsigned int gfp_mask, uns
 
 	/* Go through the zonelist once, looking for a zone with enough free 
 	*/
 	for (i = 0; (z = zones[i]) != NULL; i++) {
-		min = z->pages_low + (1<<order) + z->protection[alloc_type];
 
-		if (z->free_pages < min)
+		if (!zone_watermark_ok(z, order, z->pages_low,
+				alloc_type, 0, 0))

The original code didnt had the can_try_harder/gfp_high decrease which is now on zone_watermark_ok.

Means that those allocations will now be successful earlier, instead of going to the next zonelist iteration. kswapd will not be awake when it used to be.

Quoted 5 lines
Quoted 2 lines

Hopefully it doesnt matter that much. You did this by intention?

That should be OK: the last two zero arguments mean that doesn't get evaluated; so it should work as you'd expect I think?

Oh correct, pardon me.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw

Re: [PATCH 2/3] higher order watermarks

Quoted 13 lines · Marcelo Tosatti

Hi Nick!

Quoted 4 lines · Nick Piggin

So now what we need to do in order to calculate, say the amount of memory that will satisfy order-2 *and above* (this is important) is the following:

	z->free_pages - (order[0].nr_free << 0) - (order[1].nr_free << 1)

Shouldnt that be then

Quoted 8 lines

free_pages -= z->free_area[o].nr_free << o;

instead of the current

free_pages -= z->free_area[order].nr_free << o;

No?

Yes, you're absolutely right. Sorry, this is what you were getting at all along :P

Quoted 9 lines
Quoted 5 lines

to find order-3 and above, you also need to subtract (order[2].nr_free << 2).

I quite liked this method because it has progressively less cost on lower order allocations, and for order-0 we don't need to do any calculation.

OK, now I get it. The only think which bugs me is the multiplication of values with different meanings.

Yeah it's wrong, of course. Good catch, thanks.

If you would care to send a patch Marcelo? I don't have a recent -mm on hand at the moment. Would that be alright?

Thanks,
Nick
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#9 lore raw

Re: [PATCH 2/3] higher order watermarks

Quoted 35 lines · Nick Piggin
Quoted 14 lines · Marcelo Tosatti

Hi Nick!

Quoted 5 lines · Nick Piggin

So now what we need to do in order to calculate, say the amount of memory that will satisfy order-2 *and above* (this is important) is the following:

	z->free_pages - (order[0].nr_free << 0) - (order[1].nr_free << 1)

Shouldnt that be then

Quoted 8 lines

free_pages -= z->free_area[o].nr_free << o;

instead of the current

free_pages -= z->free_area[order].nr_free << o;

No?

Yes, you're absolutely right. Sorry, this is what you were getting at all along :P

Quoted 8 lines
Quoted 6 lines

to find order-3 and above, you also need to subtract (order[2].nr_free << 2).

I quite liked this method because it has progressively less cost on lower order allocations, and for order-0 we don't need to do any calculation.

Quoted 8 lines
Quoted 3 lines

OK, now I get it. The only think which bugs me is the multiplication of values with different meanings.

Yeah it's wrong, of course. Good catch, thanks.

If you would care to send a patch Marcelo? I don't have a recent -mm on hand at the moment. Would that be alright?

Sure, I'll prepare a patch.

This typo probably means that the current code is not actually working as intented - did any of you receive any feedback on this patch, wrt high order allocation intensive driver setup/workload, Nick and Andrew?

I have been using a simple module which allocates a big number of high order allocations in a row (for the defragmentation code testing), I'll give it a shot tomorrow to test Nick's high-order-kswapd scheme effectiveness.

Anyway, here is the patch:

Description:
Fix typo in Nick's kswapd-high-order awareness patch

mm/page_alloc.c renamed from mm/page_alloc.c.orig +1 -1
@@ -733,7 +733,7 @@
 		return 0;
 	for (o = 0; o < order; o++) {
 		/* At the next order, this order's pages become unavailable */
-		free_pages -= z->free_area[order].nr_free << o;
+		free_pages -= z->free_area[o].nr_free << o;
 
 		/* Require fewer higher order pages to be free */
 		min >>= 1;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#10 lore raw

Re: [PATCH 2/3] higher order watermarks

Quoted 4 lines · Marcelo Tosatti

This typo probably means that the current code is not actually working as
intented - did any of you receive any feedback on this patch, wrt high order allocation intensive driver setup/workload, Nick and Andrew?

None whatsoever.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#11 lore raw

Re: [PATCH 2/3] higher order watermarks

In reply to Marcelo Tosatti
Quoted 5 lines · Marcelo Tosatti
Quoted 2 lines · Nick Piggin

Yeah it's wrong, of course. Good catch, thanks.

Quoted 9 lines
Quoted 2 lines

If you would care to send a patch Marcelo? I don't have a recent -mm on hand at the moment. Would that be alright?

Sure, I'll prepare a patch.

This typo probably means that the current code is not actually working as intented - did any of you receive any feedback on this patch, wrt high order allocation intensive driver setup/workload, Nick and Andrew?

I had tested it and it did do the right thing when fragmentation meant higer order memory was completely depleted - previously atomic allocations would just stop working, but the patches got them going again.

I did have one guy who tested the patches in a production sort of system that was getting some allocation failures. He said they didn't make much difference (increasing min_free_kbytes was effective).

So hopefully this should make things work better.

What would happen without the patch, is that if you had 0 order-2 pages free and wanted to make an order-2 allocation, free_pages would never get decremented, so it wouldn't detect the shortage.

Quoted 6 lines

I have been using a simple module which allocates a big number of high order allocations in a row (for the defragmentation code testing), I'll give it a shot tomorrow to test Nick's high-order-kswapd scheme effectiveness.

Anyway, here is the patch:

ACK. Thanks.

Quoted 7 lines

Description:
Fix typo in Nick's kswapd-high-order awareness patch

mm/page_alloc.c line 739

Quoted 8 lines
mm/page_alloc.c renamed from mm/page_alloc.c.orig +1 -1
@@ -733,7 +733,7 @@
 		return 0;
 	for (o = 0; o < order; o++) {
 		/* At the next order, this order's pages become unavailable */
-		free_pages -= z->free_area[order].nr_free << o;
+		free_pages -= z->free_area[o].nr_free << o;
 
 		/* Require fewer higher order pages to be free */
 		min >>= 1;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#12 lore raw

Re: [PATCH 2/3] higher order watermarks

In reply to Nick Piggin
Quoted 102 lines · Nick Piggin
Quoted 12 lines · Marcelo Tosatti
Quoted 10 lines · Nick Piggin

2/3

Move the watermark checking code into a single function. Extend it to account
for the order of the allocation and the number of free pages that could satisfy
such a request.

Quoted 7 lines
Quoted 1 line

Hi Nick,

I have a few comments and doubts.

Hi Marcelo,
Thanks for the comments and review. It is always very helpful to have more eyes on this area of code especially. Let's see...

Quoted 52 lines
Quoted 36 lines

linux-2.6-npiggin/include/linux/mmzone.h | 2 +
linux-2.6-npiggin/mm/page_alloc.c | 58
++++++++++++++++++++-----------

2 files changed, 41 insertions(+), 19 deletions(-)

diff -puN mm/page_alloc.c~vm-alloc-order-watermarks mm/page_alloc.c
--- linux-2.6/mm/page_alloc.c~vm-alloc-order-watermarks 2004-10-27
16:41:32.000000000 +1000
+++ linux-2.6-npiggin/mm/page_alloc.c 2004-10-27
17:53:33.000000000 +1000

(quoted diff) +1 -0
@@ -586,6 +586,37 @@ buffered_rmqueue(struct zone *zone, int 
 }
 
 /*
+ * Return 1 if free pages are above 'mark'. This takes into account the 

order
+ * of the allocation.
+ */

mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +16 -0
+int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
+		int alloc_type, int can_try_harder, int gfp_high)
+{
+	/* free_pages my go negative - that's OK */
+	long min = mark, free_pages = z->free_pages - (1 << order) + 1;
+	int o;
+
+	if (gfp_high)
+		min -= min / 2;
+	if (can_try_harder)
+		min -= min / 4;
+
+	if (free_pages <= min + z->protection[alloc_type])
+		return 0;
+	for (o = 0; o < order; o++) {
+		/* At the next order, this order's pages become unavailable 

*/

mm/page_alloc.c buffered_rmqueue(struct zone *zone, int · line 611

Quoted 4 lines
mm/page_alloc.c renamed from mm/page_alloc.c~vm-alloc-order-watermarks +4 -0
+		free_pages -= z->free_area[order].nr_free << o;
+
+		/* Require fewer higher order pages to be free */
+		min >>= 1;

I can't understand this. You decrease from free_pages nr_order_free_pages << o, in a loop, and divide min by two.

What is the meaning of "nr_free_pages[order] << o" ? Its only meaningful when o == order?

You're multiplying the number of free pages of the order the allocation wants by "0, 1..order". The two values have different meanings, until
o == order.

Quoted 9 lines

In the first iteration of the loop, order is 0, so you decrease from free_pages "z->free_area[order].nr_free". Again, the two values mean different things.

Can you enlight me?

I see you're trying to have some kind of extra protection, but the calculation is difficult to understand for me.

OK, we store the number of "order-pages" free for each order, so for example, 16K worth of order-2 pages (on a 4K page architecture) will count towards just 1 nr_free.

So now what we need to do in order to calculate, say the amount of memory that will satisfy order-2 *and above* (this is important) is the following:

	z->free_pages - (order[0].nr_free << 0) - (order[1].nr_free << 1)

to find order-3 and above, you also need to subtract (order[2].nr_free << 2).

I quite liked this method because it has progressively less cost on lower order allocations, and for order-0 we don't need to do any calculation.

Quoted 6 lines

Of course it is slightly racy, which is why I say free_pages can go negative,
but that should be OK.

Probably the comment there is woefully inadequate? - I sometimes forget that people can't read my mind :\

Nick, care to add a comment on top of zone_watermark_ok explaining the reasoning behind the calculation and its expected effects?

That would be really nice.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#13 lore raw

Re: [PATCH 2/3] higher order watermarks

Quoted 9 lines · Marcelo Tosatti
Quoted 2 lines · Nick Piggin

Probably the comment there is woefully inadequate? - I sometimes forget that people can't read my mind :\

Nick, care to add a comment on top of zone_watermark_ok explaining the reasoning behind the calculation and its expected effects?

That would be really nice.

Yep, I'll come up with something for it.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#14 lore raw

Re: [PATCH 2/3] higher order watermarks

In reply to Marcelo Tosatti
Quoted 8 lines · Marcelo Tosatti

The original code didnt had the can_try_harder/gfp_high decrease which is now on zone_watermark_ok.

Means that those allocations will now be successful earlier, instead of going to the next zonelist iteration. kswapd will not be awake when it used to be.

Hopefully it doesnt matter that much. You did this by intention?

Another thing Nick is that now balance_pgdat uses zone_watermark_ok, and that sums "z->protection[alloc_type]".

        if (free_pages <= min + z->protection[alloc_type])
                return 0;

Since balance_pgdat calls with alloc_type=0, the code will sum ZONE_DMA (alloc_type = 0) protection, and it should not.

kswapd should be working on the bare min/low/high watermarks AFAICT, without the protections.

Comments?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#15 lore raw

Re: [PATCH 2/3] higher order watermarks

Quoted 17 lines · Marcelo Tosatti
Quoted 7 lines · Marcelo Tosatti

The original code didnt had the can_try_harder/gfp_high decrease which is now on zone_watermark_ok.

Means that those allocations will now be successful earlier, instead of going to the next zonelist iteration. kswapd will not be awake when it used to be.

Hopefully it doesnt matter that much. You did this by intention?

Another thing Nick is that now balance_pgdat uses zone_watermark_ok, and that sums "z->protection[alloc_type]".

        if (free_pages <= min + z->protection[alloc_type])
                return 0;
Quoted 8 lines

Since balance_pgdat calls with alloc_type=0, the code will sum ZONE_DMA (alloc_type = 0) protection, and it should not.

kswapd should be working on the bare min/low/high watermarks AFAICT, without the protections.

Comments?

Yeah.. I think z->protection[0] should always be 0, shouldn't it? I was just hesitant to add another parameter to the function and have yet another case to check.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#16 lore raw

Re: [PATCH 2/3] higher order watermarks

Quoted 23 lines · Nick Piggin
Quoted 22 lines · Marcelo Tosatti
Quoted 8 lines · Marcelo Tosatti

The original code didnt had the can_try_harder/gfp_high decrease which is now on zone_watermark_ok.

Means that those allocations will now be successful earlier, instead of going to the next zonelist iteration. kswapd will not be awake when it used to be.

Hopefully it doesnt matter that much. You did this by intention?

Another thing Nick is that now balance_pgdat uses zone_watermark_ok, and that sums "z->protection[alloc_type]".

       if (free_pages <= min + z->protection[alloc_type])
               return 0;

Since balance_pgdat calls with alloc_type=0, the code will sum ZONE_DMA (alloc_type = 0) protection, and it should not.

Quoted 8 lines
Quoted 6 lines

kswapd should be working on the bare min/low/high watermarks AFAICT, without the protections.

Comments?

Yeah.. I think z->protection[0] should always be 0, shouldn't it?

Oh yes, fine.

Quoted 2 lines

I was just hesitant to add another parameter to the function and have yet another case to check.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>