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>
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
===================================================================
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 - 1".
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
mm/memory_hotplug.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 70 +++++++++++++++++++++++++++++++++++++++++++
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 6 +++
3 files changed, 81 insertions(+), 1 deletion(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
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>
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-rc4/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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/base/memory.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
Index: linux-3.5-rc4/drivers/base/memory.c
===================================================================
@@ -118,6 +127,7 @@ int register_memory(struct memory_blockmemory->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;
@@ -668,7 +678,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);
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/powerpc/platforms/pseries/hotplug-memory.c | 5 +----
include/linux/memory_hotplug.h | 3 +--
mm/memory_hotplug.c | 20 +++++++++++++-------
3 files changed, 15 insertions(+), 13 deletions(-)
Index: linux-3.5-rc4/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);
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
mm/memory_hotplug.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
Index: linux-3.5-rc4/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>
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-rc4/include/linux/memory_hotplug.h
===================================================================
For removing memmap region of sparse-vmemmap which is allocated bootmem,
memmap region of sparse-vmemmap needs to be registered by get_page_bootmem().
So the patch searches pages of virtual mapping and registers the pages by
get_page_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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/x86/mm/init_64.c | 53 +++++++++++++++++++++++++++++++++++++++++
include/linux/memory_hotplug.h | 2 +
include/linux/mm.h | 3 +-
mm/memory_hotplug.c | 23 +++++++++++++++--
4 files changed, 77 insertions(+), 4 deletions(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
I don't think that all pages of virtual mapping in removed memory can be
freed, since page which type is MIX_SECTION_INFO is difficult to free.
So, the patch only frees page which type is SECTION_INFO at first.
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
arch/x86/mm/init_64.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mm.h | 2 +
mm/memory_hotplug.c | 5 ++
mm/sparse.c | 5 +-
4 files changed, 101 insertions(+), 2 deletions(-)
Index: linux-3.5-rc4/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)
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/base/node.c | 7 +++++++
1 file changed, 7 insertions(+)
Index: linux-3.5-rc4/drivers/base/node.c
===================================================================
The patch adds node_set_offline() and unregister_one_node() to remove_memory()
for removing sysfs file of node.
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
mm/memory_hotplug.c | 5 +++++
1 file changed, 5 insertions(+)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 70 +++++++++++++++++++++++++++++++++++++++++++
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 6 +++
3 files changed, 81 insertions(+), 1 deletion(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
I find a function free_bootmem(), but I am not sure whether it can work here.
Another problem: how to check whether the entry uses bootmem?
Thanks
Wen Congyang
@@ -123,6 +132,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 */
@@ -452,12 +453,35 @@ static int acpi_memory_device_add(structstaticintacpi_memory_device_remove(structacpi_device*device,inttype){structacpi_memory_device*mem_device=NULL;-+structacpi_memory_info*info,*tmp;+intresult;+intnode;if(!device||!acpi_driver_data(device))return-EINVAL;mem_device=acpi_driver_data(device);++node=acpi_get_node(mem_device->device->handle);++list_for_each_entry_safe(info,tmp,&mem_device->res_list,list){+if(!info->enabled)+continue;++if(!is_memblk_offline(info->start_addr,info->length)){+result=offline_memory(info->start_addr,info->length);+if(result)+returnresult;+}++result=remove_memory(node,info->start_addr,info->length);+if(result)+returnresult;++list_del(&info->list);+kfree(info);+}+kfree(mem_device);
The caller does not care the return value, and after this function returns, the
memory device will be unbound from this driver, so we should free all memory
allocated for driver data.
@@ -70,6 +70,44 @@ void unregister_memory_isolate_notifier(}EXPORT_SYMBOL(unregister_memory_isolate_notifier);+boolis_memblk_offline(unsignedlongstart,unsignedlongsize)+{+structmemory_block*mem=NULL;+structmem_section*section;+unsignedlongstart_pfn,end_pfn;+unsignedlongpfn,section_nr;++start_pfn=PFN_DOWN(start);+end_pfn=start_pfn+PFN_DOWN(start);++for(pfn=start_pfn;pfn<end_pfn;pfn+=PAGES_PER_SECTION){+section_nr=pfn_to_section_nr(pfn);+if(!present_section_nr(section_nr));+continue;++section=__nr_to_section(section_nr);+/* same memblock? */+if(mem)+if((section_nr>=mem->start_section_nr)&&+(section_nr<=mem->end_section_nr))+continue;++mem=find_memory_block_hinted(section,mem);
The second parameter should be NULL. Otherwise, the mem->dev.kobj will
be put twice:
1. we put it when mem->state is MEM_OFFLINE
2. we put it in find_memory_block_hinted().
Thanks
Wen Congyang
quoted hunk
+ if (!mem)
+ continue;
+ if (mem->state == MEM_OFFLINE) {
+ kobject_put(&mem->dev.kobj);
+ continue;
+ }
+
+ kobject_put(&mem->dev.kobj);
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(is_memblk_offline);
+
/*
* register_memory - Setup a sysfs device for a memory block
*/
Index: linux-3.5-rc4/include/linux/memory.h
===================================================================
@@ -452,12 +453,35 @@ static int acpi_memory_device_add(structstaticintacpi_memory_device_remove(structacpi_device*device,inttype){structacpi_memory_device*mem_device=NULL;-+structacpi_memory_info*info,*tmp;+intresult;+intnode;if(!device||!acpi_driver_data(device))return-EINVAL;mem_device=acpi_driver_data(device);++node=acpi_get_node(mem_device->device->handle);++list_for_each_entry_safe(info,tmp,&mem_device->res_list,list){+if(!info->enabled)+continue;++if(!is_memblk_offline(info->start_addr,info->length)){+result=offline_memory(info->start_addr,info->length);+if(result)+returnresult;+}++result=remove_memory(node,info->start_addr,info->length);+if(result)+returnresult;++list_del(&info->list);+kfree(info);+}+kfree(mem_device);
The caller does not care the return value, and after this function returns, the
memory device will be unbound from this driver, so we should free all memory
allocated for driver data.
We can ignore return value of remove_memory() because I think that it should
return 0. But we cannot ignore return value of offline_memory() because
kernel panic will occurs if kernel removes online memory. How do we deal with
online memory?
@@ -70,6 +70,44 @@ void unregister_memory_isolate_notifier(}EXPORT_SYMBOL(unregister_memory_isolate_notifier);+boolis_memblk_offline(unsignedlongstart,unsignedlongsize)+{+structmemory_block*mem=NULL;+structmem_section*section;+unsignedlongstart_pfn,end_pfn;+unsignedlongpfn,section_nr;++start_pfn=PFN_DOWN(start);+end_pfn=start_pfn+PFN_DOWN(start);++for(pfn=start_pfn;pfn<end_pfn;pfn+=PAGES_PER_SECTION){+section_nr=pfn_to_section_nr(pfn);+if(!present_section_nr(section_nr));+continue;++section=__nr_to_section(section_nr);+/* same memblock? */+if(mem)+if((section_nr>=mem->start_section_nr)&&+(section_nr<=mem->end_section_nr))+continue;++mem=find_memory_block_hinted(section,mem);
The second parameter should be NULL. Otherwise, the mem->dev.kobj will
be put twice:
1. we put it when mem->state is MEM_OFFLINE
2. we put it in find_memory_block_hinted().
Ah, O.K.
How about it?
+bool is_memblk_offline(unsigned long start, unsigned long size)
+{
+ struct memory_block *mem = NULL;
+ struct mem_section *section;
+ unsigned long start_pfn, end_pfn;
+ unsigned long pfn, section_nr;
+
+ start_pfn = PFN_DOWN(start);
+ end_pfn = start_pfn + PFN_DOWN(start);
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ section_nr = pfn_to_section_nr(pfn);
+ if (!present_section_nr(section_nr));
+ continue;
+
+ section = __nr_to_section(section_nr);
+ /* same memblock? */
+ if (mem)
+ if((section_nr >= mem->start_section_nr) &&
+ (section_nr <= mem->end_section_nr))
+ continue;
+
+ mem = find_memory_block_hinted(section, mem);
+ if (!mem)
+ continue;
+ if (mem->state == MEM_OFFLINE)
+ continue;
+
+ kobject_put(&mem->dev.kobj);
+ return false;
+ }
+
+ if (mem)
+ kobject_put(&mem->dev.kobj);
+
+ return true;
+}
+EXPORT_SYMBOL(is_memblk_offline);
Thanks,
Yasuaki Ishimatsu
Thanks
Wen Congyang
quoted
+ if (!mem)
+ continue;
+ if (mem->state == MEM_OFFLINE) {
+ kobject_put(&mem->dev.kobj);
+ continue;
+ }
+
+ kobject_put(&mem->dev.kobj);
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(is_memblk_offline);
+
/*
* register_memory - Setup a sysfs device for a memory block
*/
Index: linux-3.5-rc4/include/linux/memory.h
===================================================================
@@ -452,12 +453,35 @@ static int acpi_memory_device_add(structstaticintacpi_memory_device_remove(structacpi_device*device,inttype){structacpi_memory_device*mem_device=NULL;-+structacpi_memory_info*info,*tmp;+intresult;+intnode;if(!device||!acpi_driver_data(device))return-EINVAL;mem_device=acpi_driver_data(device);++node=acpi_get_node(mem_device->device->handle);++list_for_each_entry_safe(info,tmp,&mem_device->res_list,list){+if(!info->enabled)+continue;++if(!is_memblk_offline(info->start_addr,info->length)){+result=offline_memory(info->start_addr,info->length);+if(result)+returnresult;+}++result=remove_memory(node,info->start_addr,info->length);+if(result)+returnresult;++list_del(&info->list);+kfree(info);+}+kfree(mem_device);
The caller does not care the return value, and after this function returns, the
memory device will be unbound from this driver, so we should free all memory
allocated for driver data.
We can ignore return value of remove_memory() because I think that it should
return 0. But we cannot ignore return value of offline_memory() because
kernel panic will occurs if kernel removes online memory. How do we deal with
online memory?
Yes, We can not remove online memory, so just free the memory if offline_memory()
or remove_memory() fails.
@@ -70,6 +70,44 @@ void unregister_memory_isolate_notifier(}EXPORT_SYMBOL(unregister_memory_isolate_notifier);+boolis_memblk_offline(unsignedlongstart,unsignedlongsize)+{+structmemory_block*mem=NULL;+structmem_section*section;+unsignedlongstart_pfn,end_pfn;+unsignedlongpfn,section_nr;++start_pfn=PFN_DOWN(start);+end_pfn=start_pfn+PFN_DOWN(start);++for(pfn=start_pfn;pfn<end_pfn;pfn+=PAGES_PER_SECTION){+section_nr=pfn_to_section_nr(pfn);+if(!present_section_nr(section_nr));+continue;++section=__nr_to_section(section_nr);+/* same memblock? */+if(mem)+if((section_nr>=mem->start_section_nr)&&+(section_nr<=mem->end_section_nr))+continue;++mem=find_memory_block_hinted(section,mem);
The second parameter should be NULL. Otherwise, the mem->dev.kobj will
be put twice:
1. we put it when mem->state is MEM_OFFLINE
2. we put it in find_memory_block_hinted().
Ah, O.K.
How about it?
This version looks fine to me.
Thanks
Wen Congyang
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 70 +++++++++++++++++++++++++++++++++++++++++++
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 6 +++
3 files changed, 81 insertions(+), 1 deletion(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
I find a function free_bootmem(), but I am not sure whether it can work here.
It cannot work here.
Another problem: how to check whether the entry uses bootmem?
When firmware_map_entry is allocated by kzalloc(), the page has PG_slab.
So we can check whether the entry was allocated by bootmem or not.
If the eantry was allocated by kzalloc(), we can free the entry by kfree().
But if the entry was allocated by bootmem, we have no way to free the entry.
Thanks,
Yasuaki Ishimatsu
@@ -123,6 +132,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 */
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 70 +++++++++++++++++++++++++++++++++++++++++++
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 6 +++
3 files changed, 81 insertions(+), 1 deletion(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
I find a function free_bootmem(), but I am not sure whether it can work here.
It cannot work here.
quoted
Another problem: how to check whether the entry uses bootmem?
When firmware_map_entry is allocated by kzalloc(), the page has PG_slab.
This is not true. In my test, I find the page does not have PG_slab sometimes.
Thanks
Wen Congyang.
So we can check whether the entry was allocated by bootmem or not.
If the eantry was allocated by kzalloc(), we can free the entry by kfree().
But if the entry was allocated by bootmem, we have no way to free the entry.
Thanks,
Yasuaki Ishimatsu
@@ -123,6 +132,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 */
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 70 +++++++++++++++++++++++++++++++++++++++++++
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 6 +++
3 files changed, 81 insertions(+), 1 deletion(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
I find a function free_bootmem(), but I am not sure whether it can work here.
It cannot work here.
quoted
Another problem: how to check whether the entry uses bootmem?
When firmware_map_entry is allocated by kzalloc(), the page has PG_slab.
This is not true. In my test, I find the page does not have PG_slab sometimes.
I think that it depends on the allocated size. firmware_map_entry size is
smaller than PAGE_SIZE. So the page has PG_Slab.
Thanks,
Yasuaki Ishimatsu
Thanks
Wen Congyang.
quoted
So we can check whether the entry was allocated by bootmem or not.
If the eantry was allocated by kzalloc(), we can free the entry by kfree().
But if the entry was allocated by bootmem, we have no way to free the entry.
Thanks,
Yasuaki Ishimatsu
@@ -123,6 +132,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 */
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 70 +++++++++++++++++++++++++++++++++++++++++++
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 6 +++
3 files changed, 81 insertions(+), 1 deletion(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
I find a function free_bootmem(), but I am not sure whether it can work here.
It cannot work here.
quoted
Another problem: how to check whether the entry uses bootmem?
When firmware_map_entry is allocated by kzalloc(), the page has PG_slab.
This is not true. In my test, I find the page does not have PG_slab sometimes.
I think that it depends on the allocated size. firmware_map_entry size is
smaller than PAGE_SIZE. So the page has PG_Slab.
In my test, I add printk in the function firmware_map_add_hotplug() to display
page's flags. And sometimes the page is not allocated by slab(I use PageSlab()
to verify it).
Thanks
Wen Congyang
Thanks,
Yasuaki Ishimatsu
quoted
Thanks
Wen Congyang.
quoted
So we can check whether the entry was allocated by bootmem or not.
If the eantry was allocated by kzalloc(), we can free the entry by kfree().
But if the entry was allocated by bootmem, we have no way to free the entry.
Thanks,
Yasuaki Ishimatsu
@@ -123,6 +132,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 */
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 70 +++++++++++++++++++++++++++++++++++++++++++
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 6 +++
3 files changed, 81 insertions(+), 1 deletion(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
I find a function free_bootmem(), but I am not sure whether it can work here.
It cannot work here.
quoted
Another problem: how to check whether the entry uses bootmem?
When firmware_map_entry is allocated by kzalloc(), the page has PG_slab.
This is not true. In my test, I find the page does not have PG_slab sometimes.
I think that it depends on the allocated size. firmware_map_entry size is
smaller than PAGE_SIZE. So the page has PG_Slab.
In my test, I add printk in the function firmware_map_add_hotplug() to display
page's flags. And sometimes the page is not allocated by slab(I use PageSlab()
to verify it).
How did you check it? Could you send your debug patch?
When the memory is not allocated from slab, the flags is 0x10000000008000.
From 8dd51368d6c03edf7edc89cab17441e3741c39c7 Mon Sep 17 00:00:00 2001
@@ -160,11 +161,17 @@ static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)int__meminitfirmware_map_add_hotplug(u64start,u64end,constchar*type){structfirmware_map_entry*entry;+structpage*entry_page;entry=kzalloc(sizeof(structfirmware_map_entry),GFP_ATOMIC);if(!entry)return-ENOMEM;+entry_page=virt_to_page(entry);+printk(KERN_WARNING"flags: %lx\n",entry_page->flags);+if(PageSlab(entry_page)){+printk(KERN_WARNING"page is allocated from slab\n");+}firmware_map_add_entry(start,end,type,entry);/* create the memmap entry */add_sysfs_fw_map_entry(entry);
--
1.7.1
Thanks
Wen Congyang
>
> Thanks,
> Yasuaki Ishimatsu
>
>> Thanks
>> Wen Congyang
>>
>>>
>>> Thanks,
>>> Yasuaki Ishimatsu
>>>
>>>>
>>>> Thanks
>>>> Wen Congyang.
>>>>
>>>>> So we can check whether the entry was allocated by bootmem or not.
>>>>> If the eantry was allocated by kzalloc(), we can free the entry by kfree().
>>>>> But if the entry was allocated by bootmem, we have no way to free the entry.
>>>>>
>>>>> Thanks,
>>>>> Yasuaki Ishimatsu
>>>>>
>>>>>>
>>>>>> Thanks
>>>>>> Wen Congyang
>>>>>>
>>>>>>> +}
>>>>>>> +
>>>>>>> static struct kobj_type memmap_ktype = {
>>>>>>> + .release = release_firmware_map_entry,
>>>>>>> .sysfs_ops = &memmap_attr_ops,
>>>>>>> .default_attrs = def_attrs,
>>>>>>> };
>>>>>>> @@ -123,6 +132,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
>>>>>>> */
>>>>>>> @@ -144,6 +163,31 @@ static int add_sysfs_fw_map_entry(struct
>>>>>>> return 0;
>>>>>>> }
>>>>>>>
>>>>>>> +/*
>>>>>>> + * Remove memmap entry on sysfs
>>>>>>> + */
>>>>>>> +static inline void remove_sysfs_fw_map_entry(struct firmware_map_entry *entry)
>>>>>>> +{
>>>>>>> + kobject_put(&entry->kobj);
>>>>>>> +}
>>>>>>> +
>>>>>>> +/*
>>>>>>> + * Search memmap entry
>>>>>>> + */
>>>>>>> +
>>>>>>> +struct firmware_map_entry * __meminit
>>>>>>> +find_firmware_map_entry(u64 start, u64 end, const char *type)
>>>>>>> +{
>>>>>>> + struct firmware_map_entry *entry;
>>>>>>> +
>>>>>>> + list_for_each_entry(entry, &map_entries, list)
>>>>>>> + if ((entry->start == start) && (entry->end == end) &&
>>>>>>> + (!strcmp(entry->type, type)))
>>>>>>> + return entry;
>>>>>>> +
>>>>>>> + return NULL;
>>>>>>> +}
>>>>>>> +
>>>>>>> /**
>>>>>>> * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
>>>>>>> * memory hotplug.
>>>>>>> @@ -196,6 +240,32 @@ int __init firmware_map_add_early(u64 st
>>>>>>> return firmware_map_add_entry(start, end, type, entry);
>>>>>>> }
>>>>>>>
>>>>>>> +/**
>>>>>>> + * firmware_map_remove() - remove a firmware mapping entry
>>>>>>> + * @start: Start of the memory range.
>>>>>>> + * @end: End of the memory range (inclusive).
>>>>>>> + * @type: Type of the memory range.
>>>>>>> + *
>>>>>>> + * removes a firmware mapping entry.
>>>>>>> + *
>>>>>>> + * Returns 0 on success, or -EINVAL if no entry.
>>>>>>> + **/
>>>>>>> +int __meminit firmware_map_remove(u64 start, u64 end, const char *type)
>>>>>>> +{
>>>>>>> + struct firmware_map_entry *entry;
>>>>>>> +
>>>>>>> + entry = find_firmware_map_entry(start, end, type);
>>>>>>> + if (!entry)
>>>>>>> + return -EINVAL;
>>>>>>> +
>>>>>>> + /* remove the memmap entry */
>>>>>>> + remove_sysfs_fw_map_entry(entry);
>>>>>>> +
>>>>>>> + firmware_map_remove_entry(entry);
>>>>>>> +
>>>>>>> + return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>> /*
>>>>>>> * Sysfs functions -------------------------------------------------------------
>>>>>>> */
>>>>>>>
>>>>>>> --
>>>>>>> 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/
>>>>>>>
>>>>>>
>>>>>> --
>>>>>> 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/
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>> --
>>>> 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/
>>>>
>>>
>>>
>>>
>>>
>>
>> --
>> 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/
>>
>
>
>
>
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 70 +++++++++++++++++++++++++++++++++++++++++++
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 6 +++
3 files changed, 81 insertions(+), 1 deletion(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
I find a function free_bootmem(), but I am not sure whether it can work here.
It cannot work here.
quoted
Another problem: how to check whether the entry uses bootmem?
When firmware_map_entry is allocated by kzalloc(), the page has PG_slab.
This is not true. In my test, I find the page does not have PG_slab sometimes.
I think that it depends on the allocated size. firmware_map_entry size is
smaller than PAGE_SIZE. So the page has PG_Slab.
In my test, I add printk in the function firmware_map_add_hotplug() to display
page's flags. And sometimes the page is not allocated by slab(I use PageSlab()
to verify it).
How did you check it? Could you send your debug patch?
Thanks,
Yasuaki Ishimatsu
Thanks
Wen Congyang
quoted
Thanks,
Yasuaki Ishimatsu
quoted
Thanks
Wen Congyang.
quoted
So we can check whether the entry was allocated by bootmem or not.
If the eantry was allocated by kzalloc(), we can free the entry by kfree().
But if the entry was allocated by bootmem, we have no way to free the entry.
Thanks,
Yasuaki Ishimatsu
@@ -123,6 +132,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 */
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>
Signed-off-by: Yasuaki Ishimatsu <redacted>
---
drivers/firmware/memmap.c | 70 +++++++++++++++++++++++++++++++++++++++++++
include/linux/firmware-map.h | 6 +++
mm/memory_hotplug.c | 6 +++
3 files changed, 81 insertions(+), 1 deletion(-)
Index: linux-3.5-rc4/mm/memory_hotplug.c
===================================================================
I find a function free_bootmem(), but I am not sure whether it can work here.
It cannot work here.
quoted
Another problem: how to check whether the entry uses bootmem?
When firmware_map_entry is allocated by kzalloc(), the page has PG_slab.
This is not true. In my test, I find the page does not have PG_slab sometimes.
I think that it depends on the allocated size. firmware_map_entry size is
smaller than PAGE_SIZE. So the page has PG_Slab.
In my test, I add printk in the function firmware_map_add_hotplug() to display
page's flags. And sometimes the page is not allocated by slab(I use PageSlab()
to verify it).
How did you check it? Could you send your debug patch?
When the memory is not allocated from slab, the flags is 0x10000000008000.
Thank you for sending the patch.
I think the page to not have PageSlab is a compound page. So we can check
whether the entry is allocate from bootmem or not as follow:
static void release_firmware_map_entry(struct kobject *kobj)
{
struct firmware_map_entry *entry = to_memmap_entry(kobj);
struct page *head_page;
head_page = virt_to_head_page(entry);
if (PageSlab(head_page))
kfree(etnry);
else
/* the entry is allocated from bootmem */
}
Thanks,
Yasuaki Ishimatsu
@@ -160,11 +161,17 @@ static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)int__meminitfirmware_map_add_hotplug(u64start,u64end,constchar*type){structfirmware_map_entry*entry;+structpage*entry_page;entry=kzalloc(sizeof(structfirmware_map_entry),GFP_ATOMIC);if(!entry)return-ENOMEM;+entry_page=virt_to_page(entry);+printk(KERN_WARNING"flags: %lx\n",entry_page->flags);+if(PageSlab(entry_page)){+printk(KERN_WARNING"page is allocated from slab\n");+}firmware_map_add_entry(start,end,type,entry);/* create the memmap entry */add_sysfs_fw_map_entry(entry);