Commit ed2f240094f900833ac06f533ab8bbcf0a1e8199
Committed by
Linus Torvalds
1 parent
cc71aba348
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
memory-hotplug: add sysfs valid_zones attribute
Currently memory-hotplug has two limits: 1. If the memory block is in ZONE_NORMAL, you can change it to ZONE_MOVABLE, but this memory block must be adjacent to ZONE_MOVABLE. 2. If the memory block is in ZONE_MOVABLE, you can change it to ZONE_NORMAL, but this memory block must be adjacent to ZONE_NORMAL. With this patch, we can easy to know a memory block can be onlined to which zone, and don't need to know the above two limits. Updated the related Documentation. [akpm@linux-foundation.org: use conventional comment layout] [akpm@linux-foundation.org: fix build with CONFIG_MEMORY_HOTREMOVE=n] [akpm@linux-foundation.org: remove unused local zone_prev] Signed-off-by: Zhang Zhen <zhenzhang.zhang@huawei.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: David Rientjes <rientjes@google.com> Cc: Toshi Kani <toshi.kani@hp.com> Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Wang Nan <wangnan0@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 5 changed files with 62 additions and 2 deletions Side-by-side Diff
Documentation/ABI/testing/sysfs-devices-memory
... | ... | @@ -61,6 +61,14 @@ |
61 | 61 | http://www.ibm.com/developerworks/wikis/display/LinuxP/powerpc-utils |
62 | 62 | |
63 | 63 | |
64 | +What: /sys/devices/system/memory/memoryX/valid_zones | |
65 | +Date: July 2014 | |
66 | +Contact: Zhang Zhen <zhenzhang.zhang@huawei.com> | |
67 | +Description: | |
68 | + The file /sys/devices/system/memory/memoryX/valid_zones is | |
69 | + read-only and is designed to show which zone this memory | |
70 | + block can be onlined to. | |
71 | + | |
64 | 72 | What: /sys/devices/system/memoryX/nodeY |
65 | 73 | Date: October 2009 |
66 | 74 | Contact: Linux Memory Management list <linux-mm@kvack.org> |
Documentation/memory-hotplug.txt
... | ... | @@ -155,6 +155,7 @@ |
155 | 155 | /sys/devices/system/memory/memoryXXX/phys_device |
156 | 156 | /sys/devices/system/memory/memoryXXX/state |
157 | 157 | /sys/devices/system/memory/memoryXXX/removable |
158 | +/sys/devices/system/memory/memoryXXX/valid_zones | |
158 | 159 | |
159 | 160 | 'phys_index' : read-only and contains memory block id, same as XXX. |
160 | 161 | 'state' : read-write |
... | ... | @@ -170,6 +171,15 @@ |
170 | 171 | block is removable and a value of 0 indicates that |
171 | 172 | it is not removable. A memory block is removable only if |
172 | 173 | every section in the block is removable. |
174 | +'valid_zones' : read-only: designed to show which zones this memory block | |
175 | + can be onlined to. | |
176 | + The first column shows it's default zone. | |
177 | + "memory6/valid_zones: Normal Movable" shows this memoryblock | |
178 | + can be onlined to ZONE_NORMAL by default and to ZONE_MOVABLE | |
179 | + by online_movable. | |
180 | + "memory7/valid_zones: Movable Normal" shows this memoryblock | |
181 | + can be onlined to ZONE_MOVABLE by default and to ZONE_NORMAL | |
182 | + by online_kernel. | |
173 | 183 | |
174 | 184 | NOTE: |
175 | 185 | These directories/files appear after physical memory hotplug phase. |
... | ... | @@ -408,7 +418,6 @@ |
408 | 418 | - allowing memory hot-add to ZONE_MOVABLE. maybe we need some switch like |
409 | 419 | sysctl or new control file. |
410 | 420 | - showing memory block and physical device relationship. |
411 | - - showing memory block is under ZONE_MOVABLE or not | |
412 | 421 | - test and make it better memory offlining. |
413 | 422 | - support HugeTLB page migration and offlining. |
414 | 423 | - memmap removing at memory offline. |
drivers/base/memory.c
... | ... | @@ -373,6 +373,45 @@ |
373 | 373 | return sprintf(buf, "%d\n", mem->phys_device); |
374 | 374 | } |
375 | 375 | |
376 | +#ifdef CONFIG_MEMORY_HOTREMOVE | |
377 | +static ssize_t show_valid_zones(struct device *dev, | |
378 | + struct device_attribute *attr, char *buf) | |
379 | +{ | |
380 | + struct memory_block *mem = to_memory_block(dev); | |
381 | + unsigned long start_pfn, end_pfn; | |
382 | + unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; | |
383 | + struct page *first_page; | |
384 | + struct zone *zone; | |
385 | + | |
386 | + start_pfn = section_nr_to_pfn(mem->start_section_nr); | |
387 | + end_pfn = start_pfn + nr_pages; | |
388 | + first_page = pfn_to_page(start_pfn); | |
389 | + | |
390 | + /* The block contains more than one zone can not be offlined. */ | |
391 | + if (!test_pages_in_a_zone(start_pfn, end_pfn)) | |
392 | + return sprintf(buf, "none\n"); | |
393 | + | |
394 | + zone = page_zone(first_page); | |
395 | + | |
396 | + if (zone_idx(zone) == ZONE_MOVABLE - 1) { | |
397 | + /*The mem block is the last memoryblock of this zone.*/ | |
398 | + if (end_pfn == zone_end_pfn(zone)) | |
399 | + return sprintf(buf, "%s %s\n", | |
400 | + zone->name, (zone + 1)->name); | |
401 | + } | |
402 | + | |
403 | + if (zone_idx(zone) == ZONE_MOVABLE) { | |
404 | + /*The mem block is the first memoryblock of ZONE_MOVABLE.*/ | |
405 | + if (start_pfn == zone->zone_start_pfn) | |
406 | + return sprintf(buf, "%s %s\n", | |
407 | + zone->name, (zone - 1)->name); | |
408 | + } | |
409 | + | |
410 | + return sprintf(buf, "%s\n", zone->name); | |
411 | +} | |
412 | +static DEVICE_ATTR(valid_zones, 0444, show_valid_zones, NULL); | |
413 | +#endif | |
414 | + | |
376 | 415 | static DEVICE_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL); |
377 | 416 | static DEVICE_ATTR(state, 0644, show_mem_state, store_mem_state); |
378 | 417 | static DEVICE_ATTR(phys_device, 0444, show_phys_device, NULL); |
... | ... | @@ -523,6 +562,9 @@ |
523 | 562 | &dev_attr_state.attr, |
524 | 563 | &dev_attr_phys_device.attr, |
525 | 564 | &dev_attr_removable.attr, |
565 | +#ifdef CONFIG_MEMORY_HOTREMOVE | |
566 | + &dev_attr_valid_zones.attr, | |
567 | +#endif | |
526 | 568 | NULL |
527 | 569 | }; |
528 | 570 |
include/linux/memory_hotplug.h
... | ... | @@ -84,6 +84,7 @@ |
84 | 84 | extern int add_one_highpage(struct page *page, int pfn, int bad_ppro); |
85 | 85 | /* VM interface that may be used by firmware interface */ |
86 | 86 | extern int online_pages(unsigned long, unsigned long, int); |
87 | +extern int test_pages_in_a_zone(unsigned long, unsigned long); | |
87 | 88 | extern void __offline_isolated_pages(unsigned long, unsigned long); |
88 | 89 | |
89 | 90 | typedef void (*online_page_callback_t)(struct page *page); |
mm/memory_hotplug.c
... | ... | @@ -1307,7 +1307,7 @@ |
1307 | 1307 | /* |
1308 | 1308 | * Confirm all pages in a range [start, end) is belongs to the same zone. |
1309 | 1309 | */ |
1310 | -static int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn) | |
1310 | +int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn) | |
1311 | 1311 | { |
1312 | 1312 | unsigned long pfn; |
1313 | 1313 | struct zone *zone = NULL; |