From: David Hildenbrand <hidden> Date: 2020-08-21 10:34:58
This is the follow-up of "[PATCH RFCv1 0/5] mm/memory_hotplug: selective
merging of memory resources" [1]
Some add_memory*() users add memory in small, contiguous memory blocks.
Examples include virtio-mem, hyper-v balloon, and the XEN balloon.
This can quickly result in a lot of memory resources, whereby the actual
resource boundaries are not of interest (e.g., it might be relevant for
DIMMs, exposed via /proc/iomem to user space). We really want to merge
added resources in this scenario where possible.
Resources are effectively stored in a list-based tree. Having a lot of
resources not only wastes memory, it also makes traversing that tree more
expensive, and makes /proc/iomem explode in size (e.g., requiring
kexec-tools to manually merge resources when creating a kdump header. The
current kexec-tools resource count limit does not allow for more than
~100GB of memory with a memory block size of 128MB on x86-64).
Let's allow to selectively merge system ram resources directly below a
specific parent resource. Patch #3 contains a /proc/iomem example. Only
tested with virtio-mem.
Note: This gets the job done and is comparably simple. More complicated
approaches would require introducing IORESOURCE_MERGEABLE and extending our
add_memory*() interfaces with a flag, specifying that merging after adding
succeeded is acceptable. I'd like to avoid that complexity and code churn
for now.
[1] https://lkml.kernel.org/r/20200731091838.7490-1-david@redhat.com
RFC -> v1:
- Switch from rather generic "merge_child_mem_resources()" where a resource
name has to be specified to "merge_system_ram_resources().
- Smaller comment/documentation/patch description changes/fixes
David Hildenbrand (5):
kernel/resource: make release_mem_region_adjustable() never fail
kernel/resource: merge_system_ram_resources() to merge resources after
hotplug
virtio-mem: try to merge system ram resources
xen/balloon: try to merge system ram resources
hv_balloon: try to merge system ram resources
drivers/hv/hv_balloon.c | 3 ++
drivers/virtio/virtio_mem.c | 14 ++++-
drivers/xen/balloon.c | 4 ++
include/linux/ioport.h | 7 ++-
kernel/resource.c | 101 ++++++++++++++++++++++++++++--------
mm/memory_hotplug.c | 22 +-------
6 files changed, 105 insertions(+), 46 deletions(-)
--
2.26.2
From: David Hildenbrand <hidden> Date: 2020-08-21 10:35:01
Let's make sure splitting a resource on memory hotunplug will never fail.
This will become more relevant once we merge selected system ram
resources - then, we'll trigger that case more frequently on memory
hotunplug.
In general, this function is already unlikely to fail. When we remove
memory, we free up quite a lot of metadata (memmap, page tables, memory
block device, etc.). The only way it could really fail currently is when
injecting allocation errors.
All other error cases inside release_mem_region_adjustable() seem to be
sanity checks if the function would be abused in different context -
let's add WARN_ON_ONCE().
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Dan Williams <redacted>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Kees Cook <redacted>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
include/linux/ioport.h | 4 ++--
kernel/resource.c | 49 ++++++++++++++++++++++++------------------
mm/memory_hotplug.c | 22 +------------------
3 files changed, 31 insertions(+), 44 deletions(-)
@@ -1255,21 +1255,28 @@ EXPORT_SYMBOL(__release_region);*assumesthatallchildrenremainintheloweraddressentryfor*simplicity.Enhancethislogicwhennecessary.*/-intrelease_mem_region_adjustable(structresource*parent,-resource_size_tstart,resource_size_tsize)+voidrelease_mem_region_adjustable(structresource*parent,+resource_size_tstart,resource_size_tsize){+structresource*new_res=NULL;+boolalloc_nofail=false;structresource**p;structresource*res;-structresource*new_res;resource_size_tend;-intret=-EINVAL;end=start+size-1;-if((start<parent->start)||(end>parent->end))-returnret;+if(WARN_ON_ONCE((start<parent->start)||(end>parent->end)))+return;-/* The alloc_resource() result gets checked later */-new_res=alloc_resource(GFP_KERNEL);+/*+*Wefreeupquitealotofmemoryonmemoryhotunplug(esp.,memap),+*justbeforereleasingtheregion.Thisishighlyunlikelyto+*fail-let'splaysaveandmakeitneverfailasthecallercannot+*performanyerrorhandling(e.g.,tryingtore-addmemorywillfail+*similarly).+*/+retry:+new_res=alloc_resource(GFP_KERNEL|alloc_nofail?__GFP_NOFAIL:0);p=&parent->child;write_lock(&resource_lock);
@@ -1295,7 +1302,6 @@ int release_mem_region_adjustable(struct resource *parent,*soifwearedealingwiththem,letusjustbackoffhere.*/if(!(res->flags&IORESOURCE_SYSRAM)){-ret=0;break;}
@@ -1312,20 +1318,23 @@ int release_mem_region_adjustable(struct resource *parent,/* free the whole entry */*p=res->sibling;free_resource(res);-ret=0;}elseif(res->start==start&&res->end!=end){/* adjust the start */-ret=__adjust_resource(res,end+1,-res->end-end);+WARN_ON_ONCE(__adjust_resource(res,end+1,+res->end-end));}elseif(res->start!=start&&res->end==end){/* adjust the end */-ret=__adjust_resource(res,res->start,-start-res->start);+WARN_ON_ONCE(__adjust_resource(res,res->start,+start-res->start));}else{-/* split into two entries */+/* split into two entries - we need a new resource */if(!new_res){-ret=-ENOMEM;-break;+new_res=alloc_resource(GFP_ATOMIC);+if(!new_res){+alloc_nofail=true;+write_unlock(&resource_lock);+gotoretry;+}}new_res->name=res->name;new_res->start=end+1;
@@ -1336,9 +1345,8 @@ int release_mem_region_adjustable(struct resource *parent,new_res->sibling=res->sibling;new_res->child=NULL;-ret=__adjust_resource(res,res->start,-start-res->start);-if(ret)+if(WARN_ON_ONCE(__adjust_resource(res,res->start,+start-res->start)))break;res->sibling=new_res;new_res=NULL;
From: David Hildenbrand <hidden> Date: 2020-08-21 10:35:09
Some add_memory*() users add memory in small, contiguous memory blocks.
Examples include virtio-mem, hyper-v balloon, and the XEN balloon.
This can quickly result in a lot of memory resources, whereby the actual
resource boundaries are not of interest (e.g., it might be relevant for
DIMMs, exposed via /proc/iomem to user space). We really want to merge
added resources in this scenario where possible.
Let's provide an interface to trigger merging of applicable child
resources. It will be, for example, used by virtio-mem to trigger
merging of system ram resources it added to its resource container, but
also by XEN and Hyper-V to trigger merging of system ram resources in
iomem_resource.
Note: We really want to merge after the whole operation succeeded, not
directly when adding a resource to the resource tree (it would break
add_memory_resource() and require splitting resources again when the
operation failed - e.g., due to -ENOMEM).
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Dan Williams <redacted>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Kees Cook <redacted>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Thomas Gleixner <redacted>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Stephen Hemminger <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Roger Pau Monné <redacted>
Cc: Julien Grall <redacted>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
include/linux/ioport.h | 3 +++
kernel/resource.c | 52 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
From: David Hildenbrand <hidden> Date: 2020-08-21 10:35:31
virtio-mem adds memory in memory block granularity, to be able to
remove it in the same granularity again later, and to grow slowly on
demand. This, however, results in quite a lot of resources when
adding a lot of memory. Resources are effectively stored in a list-based
tree. Having a lot of resources not only wastes memory, it also makes
traversing that tree more expensive, and makes /proc/iomem explode in
size (e.g., requiring kexec-tools to manually merge resources later
when e.g., trying to create a kdump header).
Before this patch, we get (/proc/iomem) when hotplugging 2G via virtio-mem
on x86-64:
[...]
100000000-13fffffff : System RAM
140000000-33fffffff : virtio0
140000000-147ffffff : System RAM (virtio_mem)
148000000-14fffffff : System RAM (virtio_mem)
150000000-157ffffff : System RAM (virtio_mem)
158000000-15fffffff : System RAM (virtio_mem)
160000000-167ffffff : System RAM (virtio_mem)
168000000-16fffffff : System RAM (virtio_mem)
170000000-177ffffff : System RAM (virtio_mem)
178000000-17fffffff : System RAM (virtio_mem)
180000000-187ffffff : System RAM (virtio_mem)
188000000-18fffffff : System RAM (virtio_mem)
190000000-197ffffff : System RAM (virtio_mem)
198000000-19fffffff : System RAM (virtio_mem)
1a0000000-1a7ffffff : System RAM (virtio_mem)
1a8000000-1afffffff : System RAM (virtio_mem)
1b0000000-1b7ffffff : System RAM (virtio_mem)
1b8000000-1bfffffff : System RAM (virtio_mem)
3280000000-32ffffffff : PCI Bus 0000:00
With this patch, we get (/proc/iomem):
[...]
fffc0000-ffffffff : Reserved
100000000-13fffffff : System RAM
140000000-33fffffff : virtio0
140000000-1bfffffff : System RAM (virtio_mem)
3280000000-32ffffffff : PCI Bus 0000:00
Of course, with more hotplugged memory, it gets worse. When unplugging
memory blocks again, try_remove_memory() (via
offline_and_remove_memory()) will properly split the resource up again.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Dan Williams <redacted>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Jason Wang <redacted>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
drivers/virtio/virtio_mem.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
From: David Hildenbrand <hidden> Date: 2020-08-21 10:35:48
Let's use the new mechanism to merge system ram resources below the
root. We are the only one hotplugging system ram, e.g., DIMMs don't apply,
so this is safe to be used.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Stephen Hemminger <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
drivers/hv/hv_balloon.c | 3 +++
1 file changed, 3 insertions(+)
@@ -745,6 +745,9 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,has->covered_end_pfn-=processed_pfn;spin_unlock_irqrestore(&dm_device.ha_lock,flags);break;+}else{+/* Try to reduce the number of system ram resources. */+merge_system_ram_resources(&iomem_resource);}/*
From: David Hildenbrand <hidden> Date: 2020-08-21 10:36:00
Let's reuse the new mechanism to merge system ram resources below the
root. We are the only one hotplugging system ram (e.g., DIMMs don't apply),
so this is safe to be used.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Roger Pau Monné <redacted>
Cc: Julien Grall <redacted>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
drivers/xen/balloon.c | 4 ++++
1 file changed, 4 insertions(+)
@@ -338,6 +338,10 @@ static enum bp_state reserve_additional_memory(void)if(rc){pr_warn("Cannot add additional memory (%i)\n",rc);gotoerr;+}else{+resource=NULL;+/* Try to reduce the number of system ram resources. */+merge_system_ram_resources(&iomem_resource);}balloon_stats.total_pages+=balloon_hotplug;
Some add_memory*() users add memory in small, contiguous memory blocks.
Examples include virtio-mem, hyper-v balloon, and the XEN balloon.
This can quickly result in a lot of memory resources, whereby the actual
resource boundaries are not of interest (e.g., it might be relevant for
DIMMs, exposed via /proc/iomem to user space). We really want to merge
added resources in this scenario where possible.
Let's provide an interface to trigger merging of applicable child
resources. It will be, for example, used by virtio-mem to trigger
merging of system ram resources it added to its resource container, but
also by XEN and Hyper-V to trigger merging of system ram resources in
iomem_resource.
Note: We really want to merge after the whole operation succeeded, not
directly when adding a resource to the resource tree (it would break
add_memory_resource() and require splitting resources again when the
operation failed - e.g., due to -ENOMEM).
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Dan Williams <redacted>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Kees Cook <redacted>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Thomas Gleixner <redacted>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Stephen Hemminger <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Roger Pau Monné <redacted>
Cc: Julien Grall <redacted>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
include/linux/ioport.h | 3 +++
kernel/resource.c | 52 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
From: Jürgen Groß <jgross@suse.com> Date: 2020-09-02 10:15:30
On 21.08.20 12:34, David Hildenbrand wrote:
quoted hunk
Let's reuse the new mechanism to merge system ram resources below the
root. We are the only one hotplugging system ram (e.g., DIMMs don't apply),
so this is safe to be used.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Roger Pau Monné <redacted>
Cc: Julien Grall <redacted>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
drivers/xen/balloon.c | 4 ++++
1 file changed, 4 insertions(+)
@@ -338,6 +338,10 @@ static enum bp_state reserve_additional_memory(void)if(rc){pr_warn("Cannot add additional memory (%i)\n",rc);gotoerr;+}else{+resource=NULL;+/* Try to reduce the number of system ram resources. */+merge_system_ram_resources(&iomem_resource);}
I don't see the need for setting resource to NULL and to use an "else"
clause here.
Juergen
From: David Hildenbrand <hidden> Date: 2020-09-02 10:34:29
Am 02.09.2020 um 12:15 schrieb Jürgen Groß [off-list ref]:
On 21.08.20 12:34, David Hildenbrand wrote:
quoted
Let's reuse the new mechanism to merge system ram resources below the
root. We are the only one hotplugging system ram (e.g., DIMMs don't apply),
so this is safe to be used.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Roger Pau Monné <redacted>
Cc: Julien Grall <redacted>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
drivers/xen/balloon.c | 4 ++++
1 file changed, 4 insertions(+)
@@ -338,6 +338,10 @@ static enum bp_state reserve_additional_memory(void)if(rc){pr_warn("Cannot add additional memory (%i)\n",rc);gotoerr;+}else{+resource=NULL;+/* Try to reduce the number of system ram resources. */+merge_system_ram_resources(&iomem_resource);}
I don't see the need for setting resource to NULL and to use an "else"
clause here.
I set it to NULL because the pointer may be stale after that call - to avoid future bugs. But I can drop it.
Ack to the „else“ case.
Thanks for having a look!
From: Wei Liu <wei.liu@kernel.org> Date: 2020-09-04 18:10:30
On Fri, Aug 21, 2020 at 12:34:31PM +0200, David Hildenbrand wrote:
quoted hunk
Let's use the new mechanism to merge system ram resources below the
root. We are the only one hotplugging system ram, e.g., DIMMs don't apply,
so this is safe to be used.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Stephen Hemminger <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
drivers/hv/hv_balloon.c | 3 +++
1 file changed, 3 insertions(+)
@@ -745,6 +745,9 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,has->covered_end_pfn-=processed_pfn;spin_unlock_irqrestore(&dm_device.ha_lock,flags);break;+}else{+/* Try to reduce the number of system ram resources. */+merge_system_ram_resources(&iomem_resource);}
You don't need to put the call under the "else" branch. It will have
broken out of the loop if ret is not zero.
Wei.
From: David Hildenbrand <hidden> Date: 2020-09-08 10:28:55
On 04.09.20 19:30, Wei Liu wrote:
On Fri, Aug 21, 2020 at 12:34:31PM +0200, David Hildenbrand wrote:
quoted
Let's use the new mechanism to merge system ram resources below the
root. We are the only one hotplugging system ram, e.g., DIMMs don't apply,
so this is safe to be used.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Stephen Hemminger <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
drivers/hv/hv_balloon.c | 3 +++
1 file changed, 3 insertions(+)
@@ -745,6 +745,9 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,has->covered_end_pfn-=processed_pfn;spin_unlock_irqrestore(&dm_device.ha_lock,flags);break;+}else{+/* Try to reduce the number of system ram resources. */+merge_system_ram_resources(&iomem_resource);}
You don't need to put the call under the "else" branch. It will have
broken out of the loop if ret is not zero.
From: David Hildenbrand <hidden> Date: 2020-09-08 10:29:13
On 31.08.20 11:35, Pankaj Gupta wrote:
quoted
Some add_memory*() users add memory in small, contiguous memory blocks.
Examples include virtio-mem, hyper-v balloon, and the XEN balloon.
This can quickly result in a lot of memory resources, whereby the actual
resource boundaries are not of interest (e.g., it might be relevant for
DIMMs, exposed via /proc/iomem to user space). We really want to merge
added resources in this scenario where possible.
Let's provide an interface to trigger merging of applicable child
resources. It will be, for example, used by virtio-mem to trigger
merging of system ram resources it added to its resource container, but
also by XEN and Hyper-V to trigger merging of system ram resources in
iomem_resource.
Note: We really want to merge after the whole operation succeeded, not
directly when adding a resource to the resource tree (it would break
add_memory_resource() and require splitting resources again when the
operation failed - e.g., due to -ENOMEM).
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Dan Williams <redacted>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Kees Cook <redacted>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Thomas Gleixner <redacted>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Stephen Hemminger <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Roger Pau Monné <redacted>
Cc: Julien Grall <redacted>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: Baoquan He <redacted>
Cc: Wei Yang <redacted>
Signed-off-by: David Hildenbrand <redacted>
---
include/linux/ioport.h | 3 +++
kernel/resource.c | 52 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
Maybe this can be changed to:
!(cur->flags & ~flags)
That would be different I think.
(cur->flags & flags) == flags
checks that all "flags" are set (additional ones might be set).
!(cur->flags & ~flags)
checks that no other flags besides "flags" are set (and "flags" are not
required to be set).
We use the same handling in find_next_iomem_res(), e.g., called via
walk_system_ram_range also with IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY.
Thanks for having a look!
--
Thanks,
David / dhildenb