diff options
author | Andy Whitcroft <apw@shadowen.org> | 2007-10-16 04:24:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:42:51 -0400 |
commit | 540557b9439ec19668553830c90222f9fb0c2e95 (patch) | |
tree | 07dfa0e88580d4101dbb11ebc59348233e18b2f0 | |
parent | cd881a6b22902b356cacf8fd2e4e895871068eec (diff) |
sparsemem: record when a section has a valid mem_map
We have flags to indicate whether a section actually has a valid mem_map
associated with it. This is never set and we rely solely on the present bit
to indicate a section is valid. By definition a section is not valid if it
has no mem_map and there is a window during init where the present bit is set
but there is no mem_map, during which pfn_valid() will return true
incorrectly.
Use the existing SECTION_HAS_MEM_MAP flag to indicate the presence of a valid
mem_map. Switch valid_section{,_nr} and pfn_valid() to this bit. Add a new
present_section{,_nr} and pfn_present() interfaces for those users who care to
know that a section is going to be valid.
[akpm@linux-foundation.org: coding-syle fixes]
Signed-off-by: Andy Whitcroft <apw@shadowen.org>
Acked-by: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <clameter@sgi.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Andi Kleen <ak@suse.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/base/memory.c | 6 | ||||
-rw-r--r-- | include/linux/mmzone.h | 16 | ||||
-rw-r--r-- | mm/sparse.c | 9 |
3 files changed, 22 insertions, 9 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 7a1390cd6aad..c41d0728efe2 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
@@ -238,7 +238,7 @@ store_mem_state(struct sys_device *dev, const char *buf, size_t count) | |||
238 | mem = container_of(dev, struct memory_block, sysdev); | 238 | mem = container_of(dev, struct memory_block, sysdev); |
239 | phys_section_nr = mem->phys_index; | 239 | phys_section_nr = mem->phys_index; |
240 | 240 | ||
241 | if (!valid_section_nr(phys_section_nr)) | 241 | if (!present_section_nr(phys_section_nr)) |
242 | goto out; | 242 | goto out; |
243 | 243 | ||
244 | if (!strncmp(buf, "online", min((int)count, 6))) | 244 | if (!strncmp(buf, "online", min((int)count, 6))) |
@@ -418,7 +418,7 @@ int register_new_memory(struct mem_section *section) | |||
418 | 418 | ||
419 | int unregister_memory_section(struct mem_section *section) | 419 | int unregister_memory_section(struct mem_section *section) |
420 | { | 420 | { |
421 | if (!valid_section(section)) | 421 | if (!present_section(section)) |
422 | return -EINVAL; | 422 | return -EINVAL; |
423 | 423 | ||
424 | return remove_memory_block(0, section, 0); | 424 | return remove_memory_block(0, section, 0); |
@@ -443,7 +443,7 @@ int __init memory_dev_init(void) | |||
443 | * during boot and have been initialized | 443 | * during boot and have been initialized |
444 | */ | 444 | */ |
445 | for (i = 0; i < NR_MEM_SECTIONS; i++) { | 445 | for (i = 0; i < NR_MEM_SECTIONS; i++) { |
446 | if (!valid_section_nr(i)) | 446 | if (!present_section_nr(i)) |
447 | continue; | 447 | continue; |
448 | err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0); | 448 | err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0); |
449 | if (!ret) | 449 | if (!ret) |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 4e5627379b09..f21e5951038b 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -771,12 +771,17 @@ static inline struct page *__section_mem_map_addr(struct mem_section *section) | |||
771 | return (struct page *)map; | 771 | return (struct page *)map; |
772 | } | 772 | } |
773 | 773 | ||
774 | static inline int valid_section(struct mem_section *section) | 774 | static inline int present_section(struct mem_section *section) |
775 | { | 775 | { |
776 | return (section && (section->section_mem_map & SECTION_MARKED_PRESENT)); | 776 | return (section && (section->section_mem_map & SECTION_MARKED_PRESENT)); |
777 | } | 777 | } |
778 | 778 | ||
779 | static inline int section_has_mem_map(struct mem_section *section) | 779 | static inline int present_section_nr(unsigned long nr) |
780 | { | ||
781 | return present_section(__nr_to_section(nr)); | ||
782 | } | ||
783 | |||
784 | static inline int valid_section(struct mem_section *section) | ||
780 | { | 785 | { |
781 | return (section && (section->section_mem_map & SECTION_HAS_MEM_MAP)); | 786 | return (section && (section->section_mem_map & SECTION_HAS_MEM_MAP)); |
782 | } | 787 | } |
@@ -798,6 +803,13 @@ static inline int pfn_valid(unsigned long pfn) | |||
798 | return valid_section(__nr_to_section(pfn_to_section_nr(pfn))); | 803 | return valid_section(__nr_to_section(pfn_to_section_nr(pfn))); |
799 | } | 804 | } |
800 | 805 | ||
806 | static inline int pfn_present(unsigned long pfn) | ||
807 | { | ||
808 | if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS) | ||
809 | return 0; | ||
810 | return present_section(__nr_to_section(pfn_to_section_nr(pfn))); | ||
811 | } | ||
812 | |||
801 | /* | 813 | /* |
802 | * These are _only_ used during initialisation, therefore they | 814 | * These are _only_ used during initialisation, therefore they |
803 | * can use __initdata ... They could have names to indicate | 815 | * can use __initdata ... They could have names to indicate |
diff --git a/mm/sparse.c b/mm/sparse.c index e8f36e4796d0..54f3940406cb 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -176,7 +176,7 @@ unsigned long __init node_memmap_size_bytes(int nid, unsigned long start_pfn, | |||
176 | if (nid != early_pfn_to_nid(pfn)) | 176 | if (nid != early_pfn_to_nid(pfn)) |
177 | continue; | 177 | continue; |
178 | 178 | ||
179 | if (pfn_valid(pfn)) | 179 | if (pfn_present(pfn)) |
180 | nr_pages += PAGES_PER_SECTION; | 180 | nr_pages += PAGES_PER_SECTION; |
181 | } | 181 | } |
182 | 182 | ||
@@ -206,11 +206,12 @@ struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pn | |||
206 | static int __meminit sparse_init_one_section(struct mem_section *ms, | 206 | static int __meminit sparse_init_one_section(struct mem_section *ms, |
207 | unsigned long pnum, struct page *mem_map) | 207 | unsigned long pnum, struct page *mem_map) |
208 | { | 208 | { |
209 | if (!valid_section(ms)) | 209 | if (!present_section(ms)) |
210 | return -EINVAL; | 210 | return -EINVAL; |
211 | 211 | ||
212 | ms->section_mem_map &= ~SECTION_MAP_MASK; | 212 | ms->section_mem_map &= ~SECTION_MAP_MASK; |
213 | ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum); | 213 | ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum) | |
214 | SECTION_HAS_MEM_MAP; | ||
214 | 215 | ||
215 | return 1; | 216 | return 1; |
216 | } | 217 | } |
@@ -256,7 +257,7 @@ void __init sparse_init(void) | |||
256 | struct page *map; | 257 | struct page *map; |
257 | 258 | ||
258 | for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) { | 259 | for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) { |
259 | if (!valid_section_nr(pnum)) | 260 | if (!present_section_nr(pnum)) |
260 | continue; | 261 | continue; |
261 | 262 | ||
262 | map = sparse_early_mem_map_alloc(pnum); | 263 | map = sparse_early_mem_map_alloc(pnum); |