diff mbox

[PATCH/RFCv4,0/6] The Contiguous Memory Allocator framework

Message ID 20100902175424.5849c197.kamezawa.hiroyu@jp.fujitsu.com (mailing list archive)
State Superseded
Headers show

Commit Message

KAMEZAWA Hiroyuki Sept. 2, 2010, 8:54 a.m. UTC
None
diff mbox

Patch

Index: kametest/mm/isolation.c
===================================================================
--- /dev/null
+++ kametest/mm/isolation.c
@@ -0,0 +1,233 @@ 
+struct page_range {
+	unsigned long base, end, pages;
+};
+
+int __get_contig_block(unsigned long pfn, unsigned long nr_pages, void *arg)
+{
+	struct page_range *blockinfo = arg;
+
+	if (nr_pages > blockinfo->pages) {
+		blockinfo->base = pfn;
+		blockinfo->end = pfn + nr_pages;
+		return 1;
+	}
+	return 0;
+}
+
+
+unsigned long __find_contig_block(unsigned long base,
+		unsigned long end, unsigned long pages)
+{
+	unsigned long pfn, tmp, index;
+	struct page_range blockinfo;
+	int ret;
+
+	/* Skip memory holes */
+retry:
+	blockinfo.base = base;
+	blockinfo.end = end;
+	blockinfo.pages = pages;
+	ret = walk_system_ram_range(base, end - base, &blockinfo,
+		__get_contig_block);	
+	if (!ret)
+		return 0;
+	/* Ok, we gound contiguous memory chunk of size. Isolate it.*/
+	for (pfn = blockinfo->base; pfn + pages < blockinfo->end;) {
+
+		for (index = 0; index < nr_pages; index += pageblock_nr_pages)
+			struct page *page;
+
+			page = pfn_to_page(pfn+index);
+			if (set_migratetype_isoalte(page))
+				break;
+		}
+		if (index == nr_pages)
+			return pfn; /* [pfn...pfn+nr_pages) are isolated */
+		/* rollback */
+		for (tmp = 0; tmp < index; tmp += pageblock_nr_pages) {
+			page = pfn_to_page(pfn+tmp);
+			unset_migratetype_isolate(page);
+		} 
+		pfn += index;
+	}
+	/* failed ? */
+	if (blockinfo.end + pages < end) {
+		/* Move base address and find the next block */
+		base = blockinfo.end;
+		goto retry;
+	}
+	return 0;
+}
+
+unsigned long
+find_isolate_conting_block(unsigned long hint, unsigned long size)
+{
+	unsigned long base, found, end, blocks, pages;
+	unsigned long *map;
+	int nid, retry;
+	physaddr_t addr = 0;
+
+	pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+	pages = ALIGN(pages, pageblock_nr_pages);
+	blocks = pages/pageblock_nr_pages;
+	base = hint;
+
+retry:
+	for_each_node_state(nid, N_HIGH_MEMORY) {
+		unsigned long start;
+		pg_data_t *node = NODE_DATA(nid);
+
+		if (node->node_start_pfn + node->node_end_pfn  - base < pages)
+			continue;
+		if (base < node->node_start_pfn)
+			base = node->node_start_pfn;
+		end = node->node_end_pfn;
+		/* Maybe we can use this Node */
+		found = __find_contig_block(base, end, blocks);
+		if (found) /* Found ? */
+			break;
+		base = end; /* try next node*/
+	}
+	if (!found)
+		goto out;
+	/*
+	 * Ok, here, we have contiguous pageblock marked as "isolated"
+	 * try migration.
+ 	 */
+	retry = 5;
+	while (retry--) {
+		if (!do_migrate_range(found, found + pages))
+			break;
+		lru_add_drain_all();
+		flush_scheduled_work();
+		cond_resched();
+		drain_all_pages();
+	}
+	lru_add_drain_all();
+	flush_scheduled_work();
+	drain_all_pages();
+	offlined_pages = check_pages_isolated(found, found+pages);
+	/* Ok, here, [found...found+pages) memory are isolated */
+out:
+	return found;
+}

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html