linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
To: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: "linux-mm@kvack.org" <linux-mm@kvack.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"minchan.kim@gmail.com" <minchan.kim@gmail.com>
Subject: [RFC][PATCH 2/3] find a contiguous range.
Date: Wed, 13 Oct 2010 12:17:38 +0900	[thread overview]
Message-ID: <20101013121738.933ff002.kamezawa.hiroyu@jp.fujitsu.com> (raw)
In-Reply-To: <20101013121527.8ec6a769.kamezawa.hiroyu@jp.fujitsu.com>

From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>

Unlike memory hotplug, at an allocation of contigous memory range, address
may not be a problem. IOW, if a requester of memory wants to allocate 100M of
of contigous memory, placement of allocated memory may not be a problem.
So, "finding a range of memory which seems to be MOVABLE" is required.

This patch adds a functon to isolate a length of memory within [start, end).
This function returns a pfn which is 1st page of isolated contigous chunk
of given length within [start, end).

If no_search=true is passed as argument, start address is always same to
the specified "base" addresss.

After isolation, free memory within this area will never be allocated.
But some pages will remain as "Used/LRU" pages. They should be dropped by
page reclaim or migration.


Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
---
 mm/page_isolation.c |  130 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 130 insertions(+)

Index: mmotm-1008/mm/page_isolation.c
===================================================================
--- mmotm-1008.orig/mm/page_isolation.c
+++ mmotm-1008/mm/page_isolation.c
@@ -9,6 +9,7 @@
 #include <linux/pageblock-flags.h>
 #include <linux/memcontrol.h>
 #include <linux/migrate.h>
+#include <linux/memory_hotplug.h>
 #include <linux/mm_inline.h>
 #include "internal.h"
 
@@ -254,3 +255,132 @@ out:
 	return ret;
 }
 
+/*
+ * Functions for getting contiguous MOVABLE pages in a zone.
+ */
+struct page_range {
+	unsigned long base; /* Base address of searching contigouous block */
+	unsigned long end;
+	unsigned long pages;/* Length of contiguous block */
+};
+
+static inline unsigned long  MAX_ORDER_ALIGN(unsigned long x)
+{
+	return ALIGN(x, MAX_ORDER_NR_PAGES);
+}
+
+static inline unsigned long MAX_ORDER_BASE(unsigned long x)
+{
+	return x & ~(MAX_ORDER_NR_PAGES - 1);
+}
+
+int __get_contig_block(unsigned long pfn, unsigned long nr_pages, void *arg)
+{
+	struct page_range *blockinfo = arg;
+	unsigned long end;
+
+	end = pfn + nr_pages;
+	pfn = MAX_ORDER_ALIGN(pfn);
+	end = MAX_ORDER_BASE(end);
+
+	if (end < pfn)
+		return 0;
+	if (end - pfn >= blockinfo->pages) {
+		blockinfo->base = pfn;
+		blockinfo->end = end;
+		return 1;
+	}
+	return 0;
+}
+
+static void __trim_zone(struct page_range *range)
+{
+	struct zone *zone;
+	unsigned long pfn;
+	/*
+	 * In most case, each zone's [start_pfn, end_pfn) has no
+	 * overlap between each other. But some arch allows it and
+	 * we need to check it here.
+	 */
+	for (pfn = range->base, zone = page_zone(pfn_to_page(pfn));
+	     pfn < range->end;
+	     pfn += MAX_ORDER_NR_PAGES) {
+
+		if (zone != page_zone(pfn_to_page(pfn)))
+			break;
+	}
+	range->end = min(pfn, range->end);
+	return;
+}
+
+/*
+ * This function is for finding a contiguous memory block which has length
+ * of pages and MOVABLE. If it finds, make the range of pages as ISOLATED
+ * and return the first page's pfn.
+ * If no_search==true, this function doesn't scan the range but tries to
+ * isolate the range of memory.
+ */
+
+static unsigned long find_contig_block(unsigned long base,
+		unsigned long end, unsigned long pages, bool no_search)
+{
+	unsigned long pfn, pos;
+	struct page_range blockinfo;
+	int ret;
+
+	pages = MAX_ORDER_ALIGN(pages);
+retry:
+	blockinfo.base = base;
+	blockinfo.end = end;
+	blockinfo.pages = pages;
+	/*
+	 * At first, check physical page layout and skip memory holes.
+	 */
+	ret = walk_system_ram_range(base, end - base, &blockinfo,
+		__get_contig_block);
+	if (!ret)
+		return 0;
+	/* check contiguous pages in a zone */
+	__trim_zone(&blockinfo);
+
+
+	/* Ok, we found contiguous memory chunk of size. Isolate it.*/
+	for (pfn = blockinfo.base; pfn + pages < blockinfo.end;
+	     pfn += MAX_ORDER_NR_PAGES) {
+		/* If no_search==true, base addess should be same to 'base' */
+		if (no_search && pfn != base)
+			break;
+		/* Better code is necessary here.. */
+		for (pos = pfn; pos < pfn + pages; pos++) {
+			struct page *p;
+
+			if (!pfn_valid_within(pos))
+				break;
+			p = pfn_to_page(pos);
+			if (PageReserved(p))
+				break;
+			/* This may hit a page on per-cpu queue. */
+			if (page_count(p) && !PageLRU(p))
+				break;
+			/* Need to skip order of pages */
+		}
+		if (pos != pfn + pages) {
+			pfn = MAX_ORDER_BASE(pos);
+			continue;
+		}
+		/*
+		 * Now, we know [base,end) of a contiguous chunk.
+		 * Don't need to take care of memory holes.
+		 */
+		if (!start_isolate_page_range(pfn, pfn + pages))
+			return pfn;
+	}
+
+	/* failed */
+	if (!no_search && blockinfo.end + pages < end) {
+		/* Move base address and find the next block of RAM. */
+		base = blockinfo.end;
+		goto retry;
+	}
+	return 0;
+}

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

  reply	other threads:[~2010-10-13  3:22 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-13  3:15 [RFC][PATCH 1/3] contigous big page allocator KAMEZAWA Hiroyuki
2010-10-13  3:17 ` KAMEZAWA Hiroyuki [this message]
2010-10-17  3:18   ` [RFC][PATCH 2/3] find a contiguous range Minchan Kim
2010-10-18  0:29     ` KAMEZAWA Hiroyuki
2010-10-13  3:18 ` [RFC][PATCH 3/3] alloc contig pages with migration KAMEZAWA Hiroyuki
2010-10-17  4:05   ` Minchan Kim
2010-10-18  0:35     ` KAMEZAWA Hiroyuki
2010-10-18  5:18       ` Minchan Kim
2010-10-18  5:31         ` KAMEZAWA Hiroyuki
2010-10-18  5:52           ` Minchan Kim
2010-10-18  5:52             ` KAMEZAWA Hiroyuki
2010-10-13  5:05 ` [RFC][PATCH 1/3] contigous big page allocator KOSAKI Motohiro
2010-10-13  7:01 ` Andi Kleen
2010-10-13  7:12   ` KAMEZAWA Hiroyuki
2010-10-13  8:36     ` Andi Kleen
2010-10-13  8:39       ` KAMEZAWA Hiroyuki
2010-10-14  1:59       ` KOSAKI Motohiro
2010-10-14  7:07   ` FUJITA Tomonori
2010-10-14  7:24     ` Andi Kleen
2010-10-14  8:36       ` FUJITA Tomonori
2010-10-14 12:55         ` Andi Kleen
2010-10-14 15:09           ` FUJITA Tomonori
2010-10-14 12:10       ` Felipe Contreras
2010-10-14 12:09     ` Felipe Contreras
2010-10-14 15:24       ` FUJITA Tomonori
2010-10-14 21:50         ` Felipe Contreras

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101013121738.933ff002.kamezawa.hiroyu@jp.fujitsu.com \
    --to=kamezawa.hiroyu@jp.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=minchan.kim@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox