Commit e76b63f8 authored by Yinghai Lu's avatar Yinghai Lu Committed by Linus Torvalds

memblock, numa: binary search node id

Current early_pfn_to_nid() on arch that support memblock go over
memblock.memory one by one, so will take too many try near the end.

We can use existing memblock_search to find the node id for given pfn,
that could save some time on bigger system that have many entries
memblock.memory array.

Here are the timing differences for several machines.  In each case with
the patch less time was spent in __early_pfn_to_nid().

                        3.11-rc5        with patch      difference (%)
                        --------        ----------      --------------
UV1: 256 nodes  9TB:     411.66          402.47         -9.19 (2.23%)
UV2: 255 nodes 16TB:    1141.02         1138.12         -2.90 (0.25%)
UV2:  64 nodes  2TB:     128.15          126.53         -1.62 (1.26%)
UV2:  32 nodes  2TB:     121.87          121.07         -0.80 (0.66%)
                        Time in seconds.
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Cc: Tejun Heo <tj@kernel.org>
Acked-by: default avatarRuss Anderson <rja@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 0bf598d8
...@@ -60,6 +60,8 @@ int memblock_reserve(phys_addr_t base, phys_addr_t size); ...@@ -60,6 +60,8 @@ int memblock_reserve(phys_addr_t base, phys_addr_t size);
void memblock_trim_memory(phys_addr_t align); void memblock_trim_memory(phys_addr_t align);
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
unsigned long *end_pfn);
void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
unsigned long *out_end_pfn, int *out_nid); unsigned long *out_end_pfn, int *out_nid);
......
...@@ -914,6 +914,24 @@ int __init_memblock memblock_is_memory(phys_addr_t addr) ...@@ -914,6 +914,24 @@ int __init_memblock memblock_is_memory(phys_addr_t addr)
return memblock_search(&memblock.memory, addr) != -1; return memblock_search(&memblock.memory, addr) != -1;
} }
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
unsigned long *start_pfn, unsigned long *end_pfn)
{
struct memblock_type *type = &memblock.memory;
int mid = memblock_search(type, (phys_addr_t)pfn << PAGE_SHIFT);
if (mid == -1)
return -1;
*start_pfn = type->regions[mid].base >> PAGE_SHIFT;
*end_pfn = (type->regions[mid].base + type->regions[mid].size)
>> PAGE_SHIFT;
return type->regions[mid].nid;
}
#endif
/** /**
* memblock_is_region_memory - check if a region is a subset of memory * memblock_is_region_memory - check if a region is a subset of memory
* @base: base of region to check * @base: base of region to check
......
...@@ -4306,7 +4306,7 @@ int __meminit init_currently_empty_zone(struct zone *zone, ...@@ -4306,7 +4306,7 @@ int __meminit init_currently_empty_zone(struct zone *zone,
int __meminit __early_pfn_to_nid(unsigned long pfn) int __meminit __early_pfn_to_nid(unsigned long pfn)
{ {
unsigned long start_pfn, end_pfn; unsigned long start_pfn, end_pfn;
int i, nid; int nid;
/* /*
* NOTE: The following SMP-unsafe globals are only used early in boot * NOTE: The following SMP-unsafe globals are only used early in boot
* when the kernel is running single-threaded. * when the kernel is running single-threaded.
...@@ -4317,15 +4317,14 @@ int __meminit __early_pfn_to_nid(unsigned long pfn) ...@@ -4317,15 +4317,14 @@ int __meminit __early_pfn_to_nid(unsigned long pfn)
if (last_start_pfn <= pfn && pfn < last_end_pfn) if (last_start_pfn <= pfn && pfn < last_end_pfn)
return last_nid; return last_nid;
for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) nid = memblock_search_pfn_nid(pfn, &start_pfn, &end_pfn);
if (start_pfn <= pfn && pfn < end_pfn) { if (nid != -1) {
last_start_pfn = start_pfn; last_start_pfn = start_pfn;
last_end_pfn = end_pfn; last_end_pfn = end_pfn;
last_nid = nid; last_nid = nid;
return nid;
} }
/* This is a memory hole */
return -1; return nid;
} }
#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */ #endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment