aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/mmzone.h
diff options
context:
space:
mode:
authorMel Gorman <mel@csn.ul.ie>2007-07-17 07:03:12 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-17 13:22:59 -0400
commit2a1e274acf0b1c192face19a4be7c12d4503eaaf (patch)
treef7e98e1fe19d38bb10bf178fb8f8ed1789b659b2 /include/linux/mmzone.h
parent769848c03895b63e5662eb7e4ec8c4866f7d0183 (diff)
Create the ZONE_MOVABLE zone
The following 8 patches against 2.6.20-mm2 create a zone called ZONE_MOVABLE that is only usable by allocations that specify both __GFP_HIGHMEM and __GFP_MOVABLE. This has the effect of keeping all non-movable pages within a single memory partition while allowing movable allocations to be satisfied from either partition. The patches may be applied with the list-based anti-fragmentation patches that groups pages together based on mobility. The size of the zone is determined by a kernelcore= parameter specified at boot-time. This specifies how much memory is usable by non-movable allocations and the remainder is used for ZONE_MOVABLE. Any range of pages within ZONE_MOVABLE can be released by migrating the pages or by reclaiming. When selecting a zone to take pages from for ZONE_MOVABLE, there are two things to consider. First, only memory from the highest populated zone is used for ZONE_MOVABLE. On the x86, this is probably going to be ZONE_HIGHMEM but it would be ZONE_DMA on ppc64 or possibly ZONE_DMA32 on x86_64. Second, the amount of memory usable by the kernel will be spread evenly throughout NUMA nodes where possible. If the nodes are not of equal size, the amount of memory usable by the kernel on some nodes may be greater than others. By default, the zone is not as useful for hugetlb allocations because they are pinned and non-migratable (currently at least). A sysctl is provided that allows huge pages to be allocated from that zone. This means that the huge page pool can be resized to the size of ZONE_MOVABLE during the lifetime of the system assuming that pages are not mlocked. Despite huge pages being non-movable, we do not introduce additional external fragmentation of note as huge pages are always the largest contiguous block we care about. Credit goes to Andy Whitcroft for catching a large variety of problems during review of the patches. This patch creates an additional zone, ZONE_MOVABLE. This zone is only usable by allocations which specify both __GFP_HIGHMEM and __GFP_MOVABLE. Hot-added memory continues to be placed in their existing destination as there is no mechanism to redirect them to a specific zone. [y-goto@jp.fujitsu.com: Fix section mismatch of memory hotplug related code] [akpm@linux-foundation.org: various fixes] Signed-off-by: Mel Gorman <mel@csn.ul.ie> Cc: Andy Whitcroft <apw@shadowen.org> Signed-off-by: Yasunori Goto <y-goto@jp.fujitsu.com> Cc: William Lee Irwin III <wli@holomorphy.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/mmzone.h')
-rw-r--r--include/linux/mmzone.h20
1 files changed, 18 insertions, 2 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 04b1636a970b..d71ff763c9df 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -146,6 +146,7 @@ enum zone_type {
146 */ 146 */
147 ZONE_HIGHMEM, 147 ZONE_HIGHMEM,
148#endif 148#endif
149 ZONE_MOVABLE,
149 MAX_NR_ZONES 150 MAX_NR_ZONES
150}; 151};
151 152
@@ -167,6 +168,7 @@ enum zone_type {
167 + defined(CONFIG_ZONE_DMA32) \ 168 + defined(CONFIG_ZONE_DMA32) \
168 + 1 \ 169 + 1 \
169 + defined(CONFIG_HIGHMEM) \ 170 + defined(CONFIG_HIGHMEM) \
171 + 1 \
170) 172)
171#if __ZONE_COUNT < 2 173#if __ZONE_COUNT < 2
172#define ZONES_SHIFT 0 174#define ZONES_SHIFT 0
@@ -499,10 +501,22 @@ static inline int populated_zone(struct zone *zone)
499 return (!!zone->present_pages); 501 return (!!zone->present_pages);
500} 502}
501 503
504extern int movable_zone;
505
506static inline int zone_movable_is_highmem(void)
507{
508#if defined(CONFIG_HIGHMEM) && defined(CONFIG_ARCH_POPULATES_NODE_MAP)
509 return movable_zone == ZONE_HIGHMEM;
510#else
511 return 0;
512#endif
513}
514
502static inline int is_highmem_idx(enum zone_type idx) 515static inline int is_highmem_idx(enum zone_type idx)
503{ 516{
504#ifdef CONFIG_HIGHMEM 517#ifdef CONFIG_HIGHMEM
505 return (idx == ZONE_HIGHMEM); 518 return (idx == ZONE_HIGHMEM ||
519 (idx == ZONE_MOVABLE && zone_movable_is_highmem()));
506#else 520#else
507 return 0; 521 return 0;
508#endif 522#endif
@@ -522,7 +536,9 @@ static inline int is_normal_idx(enum zone_type idx)
522static inline int is_highmem(struct zone *zone) 536static inline int is_highmem(struct zone *zone)
523{ 537{
524#ifdef CONFIG_HIGHMEM 538#ifdef CONFIG_HIGHMEM
525 return zone == zone->zone_pgdat->node_zones + ZONE_HIGHMEM; 539 int zone_idx = zone - zone->zone_pgdat->node_zones;
540 return zone_idx == ZONE_HIGHMEM ||
541 (zone_idx == ZONE_MOVABLE && zone_movable_is_highmem());
526#else 542#else
527 return 0; 543 return 0;
528#endif 544#endif