This patch series aims to support physical memory hot-remove.
[RFC PATCH v4 1/13] memory-hotplug : rename remove_memory to offline_memory
[RFC PATCH v4 2/13] memory-hotplug : add physical memory hotplug code to acpi_memory_device_remove
[RFC PATCH v4 3/13] memory-hotplug : check whether memory is present or not
[RFC PATCH v4 4/13] memory-hotplug : remove /sys/firmware/memmap/X sysfs
[RFC PATCH v4 5/13] memory-hotplug : does not release memory region in PAGES_PER_SECTION chunks
[RFC PATCH v4 6/13] memory-hotplug : add memory_block_release
[RFC PATCH v4 7/13] memory-hotplug : remove_memory calls __remove_pages
[RFC PATCH v4 8/13] memory-hotplug : check page type in get_page_bootmem
[RFC PATCH v4 9/13] memory-hotplug : move register_page_bootmem_info_node and put_page_bootmem for
sparse-vmemmap4
[RFC PATCH v4 10/13] memory-hotplug : implement register_page_bootmem_info_section of sparse-vmemmap
[RFC PATCH v4 11/13] memory-hotplug : free memmap of sparse-vmemmap
[RFC PATCH v4 12/13] memory-hotplug : add node_device_release
[RFC PATCH v4 13/13] memory-hotplug : remove sysfs file of node
Even if you apply these patches, you cannot remove the physical memory
completely since these patches are still under development. But other
components can be removed. I want you to cooperate to improve the
physical memory hot-remove. So please review these patches and give
your comment/idea.
The patches can free/remove following things:
- acpi_memory_info : [RFC PATCH 2/13]
- /sys/firmware/memmap/X/{end, start, type} : [RFC PATCH 4/13]
- iomem_resource : [RFC PATCH 5/13]
- mem_section and related sysfs files : [RFC PATCH 6-11/13]
- node and related sysfs files : [RFC PATCH 12-13/13]
The patches cannot do following things yet:
- page table of removed memory
If you find lack of function for physical memory hot-remove, please let me
know.
change log of v4:
* remove "memory-hotplug : unify argument of firmware_map_add_early/hotplug"
from the patch series, since the patch is a bugfix. It is being disccussed
on other thread. But for testing the patch series, the patch is needed.
So I added the patch as [PATCH 0/13].
[RFC PATCH v4 2/13]
* check memory is online or not at remove_memory()
* add memory_add_physaddr_to_nid() to acpi_memory_device_remove() for
getting node id
[RFC PATCH v4 3/13]
* create new patch : check memory is online or not at online_pages()
[RFC PATCH v4 4/13]
* add __ref section to remove_memory()
* call firmware_map_remove_entry() before remove_sysfs_fw_map_entry()
[RFC PATCH v4 11/13]
* rewrite register_page_bootmem_memmap() for removing page used as PT/PMD
change log of v3:
* rebase to 3.5.0-rc6
[RFC PATCH v2 2/13]
* remove extra kobject_put()
* The patch was commented by Wen. Wen's comment is
"acpi_memory_device_remove() should ignore a return value of
remove_memory() since caller does not care the return value".
But I did not change it since I think caller should care the
return value. And I am trying to fix it as follow:
https://lkml.org/lkml/2012/7/5/624
[RFC PATCH v2 4/13]
* remove a firmware_memmap_entry allocated by kzmalloc()
change log of v2:
[RFC PATCH v2 2/13]
* check whether memory block is offline or not before calling offline_memory()
* check whether section is valid or not in is_memblk_offline()
* call kobject_put() for each memory_block in is_memblk_offline()
[RFC PATCH v2 3/13]
* unify the end argument of firmware_map_add_early/hotplug
[RFC PATCH v2 4/13]
* add release_firmware_map_entry() for freeing firmware_map_entry
[RFC PATCH v2 6/13]
* add release_memory_block() for freeing memory_block
[RFC PATCH v2 11/13]
* fix wrong arguments of free_pages()
---
arch/powerpc/platforms/pseries/hotplug-memory.c | 16 +-
arch/x86/mm/init_64.c | 144 ++++++++++++++++++++++++
drivers/acpi/acpi_memhotplug.c | 28 ++++
drivers/base/memory.c | 54 ++++++++-
drivers/base/node.c | 7 +
drivers/firmware/memmap.c | 78 ++++++++++++-
include/linux/firmware-map.h | 6 +
include/linux/memory.h | 5
include/linux/memory_hotplug.h | 17 --
include/linux/mm.h | 5
mm/memory_hotplug.c | 98 ++++++++++++----
mm/sparse.c | 5
12 files changed, 414 insertions(+), 49 deletions(-)
There are two ways to create /sys/firmware/memmap/X sysfs:
- firmware_map_add_early
When the system starts, it is calledd from e820_reserve_resources()
- firmware_map_add_hotplug
When the memory is hot plugged, it is called from add_memory()
But these functions are called without unifying value of end argument as below:
- end argument of firmware_map_add_early() : start + size - 1
- end argument of firmware_map_add_hogplug() : start + size
The patch unifies them to "start + size". Even if applying the patch,
/sys/firmware/memmap/X/end file content does not change.
CC: Thomas Gleixner <redacted>
CC: Ingo Molnar <mingo@kernel.org>
CC: H. Peter Anvin <hpa@zytor.com>
CC: Tejun Heo <tj@kernel.org>
CC: Andrew Morton <akpm@linux-foundation.org>
Reviewed-by: Dave Hansen <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/x86/kernel/e820.c | 2 +-
drivers/firmware/memmap.c | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
Index: linux-3.5-rc6/arch/x86/kernel/e820.c
===================================================================
remove_memory() does not remove memory but just offlines memory. The patch
changes name of it to offline_memory().
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/acpi/acpi_memhotplug.c | 2 +-
drivers/base/memory.c | 4 ++--
include/linux/memory_hotplug.h | 2 +-
mm/memory_hotplug.c | 6 +++---
4 files changed, 7 insertions(+), 7 deletions(-)
Index: linux-3.5-rc4/drivers/acpi/acpi_memhotplug.c
===================================================================
@@ -998,6 +998,28 @@ int offline_memory(u64 start, u64 size)end_pfn=start_pfn+PFN_DOWN(size);returnoffline_pages(start_pfn,end_pfn,120*HZ);}++intremove_memory(intnid,u64start,u64size)+{+intret=-EBUSY;+lock_memory_hotplug();+/*+*Thememorymightbecomeonlinebyothertask,evenifyouoffineit.+*Sowecheckwhetherthecpuhasbeenonlinedornot.+*/+if(!is_memblk_offline(start,size)){+pr_warn("memory removing [mem %#010llx-%#010llx] failed, "+"because the memmory range is online\n",+start,start+size);+ret=-EAGAIN;+}++unlock_memory_hotplug();+returnret;++}+EXPORT_SYMBOL_GPL(remove_memory);+#elseintoffline_memory(u64start,u64size){
If system supports memory hot-remove, online_pages() may online removed pages.
So online_pages() need to check whether onlining pages are present or not.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
include/linux/mmzone.h | 21 +++++++++++++++++++++
mm/memory_hotplug.c | 13 +++++++++++++
2 files changed, 34 insertions(+)
Index: linux-3.5-rc6/include/linux/mmzone.h
===================================================================
@@ -467,6 +467,19 @@ int __ref online_pages(unsigned long pfnstructmemory_notifyarg;lock_memory_hotplug();+/*+*Ifsystemsupportsmemoryhot-remove,thememorymayhavebeen+*removed.Sowecheckwhetherthememoryhasbeenremovedornot.+*+*Note:WhenCONFIG_SPARSEMEMisdefined,pfns_present()become+*effective.IfCONFIG_SPARSEMEMisnotdefined,pfns_present()+*alwaysreturns0.+*/+ret=pfns_present(pfn,nr_pages);+if(ret){+unlock_memory_hotplug();+returnret;+}arg.start_pfn=pfn;arg.nr_pages=nr_pages;arg.status_change_nid=-1;
When (hot)adding memory into system, /sys/firmware/memmap/X/{end, start, type}
sysfs files are created. But there is no code to remove these files. The patch
implements the function to remove them.
Note : The code does not free firmware_map_entry since there is no way to free
memory which is allocated by bootmem.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 78 ++++++++++++++++++++++++++++++++++++++++++-
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 9 +++-
3 files changed, 90 insertions(+), 3 deletions(-)
Index: linux-3.5-rc6/mm/memory_hotplug.c
===================================================================
@@ -1012,9 +1012,9 @@ int offline_memory(u64 start, u64 size)returnoffline_pages(start_pfn,end_pfn,120*HZ);}-intremove_memory(intnid,u64start,u64size)+int__refremove_memory(intnid,u64start,u64size){-intret=-EBUSY;+intret=0;lock_memory_hotplug();/**Thememorymightbecomeonlinebyothertask,evenifyouoffineit.
@@ -1025,8 +1025,13 @@ int remove_memory(int nid, u64 start, u6"because the memmory range is online\n",start,start+size);ret=-EAGAIN;+gotoout;}+/* remove memmap entry */+firmware_map_remove(start,start+size,"System RAM");++out:unlock_memory_hotplug();returnret;
@@ -79,7 +80,22 @@ static const struct sysfs_ops memmap_att.show=memmap_attr_show,};+#define to_memmap_entry(obj) container_of(obj, struct firmware_map_entry, kobj)++staticvoidrelease_firmware_map_entry(structkobject*kobj)+{+structfirmware_map_entry*entry=to_memmap_entry(kobj);+structpage*page;++page=virt_to_page(entry);+if(PageSlab(page)||PageCompound(page))+kfree(entry);++/* There is no way to free memory allocated from bootmem*/+}+staticstructkobj_typememmap_ktype={+.release=release_firmware_map_entry,.sysfs_ops=&memmap_attr_ops,.default_attrs=def_attrs,};
@@ -123,6 +139,16 @@ static int firmware_map_add_entry(u64 streturn0;}+/**+*firmware_map_remove_entry()-Doestherealworktoremoveafirmware+*memmapentry.+*@entry:removedentry.+**/+staticinlinevoidfirmware_map_remove_entry(structfirmware_map_entry*entry)+{+list_del(&entry->list);+}+/**Addmemmapentryonsysfs*/
@@ -144,6 +170,31 @@ static int add_sysfs_fw_map_entry(structreturn0;}+/*+*Removememmapentryonsysfs+*/+staticinlinevoidremove_sysfs_fw_map_entry(structfirmware_map_entry*entry)+{+kobject_put(&entry->kobj);+}++/*+*Searchmemmapentry+*/++structfirmware_map_entry*__meminit+find_firmware_map_entry(u64start,u64end,constchar*type)+{+structfirmware_map_entry*entry;++list_for_each_entry(entry,&map_entries,list)+if((entry->start==start)&&(entry->end==end)&&+(!strcmp(entry->type,type)))+returnentry;++returnNULL;+}+/***firmware_map_add_hotplug()-Addsafirmwaremappingentrywhenwedo*memoryhotplug.
@@ -196,6 +247,32 @@ int __init firmware_map_add_early(u64 streturnfirmware_map_add_entry(start,end,type,entry);}+/**+*firmware_map_remove()-removeafirmwaremappingentry+*@start:Startofthememoryrange.+*@end:Endofthememoryrange.+*@type:Typeofthememoryrange.+*+*removesafirmwaremappingentry.+*+*Returns0onsuccess,or-EINVALifnoentry.+**/+int__meminitfirmware_map_remove(u64start,u64end,constchar*type)+{+structfirmware_map_entry*entry;++entry=find_firmware_map_entry(start,end-1,type);+if(!entry)+return-EINVAL;++firmware_map_remove_entry(entry);++/* remove the memmap entry */+remove_sysfs_fw_map_entry(entry);++return0;+}+/**Sysfsfunctions-------------------------------------------------------------*/
The patch adds __remove_pages() to remove_memory(). Then the range of
phys_start_pfn argument and nr_pages argument in __remove_pagse() may
have different zone. So zone argument is removed from __remove_pages()
and __remove_pages() caluculates zone in each section.
When CONFIG_SPARSEMEM_VMEMMAP is defined, there is no way to remove a memmap.
So __remove_section only calls unregister_memory_section().
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/powerpc/platforms/pseries/hotplug-memory.c | 5 +----
include/linux/memory_hotplug.h | 3 +--
mm/memory_hotplug.c | 19 ++++++++++++-------
3 files changed, 14 insertions(+), 13 deletions(-)
Index: linux-3.5-rc6/mm/memory_hotplug.c
===================================================================
@@ -363,6 +366,7 @@ int __remove_pages(struct zone *zone, unsections_to_remove=nr_pages/PAGES_PER_SECTION;for(i=0;i<sections_to_remove;i++){unsignedlongpfn=phys_start_pfn+i*PAGES_PER_SECTION;+zone=page_zone(pfn_to_page(pfn));ret=__remove_section(zone,__pfn_to_section(pfn));if(ret)break;
@@ -89,8 +89,7 @@ extern bool is_pageblock_removable_noloc/* reasonably generic interface to expand the physical pages in a zone */externint__add_pages(intnid,structzone*zone,unsignedlongstart_pfn,unsignedlongnr_pages);-externint__remove_pages(structzone*zone,unsignedlongstart_pfn,-unsignedlongnr_pages);+externint__remove_pages(unsignedlongstart_pfn,unsignedlongnr_pages);#ifdef CONFIG_NUMAexternintmemory_add_physaddr_to_nid(u64start);
Since applying a patch(de7f0cba96786c), release_mem_region() has been changed
as called in PAGES_PER_SECTION chunks because register_memory_resource() is
called in PAGES_PER_SECTION chunks by add_memory(). But it seems firmware
dependency. If CRS are written in the PAGES_PER_SECTION chunks in ACPI DSDT
Table, register_memory_resource() is called in PAGES_PER_SECTION chunks.
But if CRS are written in the DIMM unit in ACPI DSDT Table,
register_memory_resource() is called in DIMM unit. So release_mem_region()
should not be called in PAGES_PER_SECTION chunks. The patch fixes it.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/powerpc/platforms/pseries/hotplug-memory.c | 13 +++++++++----
mm/memory_hotplug.c | 4 ++--
2 files changed, 11 insertions(+), 6 deletions(-)
Index: linux-3.5-rc6/mm/memory_hotplug.c
===================================================================
@@ -358,11 +358,11 @@ int __remove_pages(struct zone *zone, unBUG_ON(phys_start_pfn&~PAGE_SECTION_MASK);BUG_ON(nr_pages%PAGES_PER_SECTION);+release_mem_region(phys_start_pfn<<PAGE_SHIFT,nr_pages*PAGE_SIZE);+sections_to_remove=nr_pages/PAGES_PER_SECTION;for(i=0;i<sections_to_remove;i++){unsignedlongpfn=phys_start_pfn+i*PAGES_PER_SECTION;-release_mem_region(pfn<<PAGE_SHIFT,-PAGES_PER_SECTION<<PAGE_SHIFT);ret=__remove_section(zone,__pfn_to_section(pfn));if(ret)break;
When calling remove_memory_block(), the function shows following message at
device_release().
Device 'memory528' does not have a release() function, it is broken and must
be fixed.
remove_memory_block() calls kfree(mem). I think it shouled be called from
device_release(). So the patch implements memory_block_release()
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/base/memory.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
Index: linux-3.5-rc6/drivers/base/memory.c
===================================================================
@@ -119,6 +128,7 @@ int register_memory(struct memory_block memory->dev.bus=&memory_subsys;memory->dev.id=memory->start_section_nr/sections_per_block;+memory->dev.release=release_memory_block;error=device_register(&memory->dev);returnerror;
@@ -669,7 +679,6 @@ int remove_memory_block(unsigned long nomem_remove_simple_file(mem,phys_device);mem_remove_simple_file(mem,removable);unregister_memory(mem);-kfree(mem);}elsekobject_put(&mem->dev.kobj);
There is a possibility that get_page_bootmem() is called to the same page many
times. So when get_page_bootmem is called to the same page, the function only
increments page->_count.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
mm/memory_hotplug.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
Index: linux-3.5-rc6/mm/memory_hotplug.c
===================================================================
For implementing register_page_bootmem_info_node of sparse-vmemmap,
register_page_bootmem_info_node and put_page_bootmem are moved to
memory_hotplug.c
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
include/linux/memory_hotplug.h | 9 ---------
mm/memory_hotplug.c | 8 ++++++--
2 files changed, 6 insertions(+), 11 deletions(-)
Index: linux-3.5-rc6/include/linux/memory_hotplug.h
===================================================================
All pages of virtual mapping in removed memory cannot be freed, since some pages
used as PGD/PUD includes not only removed memory but also other memory. So the
patch checks whether page can be freed or not.
How to check whether page can be freed or not?
1. When removing memory, the page structs of the revmoved memory are filled
with 0FD.
2. All page structs are filled with 0xFD on PT/PMD, PT/PMD can be cleared.
In this case, the page used as PT/PMD can be freed.
Applying patch, __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is integrated
into one. So __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is deleted.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/x86/mm/init_64.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mm.h | 2
mm/memory_hotplug.c | 19 -------
mm/sparse.c | 5 +-
4 files changed, 128 insertions(+), 19 deletions(-)
Index: linux-3.5-rc6/include/linux/mm.h
===================================================================
@@ -614,12 +614,13 @@ static inline struct page *kmalloc_secti/* This will make the necessary allocations eventually. */returnsparse_mem_map_populate(pnum,nid);}-staticvoid__kfree_section_memmap(structpage*memmap,unsignedlongnr_pages)+staticvoid__kfree_section_memmap(structpage*page,unsignedlongnr_pages){-return;/* XXX: Not implemented yet */+vmemmap_kfree(page,nr_pages);}staticvoidfree_map_bootmem(structpage*page,unsignedlongnr_pages){+vmemmap_free_bootmem(page,nr_pages);}#elsestaticstructpage*__kmalloc_section_memmap(unsignedlongnr_pages)
@@ -300,7 +300,6 @@ static int __meminit __add_section(int nreturnregister_new_memory(nid,__pfn_to_section(phys_start_pfn));}-#ifdef CONFIG_SPARSEMEM_VMEMMAPstaticint__remove_section(structzone*zone,structmem_section*ms){intret=-EINVAL;
@@ -309,29 +308,15 @@ static int __remove_section(struct zone returnret;ret=unregister_memory_section(ms);--returnret;-}-#else-staticint__remove_section(structzone*zone,structmem_section*ms)-{-unsignedlongflags;-structpglist_data*pgdat=zone->zone_pgdat;-intret=-EINVAL;--if(!valid_section(ms))-returnret;--ret=unregister_memory_section(ms);if(ret)returnret;pgdat_resize_lock(pgdat,&flags);sparse_remove_one_section(zone,ms);pgdat_resize_unlock(pgdat,&flags);-return0;++returnret;}-#endif/**Reasonablygenericfunctionforaddingmemory.Itis
When calling unregister_node(), the function shows following message at
device_release().
Device 'node2' does not have a release() function, it is broken and must be
fixed.
So the patch implements node_device_release()
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/base/node.c | 7 +++++++
1 file changed, 7 insertions(+)
Index: linux-3.5-rc6/drivers/base/node.c
===================================================================
If system supports memory hot-remove, online_pages() may online removed pages.
So online_pages() need to check whether onlining pages are present or not.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
include/linux/mmzone.h | 21 +++++++++++++++++++++
mm/memory_hotplug.c | 13 +++++++++++++
2 files changed, 34 insertions(+)
Index: linux-3.5-rc6/include/linux/mmzone.h
===================================================================
@@ -467,6 +467,19 @@ int __ref online_pages(unsigned long pfnstructmemory_notifyarg;lock_memory_hotplug();+/*+*Ifsystemsupportsmemoryhot-remove,thememorymayhavebeen+*removed.Sowecheckwhetherthememoryhasbeenremovedornot.+*+*Note:WhenCONFIG_SPARSEMEMisdefined,pfns_present()become+*effective.IfCONFIG_SPARSEMEMisnotdefined,pfns_present()+*alwaysreturns0.+*/+ret=pfns_present(pfn,nr_pages);+if(ret){+unlock_memory_hotplug();+returnret;+}arg.start_pfn=pfn;arg.nr_pages=nr_pages;arg.status_change_nid=-1;
If system supports memory hot-remove, online_pages() may online removed pages.
So online_pages() need to check whether onlining pages are present or not.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
include/linux/mmzone.h | 21 +++++++++++++++++++++
mm/memory_hotplug.c | 13 +++++++++++++
2 files changed, 34 insertions(+)
Index: linux-3.5-rc6/include/linux/mmzone.h
===================================================================
@@ -467,6 +467,19 @@ int __ref online_pages(unsigned long pfnstructmemory_notifyarg;lock_memory_hotplug();+/*+*Ifsystemsupportsmemoryhot-remove,thememorymayhavebeen+*removed.Sowecheckwhetherthememoryhasbeenremovedornot.+*+*Note:WhenCONFIG_SPARSEMEMisdefined,pfns_present()become+*effective.IfCONFIG_SPARSEMEMisnotdefined,pfns_present()+*alwaysreturns0.+*/+ret=pfns_present(pfn,nr_pages);+if(ret){+unlock_memory_hotplug();+returnret;+}arg.start_pfn=pfn;arg.nr_pages=nr_pages;arg.status_change_nid=-1;
When (hot)adding memory into system, /sys/firmware/memmap/X/{end, start, type}
sysfs files are created. But there is no code to remove these files. The patch
implements the function to remove them.
Note : The code does not free firmware_map_entry since there is no way to free
memory which is allocated by bootmem.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 78 ++++++++++++++++++++++++++++++++++++++++++-
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 9 +++-
3 files changed, 90 insertions(+), 3 deletions(-)
Index: linux-3.5-rc6/mm/memory_hotplug.c
===================================================================
@@ -1012,9 +1012,9 @@ int offline_memory(u64 start, u64 size)returnoffline_pages(start_pfn,end_pfn,120*HZ);}-intremove_memory(intnid,u64start,u64size)+int__refremove_memory(intnid,u64start,u64size){-intret=-EBUSY;+intret=0;lock_memory_hotplug();/**Thememorymightbecomeonlinebyothertask,evenifyouoffineit.
@@ -1025,8 +1025,13 @@ int remove_memory(int nid, u64 start, u6"because the memmory range is online\n",start,start+size);ret=-EAGAIN;+gotoout;}+/* remove memmap entry */+firmware_map_remove(start,start+size,"System RAM");++out:unlock_memory_hotplug();returnret;
IIRC, this function's implementation is changed. Why do you do it?
If PageCompound(page), should we check page->first_page's flags?
Thanks
Wen Congyang
quoted hunk
+
+ /* There is no way to free memory allocated from bootmem*/
+}
+
static struct kobj_type memmap_ktype = {
+ .release = release_firmware_map_entry,
.sysfs_ops = &memmap_attr_ops,
.default_attrs = def_attrs,
};
@@ -123,6 +139,16 @@ static int firmware_map_add_entry(u64 st return 0; }+/**+ * firmware_map_remove_entry() - Does the real work to remove a firmware+ * memmap entry.+ * @entry: removed entry.+ **/+static inline void firmware_map_remove_entry(struct firmware_map_entry *entry)+{+ list_del(&entry->list);+}+ /* * Add memmap entry on sysfs */
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
When (hot)adding memory into system, /sys/firmware/memmap/X/{end, start, type}
sysfs files are created. But there is no code to remove these files. The patch
implements the function to remove them.
Note : The code does not free firmware_map_entry since there is no way to free
memory which is allocated by bootmem.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 78 ++++++++++++++++++++++++++++++++++++++++++-
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 9 +++-
3 files changed, 90 insertions(+), 3 deletions(-)
Index: linux-3.5-rc6/mm/memory_hotplug.c
===================================================================
@@ -1012,9 +1012,9 @@ int offline_memory(u64 start, u64 size)returnoffline_pages(start_pfn,end_pfn,120*HZ);}-intremove_memory(intnid,u64start,u64size)+int__refremove_memory(intnid,u64start,u64size){-intret=-EBUSY;+intret=0;lock_memory_hotplug();/**Thememorymightbecomeonlinebyothertask,evenifyouoffineit.
@@ -1025,8 +1025,13 @@ int remove_memory(int nid, u64 start, u6"because the memmory range is online\n",start,start+size);ret=-EAGAIN;+gotoout;}+/* remove memmap entry */+firmware_map_remove(start,start+size,"System RAM");++out:unlock_memory_hotplug();returnret;
IIRC, this function's implementation is changed. Why do you do it?
If PageCompound(page), should we check page->first_page's flags?
I forgot to write the change to change log. Jiang and Christoph discussed
how to find the slab page:
- https://lkml.org/lkml/2012/7/6/333
Then, Christoph proposed this method. So I changed it.
Thanks,
Yasuaki Ishimatsu
Thanks
Wen Congyang
quoted
+
+ /* There is no way to free memory allocated from bootmem*/
+}
+
static struct kobj_type memmap_ktype = {
+ .release = release_firmware_map_entry,
.sysfs_ops = &memmap_attr_ops,
.default_attrs = def_attrs,
};
@@ -123,6 +139,16 @@ static int firmware_map_add_entry(u64 st return 0; }+/**+ * firmware_map_remove_entry() - Does the real work to remove a firmware+ * memmap entry.+ * @entry: removed entry.+ **/+static inline void firmware_map_remove_entry(struct firmware_map_entry *entry)+{+ list_del(&entry->list);+}+ /* * Add memmap entry on sysfs */
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
If system supports memory hot-remove, online_pages() may online removed pages.
So online_pages() need to check whether onlining pages are present or not.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
include/linux/mmzone.h | 21 +++++++++++++++++++++
mm/memory_hotplug.c | 13 +++++++++++++
2 files changed, 34 insertions(+)
Index: linux-3.5-rc6/include/linux/mmzone.h
===================================================================
@@ -467,6 +467,19 @@ int __ref online_pages(unsigned long pfnstructmemory_notifyarg;lock_memory_hotplug();+/*+*Ifsystemsupportsmemoryhot-remove,thememorymayhavebeen+*removed.Sowecheckwhetherthememoryhasbeenremovedornot.+*+*Note:WhenCONFIG_SPARSEMEMisdefined,pfns_present()become+*effective.IfCONFIG_SPARSEMEMisnotdefined,pfns_present()+*alwaysreturns0.+*/
There is one space before tab in the comment.
Thanks
Wen Congyang
All pages of virtual mapping in removed memory cannot be freed, since some pages
used as PGD/PUD includes not only removed memory but also other memory. So the
patch checks whether page can be freed or not.
How to check whether page can be freed or not?
1. When removing memory, the page structs of the revmoved memory are filled
with 0FD.
2. All page structs are filled with 0xFD on PT/PMD, PT/PMD can be cleared.
In this case, the page used as PT/PMD can be freed.
Applying patch, __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is integrated
into one. So __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is deleted.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/x86/mm/init_64.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mm.h | 2
mm/memory_hotplug.c | 19 -------
mm/sparse.c | 5 +-
4 files changed, 128 insertions(+), 19 deletions(-)
Index: linux-3.5-rc6/include/linux/mm.h
===================================================================
@@ -614,12 +614,13 @@ static inline struct page *kmalloc_secti/* This will make the necessary allocations eventually. */returnsparse_mem_map_populate(pnum,nid);}-staticvoid__kfree_section_memmap(structpage*memmap,unsignedlongnr_pages)+staticvoid__kfree_section_memmap(structpage*page,unsignedlongnr_pages){-return;/* XXX: Not implemented yet */+vmemmap_kfree(page,nr_pages);}staticvoidfree_map_bootmem(structpage*page,unsignedlongnr_pages){+vmemmap_free_bootmem(page,nr_pages);}#elsestaticstructpage*__kmalloc_section_memmap(unsignedlongnr_pages)
@@ -300,7 +300,6 @@ static int __meminit __add_section(int nreturnregister_new_memory(nid,__pfn_to_section(phys_start_pfn));}-#ifdef CONFIG_SPARSEMEM_VMEMMAPstaticint__remove_section(structzone*zone,structmem_section*ms){intret=-EINVAL;
@@ -309,29 +308,15 @@ static int __remove_section(struct zone returnret;ret=unregister_memory_section(ms);--returnret;-}-#else-staticint__remove_section(structzone*zone,structmem_section*ms)-{-unsignedlongflags;-structpglist_data*pgdat=zone->zone_pgdat;
This two line should not be removed. Otherwise, we can not build the kernel.
Thanks
Wen Congyang
- int ret = -EINVAL;
-
- if (!valid_section(ms))
- return ret;
-
- ret = unregister_memory_section(ms);
if (ret)
return ret;
pgdat_resize_lock(pgdat, &flags);
sparse_remove_one_section(zone, ms);
pgdat_resize_unlock(pgdat, &flags);
- return 0;
+
+ return ret;
}
-#endif
/*
* Reasonably generic function for adding memory. It is
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
All pages of virtual mapping in removed memory cannot be freed, since some pages
used as PGD/PUD includes not only removed memory but also other memory. So the
patch checks whether page can be freed or not.
How to check whether page can be freed or not?
1. When removing memory, the page structs of the revmoved memory are filled
with 0FD.
2. All page structs are filled with 0xFD on PT/PMD, PT/PMD can be cleared.
In this case, the page used as PT/PMD can be freed.
Applying patch, __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is integrated
into one. So __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is deleted.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/x86/mm/init_64.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mm.h | 2
mm/memory_hotplug.c | 19 -------
mm/sparse.c | 5 +-
4 files changed, 128 insertions(+), 19 deletions(-)
Index: linux-3.5-rc6/include/linux/mm.h
===================================================================
@@ -614,12 +614,13 @@ static inline struct page *kmalloc_secti/* This will make the necessary allocations eventually. */returnsparse_mem_map_populate(pnum,nid);}-staticvoid__kfree_section_memmap(structpage*memmap,unsignedlongnr_pages)+staticvoid__kfree_section_memmap(structpage*page,unsignedlongnr_pages){-return;/* XXX: Not implemented yet */+vmemmap_kfree(page,nr_pages);}staticvoidfree_map_bootmem(structpage*page,unsignedlongnr_pages){+vmemmap_free_bootmem(page,nr_pages);}#elsestaticstructpage*__kmalloc_section_memmap(unsignedlongnr_pages)
@@ -300,7 +300,6 @@ static int __meminit __add_section(int nreturnregister_new_memory(nid,__pfn_to_section(phys_start_pfn));}-#ifdef CONFIG_SPARSEMEM_VMEMMAPstaticint__remove_section(structzone*zone,structmem_section*ms){intret=-EINVAL;
@@ -309,29 +308,15 @@ static int __remove_section(struct zonereturnret;ret=unregister_memory_section(ms);--returnret;-}-#else-staticint__remove_section(structzone*zone,structmem_section*ms)-{-unsignedlongflags;-structpglist_data*pgdat=zone->zone_pgdat;
This two line should not be removed. Otherwise, we can not build the kernel.
Oops. I'll resend the patch.
Thanks,
Yasuaki Ishimatsu
Thanks
Wen Congyang
quoted
- int ret = -EINVAL;
-
- if (!valid_section(ms))
- return ret;
-
- ret = unregister_memory_section(ms);
if (ret)
return ret;
pgdat_resize_lock(pgdat, &flags);
sparse_remove_one_section(zone, ms);
pgdat_resize_unlock(pgdat, &flags);
- return 0;
+
+ return ret;
}
-#endif
/*
* Reasonably generic function for adding memory. It is
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
All pages of virtual mapping in removed memory cannot be freed, since some pages
used as PGD/PUD includes not only removed memory but also other memory. So the
patch checks whether page can be freed or not.
How to check whether page can be freed or not?
1. When removing memory, the page structs of the revmoved memory are filled
with 0FD.
2. All page structs are filled with 0xFD on PT/PMD, PT/PMD can be cleared.
In this case, the page used as PT/PMD can be freed.
Applying patch, __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is integrated
into one. So __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is deleted.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/x86/mm/init_64.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mm.h | 2
mm/memory_hotplug.c | 17 -------
mm/sparse.c | 5 +-
4 files changed, 128 insertions(+), 17 deletions(-)
Index: linux-3.5-rc6/include/linux/mm.h
===================================================================
@@ -614,12 +614,13 @@ static inline struct page *kmalloc_secti/* This will make the necessary allocations eventually. */returnsparse_mem_map_populate(pnum,nid);}-staticvoid__kfree_section_memmap(structpage*memmap,unsignedlongnr_pages)+staticvoid__kfree_section_memmap(structpage*page,unsignedlongnr_pages){-return;/* XXX: Not implemented yet */+vmemmap_kfree(page,nr_pages);}staticvoidfree_map_bootmem(structpage*page,unsignedlongnr_pages){+vmemmap_free_bootmem(page,nr_pages);}#elsestaticstructpage*__kmalloc_section_memmap(unsignedlongnr_pages)
@@ -300,19 +300,6 @@ static int __meminit __add_section(int nreturnregister_new_memory(nid,__pfn_to_section(phys_start_pfn));}-#ifdef CONFIG_SPARSEMEM_VMEMMAP-staticint__remove_section(structzone*zone,structmem_section*ms)-{-intret=-EINVAL;--if(!valid_section(ms))-returnret;--ret=unregister_memory_section(ms);--returnret;-}-#elsestaticint__remove_section(structzone*zone,structmem_section*ms){unsignedlongflags;
@@ -329,9 +316,9 @@ static int __remove_section(struct zone pgdat_resize_lock(pgdat,&flags);sparse_remove_one_section(zone,ms);pgdat_resize_unlock(pgdat,&flags);-return0;++returnret;}-#endif/**Reasonablygenericfunctionforaddingmemory.Itis
@@ -998,6 +998,28 @@ int offline_memory(u64 start, u64 size)end_pfn=start_pfn+PFN_DOWN(size);returnoffline_pages(start_pfn,end_pfn,120*HZ);}++intremove_memory(intnid,u64start,u64size)+{+intret=-EBUSY;+lock_memory_hotplug();+/*+*Thememorymightbecomeonlinebyothertask,evenifyouoffineit.+*Sowecheckwhetherthecpuhasbeenonlinedornot.+*/+if(!is_memblk_offline(start,size)){+pr_warn("memory removing [mem %#010llx-%#010llx] failed, "+"because the memmory range is online\n",+start,start+size);+ret=-EAGAIN;+}++unlock_memory_hotplug();+returnret;++}+EXPORT_SYMBOL_GPL(remove_memory);+#elseintoffline_memory(u64start,u64size){
Hi Yasuaki,
On Wed, Jul 18, 2012 at 6:05 PM, Yasuaki Ishimatsu
[off-list ref] wrote:
remove_memory() does not remove memory but just offlines memory. The patch
changes name of it to offline_memory().
Since offline_memory() just align the start/end pfn and there is no
matched online_memory() function,
i think it's better to remove this function and add the alignment into
offline_pages().
quoted hunk
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/acpi/acpi_memhotplug.c | 2 +-
drivers/base/memory.c | 4 ++--
include/linux/memory_hotplug.h | 2 +-
mm/memory_hotplug.c | 6 +++---
4 files changed, 7 insertions(+), 7 deletions(-)
Index: linux-3.5-rc4/drivers/acpi/acpi_memhotplug.c
===================================================================
@@ -233,7 +233,7 @@ static inline int is_mem_section_removabexternintmem_online_node(intnid);externintadd_memory(intnid,u64start,u64size);externintarch_add_memory(intnid,u64start,u64size);-externintremove_memory(u64start,u64size);+externintoffline_memory(u64start,u64size);externintsparse_add_one_section(structzone*zone,unsignedlongstart_pfn,intnr_pages);externvoidsparse_remove_one_section(structzone*zone,structmem_section*ms);--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
On Wed, Jul 18, 2012 at 6:12 PM, Yasuaki Ishimatsu
[off-list ref] wrote:
quoted hunk
The patch adds __remove_pages() to remove_memory(). Then the range of
phys_start_pfn argument and nr_pages argument in __remove_pagse() may
have different zone. So zone argument is removed from __remove_pages()
and __remove_pages() caluculates zone in each section.
When CONFIG_SPARSEMEM_VMEMMAP is defined, there is no way to remove a memmap.
So __remove_section only calls unregister_memory_section().
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/powerpc/platforms/pseries/hotplug-memory.c | 5 +----
include/linux/memory_hotplug.h | 3 +--
mm/memory_hotplug.c | 19 ++++++++++++-------
3 files changed, 14 insertions(+), 13 deletions(-)
Index: linux-3.5-rc6/mm/memory_hotplug.c
===================================================================
@@ -275,11 +275,14 @@ static int __meminit __add_section(int n#ifdef CONFIG_SPARSEMEM_VMEMMAPstaticint__remove_section(structzone*zone,structmem_section*ms){-/*-*XXX:Freeingmemmapwithvmemmapisnotimplementyet.-*Thisshouldberemovedlater.-*/-return-EBUSY;+intret=-EINVAL;++if(!valid_section(ms))+returnret;++ret=unregister_memory_section(ms);+
I saw a patch from Jiang Liu "mm/hotplug: free zone->pageset when a
zone becomes empty" to
free the zone->pageset and i think there may more cleanup needed when
a zone becomes empty.
We already have __add_zone() in __add_section(), what about add a
function like __remove_zone()
to do the cleanup here?
quoted hunk
+ return ret;
}
#else
static int __remove_section(struct zone *zone, struct mem_section *ms)
@@ -346,11 +349,11 @@ EXPORT_SYMBOL_GPL(__add_pages); * sure that pages are marked reserved and zones are adjust properly by * calling offline_pages(). */-int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,- unsigned long nr_pages)+int __remove_pages(unsigned long phys_start_pfn, unsigned long nr_pages) { unsigned long i, ret = 0; int sections_to_remove;+ struct zone *zone; /* * We can only remove entire sections
@@ -363,6 +366,7 @@ int __remove_pages(struct zone *zone, un sections_to_remove = nr_pages / PAGES_PER_SECTION; for (i = 0; i < sections_to_remove; i++) { unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION;+ zone = page_zone(pfn_to_page(pfn)); ret = __remove_section(zone, __pfn_to_section(pfn)); if (ret) break;
@@ -89,8 +89,7 @@ extern bool is_pageblock_removable_noloc/* reasonably generic interface to expand the physical pages in a zone */externint__add_pages(intnid,structzone*zone,unsignedlongstart_pfn,unsignedlongnr_pages);-externint__remove_pages(structzone*zone,unsignedlongstart_pfn,-unsignedlongnr_pages);+externint__remove_pages(unsignedlongstart_pfn,unsignedlongnr_pages);#ifdef CONFIG_NUMAexternintmemory_add_physaddr_to_nid(u64start);
@@ -76,7 +76,6 @@ unsigned long memory_block_size_bytes(vostaticintpseries_remove_memblock(unsignedlongbase,unsignedintmemblock_size){unsignedlongstart,start_pfn;-structzone*zone;inti,ret;intsections_to_remove;
@@ -87,8 +86,6 @@ static int pseries_remove_memblock(unsigreturn0;}-zone=page_zone(pfn_to_page(start_pfn));-/**Removesectionmappingsandsysfsentriesforthe*sectionofthememoryweareremoving.
@@ -101,7 +98,7 @@ static int pseries_remove_memblock(unsigsections_to_remove=(memblock_size>>PAGE_SHIFT)/PAGES_PER_SECTION;for(i=0;i<sections_to_remove;i++){unsignedlongpfn=start_pfn+i*PAGES_PER_SECTION;-ret=__remove_pages(zone,start_pfn,PAGES_PER_SECTION);+ret=__remove_pages(start_pfn,PAGES_PER_SECTION);if(ret)returnret;}--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Hi Yasuaki,
On Wed, Jul 18, 2012 at 6:05 PM, Yasuaki Ishimatsu
[off-list ref] wrote:
quoted
remove_memory() does not remove memory but just offlines memory. The patch
changes name of it to offline_memory().
Since offline_memory() just align the start/end pfn and there is no
matched online_memory() function,
i think it's better to remove this function and add the alignment into
offline_pages().
If we change it, these argument becomes different as follows:
online_pages : page frame number and number of page frame number
offline_pages : memory address and memory length
I think it is ugly. So I don't want to change it. As you say, there is no
function that matches to offline_memory(). If we create export symbol
function for onlining page, in this case, the function should be named
online_memory().
Thanks,
Yasuaki Ishimatsu
quoted
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/acpi/acpi_memhotplug.c | 2 +-
drivers/base/memory.c | 4 ++--
include/linux/memory_hotplug.h | 2 +-
mm/memory_hotplug.c | 6 +++---
4 files changed, 7 insertions(+), 7 deletions(-)
Index: linux-3.5-rc4/drivers/acpi/acpi_memhotplug.c
===================================================================
@@ -233,7 +233,7 @@ static inline int is_mem_section_removabexternintmem_online_node(intnid);externintadd_memory(intnid,u64start,u64size);externintarch_add_memory(intnid,u64start,u64size);-externintremove_memory(u64start,u64size);+externintoffline_memory(u64start,u64size);externintsparse_add_one_section(structzone*zone,unsignedlongstart_pfn,intnr_pages);externvoidsparse_remove_one_section(structzone*zone,structmem_section*ms);--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
On Wed, Jul 18, 2012 at 6:12 PM, Yasuaki Ishimatsu
[off-list ref] wrote:
quoted
The patch adds __remove_pages() to remove_memory(). Then the range of
phys_start_pfn argument and nr_pages argument in __remove_pagse() may
have different zone. So zone argument is removed from __remove_pages()
and __remove_pages() caluculates zone in each section.
When CONFIG_SPARSEMEM_VMEMMAP is defined, there is no way to remove a memmap.
So __remove_section only calls unregister_memory_section().
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/powerpc/platforms/pseries/hotplug-memory.c | 5 +----
include/linux/memory_hotplug.h | 3 +--
mm/memory_hotplug.c | 19 ++++++++++++-------
3 files changed, 14 insertions(+), 13 deletions(-)
Index: linux-3.5-rc6/mm/memory_hotplug.c
===================================================================
@@ -275,11 +275,14 @@ static int __meminit __add_section(int n#ifdef CONFIG_SPARSEMEM_VMEMMAPstaticint__remove_section(structzone*zone,structmem_section*ms){-/*-*XXX:Freeingmemmapwithvmemmapisnotimplementyet.-*Thisshouldberemovedlater.-*/-return-EBUSY;+intret=-EINVAL;++if(!valid_section(ms))+returnret;++ret=unregister_memory_section(ms);+
I saw a patch from Jiang Liu "mm/hotplug: free zone->pageset when a
zone becomes empty" to
free the zone->pageset and i think there may more cleanup needed when
a zone becomes empty.
We already have __add_zone() in __add_section(), what about add a
function like __remove_zone()
to do the cleanup here?
Thank you for your cooment. As you say, I think cleanup function of zone
is necessary. So I'll update it.
Thanks,
Yasuaki Ishimatsu.
quoted
+ return ret;
}
#else
static int __remove_section(struct zone *zone, struct mem_section *ms)
@@ -346,11 +349,11 @@ EXPORT_SYMBOL_GPL(__add_pages); * sure that pages are marked reserved and zones are adjust properly by * calling offline_pages(). */-int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,- unsigned long nr_pages)+int __remove_pages(unsigned long phys_start_pfn, unsigned long nr_pages) { unsigned long i, ret = 0; int sections_to_remove;+ struct zone *zone; /* * We can only remove entire sections
@@ -363,6 +366,7 @@ int __remove_pages(struct zone *zone, un sections_to_remove = nr_pages / PAGES_PER_SECTION; for (i = 0; i < sections_to_remove; i++) { unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION;+ zone = page_zone(pfn_to_page(pfn)); ret = __remove_section(zone, __pfn_to_section(pfn)); if (ret) break;
@@ -89,8 +89,7 @@ extern bool is_pageblock_removable_noloc/* reasonably generic interface to expand the physical pages in a zone */externint__add_pages(intnid,structzone*zone,unsignedlongstart_pfn,unsignedlongnr_pages);-externint__remove_pages(structzone*zone,unsignedlongstart_pfn,-unsignedlongnr_pages);+externint__remove_pages(unsignedlongstart_pfn,unsignedlongnr_pages);#ifdef CONFIG_NUMAexternintmemory_add_physaddr_to_nid(u64start);
@@ -76,7 +76,6 @@ unsigned long memory_block_size_bytes(vostaticintpseries_remove_memblock(unsignedlongbase,unsignedintmemblock_size){unsignedlongstart,start_pfn;-structzone*zone;inti,ret;intsections_to_remove;
@@ -87,8 +86,6 @@ static int pseries_remove_memblock(unsigreturn0;}-zone=page_zone(pfn_to_page(start_pfn));-/**Removesectionmappingsandsysfsentriesforthe*sectionofthememoryweareremoving.
@@ -101,7 +98,7 @@ static int pseries_remove_memblock(unsigsections_to_remove=(memblock_size>>PAGE_SHIFT)/PAGES_PER_SECTION;for(i=0;i<sections_to_remove;i++){unsignedlongpfn=start_pfn+i*PAGES_PER_SECTION;-ret=__remove_pages(zone,start_pfn,PAGES_PER_SECTION);+ret=__remove_pages(start_pfn,PAGES_PER_SECTION);if(ret)returnret;}--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
@@ -998,6 +998,28 @@ int offline_memory(u64 start, u64 size)end_pfn=start_pfn+PFN_DOWN(size);returnoffline_pages(start_pfn,end_pfn,120*HZ);}++intremove_memory(intnid,u64start,u64size)+{+intret=-EBUSY;+lock_memory_hotplug();+/*+*Thememorymightbecomeonlinebyothertask,evenifyouoffineit.+*Sowecheckwhetherthecpuhasbeenonlinedornot.+*/+if(!is_memblk_offline(start,size)){+pr_warn("memory removing [mem %#010llx-%#010llx] failed, "+"because the memmory range is online\n",+start,start+size);+ret=-EAGAIN;+}++unlock_memory_hotplug();+returnret;++}+EXPORT_SYMBOL_GPL(remove_memory);+#elseintoffline_memory(u64start,u64size){
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
All pages of virtual mapping in removed memory cannot be freed, since some pages
used as PGD/PUD includes not only removed memory but also other memory. So the
patch checks whether page can be freed or not.
How to check whether page can be freed or not?
1. When removing memory, the page structs of the revmoved memory are filled
with 0FD.
2. All page structs are filled with 0xFD on PT/PMD, PT/PMD can be cleared.
In this case, the page used as PT/PMD can be freed.
Applying patch, __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is integrated
into one. So __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is deleted.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/x86/mm/init_64.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mm.h | 2
mm/memory_hotplug.c | 19 -------
mm/sparse.c | 5 +-
4 files changed, 128 insertions(+), 19 deletions(-)
Index: linux-3.5-rc6/include/linux/mm.h
===================================================================
@@ -614,12 +614,13 @@ static inline struct page *kmalloc_secti/* This will make the necessary allocations eventually. */returnsparse_mem_map_populate(pnum,nid);}-staticvoid__kfree_section_memmap(structpage*memmap,unsignedlongnr_pages)+staticvoid__kfree_section_memmap(structpage*page,unsignedlongnr_pages){-return;/* XXX: Not implemented yet */+vmemmap_kfree(page,nr_pages);}staticvoidfree_map_bootmem(structpage*page,unsignedlongnr_pages){+vmemmap_free_bootmem(page,nr_pages);}#elsestaticstructpage*__kmalloc_section_memmap(unsignedlongnr_pages)
@@ -300,7 +300,6 @@ static int __meminit __add_section(int nreturnregister_new_memory(nid,__pfn_to_section(phys_start_pfn));}-#ifdef CONFIG_SPARSEMEM_VMEMMAPstaticint__remove_section(structzone*zone,structmem_section*ms){intret=-EINVAL;
@@ -309,29 +308,15 @@ static int __remove_section(struct zone returnret;ret=unregister_memory_section(ms);--returnret;-}-#else-staticint__remove_section(structzone*zone,structmem_section*ms)-{-unsignedlongflags;-structpglist_data*pgdat=zone->zone_pgdat;-intret=-EINVAL;--if(!valid_section(ms))-returnret;--ret=unregister_memory_section(ms);if(ret)returnret;pgdat_resize_lock(pgdat,&flags);sparse_remove_one_section(zone,ms);pgdat_resize_unlock(pgdat,&flags);-return0;++returnret;}-#endif/**Reasonablygenericfunctionforaddingmemory.Itis--
All pages of virtual mapping in removed memory cannot be freed, since some pages
used as PGD/PUD includes not only removed memory but also other memory. So the
patch checks whether page can be freed or not.
How to check whether page can be freed or not?
1. When removing memory, the page structs of the revmoved memory are filled
with 0FD.
2. All page structs are filled with 0xFD on PT/PMD, PT/PMD can be cleared.
In this case, the page used as PT/PMD can be freed.
Applying patch, __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is integrated
into one. So __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is deleted.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/x86/mm/init_64.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mm.h | 2
mm/memory_hotplug.c | 19 -------
mm/sparse.c | 5 +-
4 files changed, 128 insertions(+), 19 deletions(-)
Index: linux-3.5-rc6/include/linux/mm.h
===================================================================
@@ -614,12 +614,13 @@ static inline struct page *kmalloc_secti/* This will make the necessary allocations eventually. */returnsparse_mem_map_populate(pnum,nid);}-staticvoid__kfree_section_memmap(structpage*memmap,unsignedlongnr_pages)+staticvoid__kfree_section_memmap(structpage*page,unsignedlongnr_pages){-return;/* XXX: Not implemented yet */+vmemmap_kfree(page,nr_pages);}staticvoidfree_map_bootmem(structpage*page,unsignedlongnr_pages){+vmemmap_free_bootmem(page,nr_pages);}#elsestaticstructpage*__kmalloc_section_memmap(unsignedlongnr_pages)
All pages of virtual mapping in removed memory cannot be freed, since some pages
used as PGD/PUD includes not only removed memory but also other memory. So the
patch checks whether page can be freed or not.
How to check whether page can be freed or not?
1. When removing memory, the page structs of the revmoved memory are filled
with 0FD.
2. All page structs are filled with 0xFD on PT/PMD, PT/PMD can be cleared.
In this case, the page used as PT/PMD can be freed.
Applying patch, __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is integrated
into one. So __remove_section() of CONFIG_SPARSEMEM_VMEMMAP is deleted.
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/x86/mm/init_64.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mm.h | 2
mm/memory_hotplug.c | 19 -------
mm/sparse.c | 5 +-
4 files changed, 128 insertions(+), 19 deletions(-)
Index: linux-3.5-rc6/include/linux/mm.h
===================================================================
@@ -614,12 +614,13 @@ static inline struct page *kmalloc_secti/* This will make the necessary allocations eventually. */returnsparse_mem_map_populate(pnum,nid);}-staticvoid__kfree_section_memmap(structpage*memmap,unsignedlongnr_pages)+staticvoid__kfree_section_memmap(structpage*page,unsignedlongnr_pages){-return;/* XXX: Not implemented yet */+vmemmap_kfree(page,nr_pages);}staticvoidfree_map_bootmem(structpage*page,unsignedlongnr_pages){+vmemmap_free_bootmem(page,nr_pages);}#elsestaticstructpage*__kmalloc_section_memmap(unsignedlongnr_pages)
I think you want to free the memory to store struct page.
So why you free page_address(page)?
I understand it now. page is for the memory to store struct page.
You clear page table's entry for the addr, not page_address(page).
And the entry for page_address(page) is still valid now.
So I think you want this:
__flush_tlb_one(addr);
Thanks
Wen Congyang
Thanks
Wen Congyang
quoted
+ }
+
+}
+
+void vmemmap_free_bootmem(struct page *memmap, unsigned long nr_pages)
+{
+ unsigned long addr = (unsigned long)memmap;
+ unsigned long end = (unsigned long)(memmap + nr_pages);
+ unsigned long next;
+ struct page *page;
+ int page_size;
+ unsigned long magic;
+
+ for (; addr < end; addr = next) {
+ page = NULL;
+ page_size = 0;
+ next = find_and_clear_pte_page(addr, end, &page, &page_size);
+ if (!page)
+ continue;
+
+ magic = (unsigned long) page->lru.next;
+ if (magic == SECTION_INFO)
+ put_page_bootmem(page);
+ flush_tlb_kernel_range(addr, end);
+ }
+
+}
+
void register_page_bootmem_memmap(unsigned long section_nr,
struct page *start_page, unsigned long size)
{
Index: linux-3.5-rc6/mm/memory_hotplug.c
===================================================================
@@ -300,7 +300,6 @@ static int __meminit __add_section(int nreturnregister_new_memory(nid,__pfn_to_section(phys_start_pfn));}-#ifdef CONFIG_SPARSEMEM_VMEMMAPstaticint__remove_section(structzone*zone,structmem_section*ms){intret=-EINVAL;
@@ -309,29 +308,15 @@ static int __remove_section(struct zone returnret;ret=unregister_memory_section(ms);--returnret;-}-#else-staticint__remove_section(structzone*zone,structmem_section*ms)-{-unsignedlongflags;-structpglist_data*pgdat=zone->zone_pgdat;-intret=-EINVAL;--if(!valid_section(ms))-returnret;--ret=unregister_memory_section(ms);if(ret)returnret;pgdat_resize_lock(pgdat,&flags);sparse_remove_one_section(zone,ms);pgdat_resize_unlock(pgdat,&flags);-return0;++returnret;}-#endif/**Reasonablygenericfunctionforaddingmemory.Itis--
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
When calling unregister_node(), the function shows following message at
device_release().
Device 'node2' does not have a release() function, it is broken and must be
fixed.
So the patch implements node_device_release()
CC: David Rientjes <rientjes@google.com>
CC: Jiang Liu <redacted>
CC: Len Brown <redacted>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <redacted>
CC: Christoph Lameter <redacted>
Cc: Minchan Kim <redacted>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: KOSAKI Motohiro <redacted>
CC: Wen Congyang <redacted>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/base/node.c | 7 +++++++
1 file changed, 7 insertions(+)
Index: linux-3.5-rc6/drivers/base/node.c
===================================================================
This line is wrong. node_dev->work_struct may be queued in workqueue.
So, it is very dangerous to clear node_dev->work_struct here.
In my test, it will cause kernel panicked.
Thanks
Wen Congyang
quoted hunk
+}
/*
* register_node - Setup a sysfs device for a node.
@@ -265,6 +271,7 @@ int register_node(struct node *node, int node->dev.id = num; node->dev.bus = &node_subsys;+ node->dev.release = node_device_release; error = device_register(&node->dev); if (!error){--