diff options
Diffstat (limited to 'include/linux/mmzone.h')
-rw-r--r-- | include/linux/mmzone.h | 68 |
1 files changed, 45 insertions, 23 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 5ed471b58f4f..9f22090df7dd 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/threads.h> | 12 | #include <linux/threads.h> |
13 | #include <linux/numa.h> | 13 | #include <linux/numa.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/seqlock.h> | ||
15 | #include <asm/atomic.h> | 16 | #include <asm/atomic.h> |
16 | 17 | ||
17 | /* Free memory management - zoned buddy allocator. */ | 18 | /* Free memory management - zoned buddy allocator. */ |
@@ -70,10 +71,11 @@ struct per_cpu_pageset { | |||
70 | #endif | 71 | #endif |
71 | 72 | ||
72 | #define ZONE_DMA 0 | 73 | #define ZONE_DMA 0 |
73 | #define ZONE_NORMAL 1 | 74 | #define ZONE_DMA32 1 |
74 | #define ZONE_HIGHMEM 2 | 75 | #define ZONE_NORMAL 2 |
76 | #define ZONE_HIGHMEM 3 | ||
75 | 77 | ||
76 | #define MAX_NR_ZONES 3 /* Sync this with ZONES_SHIFT */ | 78 | #define MAX_NR_ZONES 4 /* Sync this with ZONES_SHIFT */ |
77 | #define ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */ | 79 | #define ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */ |
78 | 80 | ||
79 | 81 | ||
@@ -89,27 +91,18 @@ struct per_cpu_pageset { | |||
89 | * will be a maximum of 4 (2 ** 2) zonelists, for 3 modifiers there will | 91 | * will be a maximum of 4 (2 ** 2) zonelists, for 3 modifiers there will |
90 | * be 8 (2 ** 3) zonelists. GFP_ZONETYPES defines the number of possible | 92 | * be 8 (2 ** 3) zonelists. GFP_ZONETYPES defines the number of possible |
91 | * combinations of zone modifiers in "zone modifier space". | 93 | * combinations of zone modifiers in "zone modifier space". |
94 | * | ||
95 | * NOTE! Make sure this matches the zones in <linux/gfp.h> | ||
92 | */ | 96 | */ |
93 | #define GFP_ZONEMASK 0x03 | 97 | #define GFP_ZONEMASK 0x07 |
94 | /* | 98 | #define GFP_ZONETYPES 5 |
95 | * As an optimisation any zone modifier bits which are only valid when | ||
96 | * no other zone modifier bits are set (loners) should be placed in | ||
97 | * the highest order bits of this field. This allows us to reduce the | ||
98 | * extent of the zonelists thus saving space. For example in the case | ||
99 | * of three zone modifier bits, we could require up to eight zonelists. | ||
100 | * If the left most zone modifier is a "loner" then the highest valid | ||
101 | * zonelist would be four allowing us to allocate only five zonelists. | ||
102 | * Use the first form when the left most bit is not a "loner", otherwise | ||
103 | * use the second. | ||
104 | */ | ||
105 | /* #define GFP_ZONETYPES (GFP_ZONEMASK + 1) */ /* Non-loner */ | ||
106 | #define GFP_ZONETYPES ((GFP_ZONEMASK + 1) / 2 + 1) /* Loner */ | ||
107 | 99 | ||
108 | /* | 100 | /* |
109 | * On machines where it is needed (eg PCs) we divide physical memory | 101 | * On machines where it is needed (eg PCs) we divide physical memory |
110 | * into multiple physical zones. On a PC we have 3 zones: | 102 | * into multiple physical zones. On a PC we have 4 zones: |
111 | * | 103 | * |
112 | * ZONE_DMA < 16 MB ISA DMA capable memory | 104 | * ZONE_DMA < 16 MB ISA DMA capable memory |
105 | * ZONE_DMA32 0 MB Empty | ||
113 | * ZONE_NORMAL 16-896 MB direct mapped by the kernel | 106 | * ZONE_NORMAL 16-896 MB direct mapped by the kernel |
114 | * ZONE_HIGHMEM > 896 MB only page cache and user processes | 107 | * ZONE_HIGHMEM > 896 MB only page cache and user processes |
115 | */ | 108 | */ |
@@ -137,6 +130,10 @@ struct zone { | |||
137 | * free areas of different sizes | 130 | * free areas of different sizes |
138 | */ | 131 | */ |
139 | spinlock_t lock; | 132 | spinlock_t lock; |
133 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
134 | /* see spanned/present_pages for more description */ | ||
135 | seqlock_t span_seqlock; | ||
136 | #endif | ||
140 | struct free_area free_area[MAX_ORDER]; | 137 | struct free_area free_area[MAX_ORDER]; |
141 | 138 | ||
142 | 139 | ||
@@ -220,6 +217,16 @@ struct zone { | |||
220 | /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */ | 217 | /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */ |
221 | unsigned long zone_start_pfn; | 218 | unsigned long zone_start_pfn; |
222 | 219 | ||
220 | /* | ||
221 | * zone_start_pfn, spanned_pages and present_pages are all | ||
222 | * protected by span_seqlock. It is a seqlock because it has | ||
223 | * to be read outside of zone->lock, and it is done in the main | ||
224 | * allocator path. But, it is written quite infrequently. | ||
225 | * | ||
226 | * The lock is declared along with zone->lock because it is | ||
227 | * frequently read in proximity to zone->lock. It's good to | ||
228 | * give them a chance of being in the same cacheline. | ||
229 | */ | ||
223 | unsigned long spanned_pages; /* total size, including holes */ | 230 | unsigned long spanned_pages; /* total size, including holes */ |
224 | unsigned long present_pages; /* amount of memory (excluding holes) */ | 231 | unsigned long present_pages; /* amount of memory (excluding holes) */ |
225 | 232 | ||
@@ -273,6 +280,16 @@ typedef struct pglist_data { | |||
273 | struct page *node_mem_map; | 280 | struct page *node_mem_map; |
274 | #endif | 281 | #endif |
275 | struct bootmem_data *bdata; | 282 | struct bootmem_data *bdata; |
283 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
284 | /* | ||
285 | * Must be held any time you expect node_start_pfn, node_present_pages | ||
286 | * or node_spanned_pages stay constant. Holding this will also | ||
287 | * guarantee that any pfn_valid() stays that way. | ||
288 | * | ||
289 | * Nests above zone->lock and zone->size_seqlock. | ||
290 | */ | ||
291 | spinlock_t node_size_lock; | ||
292 | #endif | ||
276 | unsigned long node_start_pfn; | 293 | unsigned long node_start_pfn; |
277 | unsigned long node_present_pages; /* total number of physical pages */ | 294 | unsigned long node_present_pages; /* total number of physical pages */ |
278 | unsigned long node_spanned_pages; /* total size of physical page | 295 | unsigned long node_spanned_pages; /* total size of physical page |
@@ -293,6 +310,8 @@ typedef struct pglist_data { | |||
293 | #endif | 310 | #endif |
294 | #define nid_page_nr(nid, pagenr) pgdat_page_nr(NODE_DATA(nid),(pagenr)) | 311 | #define nid_page_nr(nid, pagenr) pgdat_page_nr(NODE_DATA(nid),(pagenr)) |
295 | 312 | ||
313 | #include <linux/memory_hotplug.h> | ||
314 | |||
296 | extern struct pglist_data *pgdat_list; | 315 | extern struct pglist_data *pgdat_list; |
297 | 316 | ||
298 | void __get_zone_counts(unsigned long *active, unsigned long *inactive, | 317 | void __get_zone_counts(unsigned long *active, unsigned long *inactive, |
@@ -302,7 +321,7 @@ void get_zone_counts(unsigned long *active, unsigned long *inactive, | |||
302 | void build_all_zonelists(void); | 321 | void build_all_zonelists(void); |
303 | void wakeup_kswapd(struct zone *zone, int order); | 322 | void wakeup_kswapd(struct zone *zone, int order); |
304 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, | 323 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, |
305 | int alloc_type, int can_try_harder, int gfp_high); | 324 | int classzone_idx, int alloc_flags); |
306 | 325 | ||
307 | #ifdef CONFIG_HAVE_MEMORY_PRESENT | 326 | #ifdef CONFIG_HAVE_MEMORY_PRESENT |
308 | void memory_present(int nid, unsigned long start, unsigned long end); | 327 | void memory_present(int nid, unsigned long start, unsigned long end); |
@@ -406,7 +425,9 @@ int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, struct file *, | |||
406 | 425 | ||
407 | #include <linux/topology.h> | 426 | #include <linux/topology.h> |
408 | /* Returns the number of the current Node. */ | 427 | /* Returns the number of the current Node. */ |
428 | #ifndef numa_node_id | ||
409 | #define numa_node_id() (cpu_to_node(raw_smp_processor_id())) | 429 | #define numa_node_id() (cpu_to_node(raw_smp_processor_id())) |
430 | #endif | ||
410 | 431 | ||
411 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 432 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
412 | 433 | ||
@@ -426,12 +447,12 @@ extern struct pglist_data contig_page_data; | |||
426 | #include <asm/sparsemem.h> | 447 | #include <asm/sparsemem.h> |
427 | #endif | 448 | #endif |
428 | 449 | ||
429 | #if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED) | 450 | #if BITS_PER_LONG == 32 |
430 | /* | 451 | /* |
431 | * with 32 bit page->flags field, we reserve 8 bits for node/zone info. | 452 | * with 32 bit page->flags field, we reserve 9 bits for node/zone info. |
432 | * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes. | 453 | * there are 4 zones (3 bits) and this leaves 9-3=6 bits for nodes. |
433 | */ | 454 | */ |
434 | #define FLAGS_RESERVED 8 | 455 | #define FLAGS_RESERVED 9 |
435 | 456 | ||
436 | #elif BITS_PER_LONG == 64 | 457 | #elif BITS_PER_LONG == 64 |
437 | /* | 458 | /* |
@@ -509,6 +530,7 @@ static inline struct mem_section *__nr_to_section(unsigned long nr) | |||
509 | return NULL; | 530 | return NULL; |
510 | return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK]; | 531 | return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK]; |
511 | } | 532 | } |
533 | extern int __section_nr(struct mem_section* ms); | ||
512 | 534 | ||
513 | /* | 535 | /* |
514 | * We use the lower bits of the mem_map pointer to store | 536 | * We use the lower bits of the mem_map pointer to store |