[RFC][PATCH] unify pfn_to_page [1/25] generic page_to_pfn / pfn_to_page

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



3 memory models are now available, memmaps of 3 models are defined as

FLATMEM      --- pfn = (page - mem_map) + offset
DISCONTIGMEM --- pfn = (page - page_node(page)->node_mem_map) +
                          (page_node(page)->node_start_pfn)
SPARSEMEM    --- see linux/mmzone.h , generic ones are defined.

Now, each arch has its own page_to_pfn()/pfn_to_page() on FLATMEM/DISCONTIGIMEM.
But most of them keeps above assumptions and looks same to i386's ones.

This patch unifies each arch's page_to_pfn/pfn_to_page to generic ones.
This patch is against 2.6.16-rc2.

comments ?

-- Kame

This patch defines generic page_to_pfn()/pfn_to_page().
For DISCONTIGMEM, page_to_pfn/pfn_to_page are not inlined.
(x86_64 already has not-inlined version and it reduces text size.)

If FLATMEM and memmap <-> pfn translation needs offset,
ARCH_PFN_OFFSET is defined by each archs.

If DISCONTIGMEM , each arch defines arch_pfn_to_nid().
If necessary, arch_local_map_nr(pfn, nid) is also defined.
arch_local_map_nr() calculates page offset in a node.

Signed-Off-By: KAMEZAWA Hiruyoki <[email protected]>


Index: cleanup_pfn_page/include/linux/mm.h
===================================================================
--- cleanup_pfn_page.orig/include/linux/mm.h
+++ cleanup_pfn_page/include/linux/mm.h
@@ -512,6 +512,32 @@ static inline void set_page_links(struct
 extern struct page *mem_map;
 #endif

+#if !defined(ARCH_HAS_PFN_PAGE) && !defined(CONFIG_SPARSEMEM)
+#if CONFIG_FLATMEM
+
+#ifndef ARCH_PFN_OFFSET
+#define ARCH_PFN_OFFSET	0
+#endif
+static inline unsigned long page_to_pfn(struct page *page)
+{
+	return (unsigned long)(page - mem_map) + ARCH_PFN_OFFSET;
+}
+static inline struct page *pfn_to_page(unsigned long pfn)
+{
+	return mem_map + (pfn - ARCH_PFN_OFFSET);
+}
+#endif /* CONFIG_FLATMEM */
+#ifdef CONFIG_DISCONTIGMEM
+/* arch_pfn_to_nid/arch_local_map_nr is defined if necesary */
+#ifndef arch_local_map_nr
+#define arch_local_map_nr(pfn ,nid)	((pfn) - NODE_DATA(nid)->node_start_pfn)
+#endif
+extern unsigned long page_to_pfn(struct page *page);
+extern struct page* pfn_to_page(unsigned long pfn);
+#endif /* CONFIG_DISCONTIGMEM */
+
+#endif
+
 static __always_inline void *lowmem_page_address(struct page *page)
 {
 	return __va(page_to_pfn(page) << PAGE_SHIFT);
Index: cleanup_pfn_page/mm/page_alloc.c
===================================================================
--- cleanup_pfn_page.orig/mm/page_alloc.c
+++ cleanup_pfn_page/mm/page_alloc.c
@@ -85,6 +85,25 @@ int min_free_kbytes = 1024;
 unsigned long __initdata nr_kernel_pages;
 unsigned long __initdata nr_all_pages;

+#if defined(CONFIG_DISCONTIGMEM) && !defined(CONFIG_VIRTUAL_MEM_MAP)
+
+struct page *pfn_to_page(unsigned long pfn)
+{
+	struct pglist_data *pgdat;
+	int nid = arch_pfn_to_nid(pfn);
+	pgdat = NODE_DATA(nid);
+	return pgdat->node_mem_map + arch_local_map_nr(pfn, nid);
+}
+EXPORT_SYMBOL(pfn_to_page);
+
+unsigned long page_to_pfn(struct page *page)
+{
+	struct zone *z = page_zone(page);
+	return z->zone_start_pfn + (unsigned long)(page - z->zone_mem_map);
+}
+EXPORT_SYMBOL(page_to_pfn);
+#endif
+
 #ifdef CONFIG_DEBUG_VM
 static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
 {


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux