Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1191753 > unrolled thread

[PATCHv2 00/10] mm, xen/balloon: memory hotplug improvements

Started byDavid Vrabel <david.vrabel@citrix.com>
First post2015-07-24 13:50 +0200
Last post2015-07-27 11:40 +0200
Articles 6 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCHv2 00/10] mm, xen/balloon: memory hotplug improvements David Vrabel <david.vrabel@citrix.com> - 2015-07-24 13:50 +0200
    [PATCHv2 07/10] xen/balloon: make alloc_xenballoon_pages() always allocate low pages David Vrabel <david.vrabel@citrix.com> - 2015-07-24 13:50 +0200
    [PATCHv2 09/10] x86/xen: export xen_alloc_p2m_entry() David Vrabel <david.vrabel@citrix.com> - 2015-07-24 14:00 +0200
    [PATCHv2 04/10] xen/balloon: find non-conflicting regions to place hotplugged memory David Vrabel <david.vrabel@citrix.com> - 2015-07-24 14:00 +0200
    [PATCHv2 10/10] xen/balloon: pre-allocate p2m entries for ballooned pages David Vrabel <david.vrabel@citrix.com> - 2015-07-24 14:20 +0200
      Re: [Xen-devel] [PATCHv2 10/10] xen/balloon: pre-allocate p2m entries  for ballooned pages David Vrabel <david.vrabel@citrix.com> - 2015-07-27 11:40 +0200

#1191753 — [PATCHv2 00/10] mm, xen/balloon: memory hotplug improvements

FromDavid Vrabel <david.vrabel@citrix.com>
Date2015-07-24 13:50 +0200
Subject[PATCHv2 00/10] mm, xen/balloon: memory hotplug improvements
Message-ID<pPJEd-4HJ-5@gated-at.bofh.it>
The series improves the use of hotplug memory in the Xen balloon
driver.

- Reliably find a non-conflicting location for the hotplugged memory
  (this fixes memory hotplug in a number of cases, particularly in
  dom0).

- Use hotplugged memory for alloc_xenballooned_pages() (keeping more
  memory available for the domain and reducing fragmentation of the
  p2m).

Changes in v2:
- New BP_WAIT state to signal the balloon process to wait for
  userspace to online the new memory.
- Preallocate P2M entries in alloc_xenballooned_pages() so they do not
  need allocated later (in a context where GFP_KERNEL allocations are
  not possible).

David
--
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/

[toc] | [next] | [standalone]


#1191756 — [PATCHv2 07/10] xen/balloon: make alloc_xenballoon_pages() always allocate low pages

FromDavid Vrabel <david.vrabel@citrix.com>
Date2015-07-24 13:50 +0200
Subject[PATCHv2 07/10] xen/balloon: make alloc_xenballoon_pages() always allocate low pages
Message-ID<pPJEf-4HJ-39@gated-at.bofh.it>
In reply to#1191753
All users of alloc_xenballoon_pages() wanted low memory pages, so
remove the option for high memory.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 arch/x86/xen/grant-table.c         |  2 +-
 drivers/xen/balloon.c              | 21 ++++++++-------------
 drivers/xen/grant-table.c          |  2 +-
 drivers/xen/privcmd.c              |  2 +-
 drivers/xen/xenbus/xenbus_client.c |  3 +--
 include/xen/balloon.h              |  3 +--
 6 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c
index 1580e7a..e079500 100644
--- a/arch/x86/xen/grant-table.c
+++ b/arch/x86/xen/grant-table.c
@@ -133,7 +133,7 @@ static int __init xlated_setup_gnttab_pages(void)
 		kfree(pages);
 		return -ENOMEM;
 	}
-	rc = alloc_xenballooned_pages(nr_grant_frames, pages, 0 /* lowmem */);
+	rc = alloc_xenballooned_pages(nr_grant_frames, pages);
 	if (rc) {
 		pr_warn("%s Couldn't balloon alloc %ld pfns rc:%d\n", __func__,
 			nr_grant_frames, rc);
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index ced34cd..cc68a4d 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -136,17 +136,16 @@ static void balloon_append(struct page *page)
 }
 
 /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
-static struct page *balloon_retrieve(bool prefer_highmem)
+static struct page *balloon_retrieve(bool require_lowmem)
 {
 	struct page *page;
 
 	if (list_empty(&ballooned_pages))
 		return NULL;
 
-	if (prefer_highmem)
-		page = list_entry(ballooned_pages.prev, struct page, lru);
-	else
-		page = list_entry(ballooned_pages.next, struct page, lru);
+	page = list_entry(ballooned_pages.next, struct page, lru);
+	if (require_lowmem && PageHighMem(page))
+		return NULL;
 	list_del(&page->lru);
 
 	if (PageHighMem(page))
@@ -533,24 +532,20 @@ EXPORT_SYMBOL_GPL(balloon_set_new_target);
  * alloc_xenballooned_pages - get pages that have been ballooned out
  * @nr_pages: Number of pages to get
  * @pages: pages returned
- * @highmem: allow highmem pages
  * @return 0 on success, error otherwise
  */
-int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
+int alloc_xenballooned_pages(int nr_pages, struct page **pages)
 {
 	int pgno = 0;
 	struct page *page;
 	mutex_lock(&balloon_mutex);
 	while (pgno < nr_pages) {
-		page = balloon_retrieve(highmem);
-		if (page && (highmem || !PageHighMem(page))) {
+		page = balloon_retrieve(true);
+		if (page) {
 			pages[pgno++] = page;
 		} else {
 			enum bp_state st;
-			if (page)
-				balloon_append(page);
-			st = decrease_reservation(nr_pages - pgno,
-					highmem ? GFP_HIGHUSER : GFP_USER);
+			st = decrease_reservation(nr_pages - pgno, GFP_USER);
 			if (st != BP_DONE)
 				goto out_undo;
 		}
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 62f591f..a4b702c 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -687,7 +687,7 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages)
 	int i;
 	int ret;
 
-	ret = alloc_xenballooned_pages(nr_pages, pages, false);
+	ret = alloc_xenballooned_pages(nr_pages, pages);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 5a29616..59cfec9 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -401,7 +401,7 @@ static int alloc_empty_pages(struct vm_area_struct *vma, int numpgs)
 	if (pages == NULL)
 		return -ENOMEM;
 
-	rc = alloc_xenballooned_pages(numpgs, pages, 0);
+	rc = alloc_xenballooned_pages(numpgs, pages);
 	if (rc != 0) {
 		pr_warn("%s Could not alloc %d pfns rc:%d\n", __func__,
 			numpgs, rc);
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 9ad3272..2a2da04 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -614,8 +614,7 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
 	if (!node)
 		return -ENOMEM;
 
-	err = alloc_xenballooned_pages(nr_grefs, node->hvm.pages,
-				       false /* lowmem */);
+	err = alloc_xenballooned_pages(nr_grefs, node->hvm.pages);
 	if (err)
 		goto out_err;
 
diff --git a/include/xen/balloon.h b/include/xen/balloon.h
index c8aee7a..83efdeb 100644
--- a/include/xen/balloon.h
+++ b/include/xen/balloon.h
@@ -22,8 +22,7 @@ extern struct balloon_stats balloon_stats;
 
 void balloon_set_new_target(unsigned long target);
 
-int alloc_xenballooned_pages(int nr_pages, struct page **pages,
-		bool highmem);
+int alloc_xenballooned_pages(int nr_pages, struct page **pages);
 void free_xenballooned_pages(int nr_pages, struct page **pages);
 
 struct device;
-- 
2.1.4

--
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/

[toc] | [prev] | [next] | [standalone]


#1191759 — [PATCHv2 09/10] x86/xen: export xen_alloc_p2m_entry()

FromDavid Vrabel <david.vrabel@citrix.com>
Date2015-07-24 14:00 +0200
Subject[PATCHv2 09/10] x86/xen: export xen_alloc_p2m_entry()
Message-ID<pPJNV-4T4-5@gated-at.bofh.it>
In reply to#1191753
Rename alloc_p2m() to xen_alloc_p2m_entry() and export it.

This is useful for ensuring that a p2m entry is allocated (i.e., not a
shared missing or identity entry) so that subsequent set_phys_to_machine()
calls will require no further allocations.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
---
 arch/x86/include/asm/xen/page.h |  2 ++
 arch/x86/xen/p2m.c              | 16 ++++++++++------
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index c44a5d5..960b380 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -45,6 +45,8 @@ extern unsigned long *xen_p2m_addr;
 extern unsigned long  xen_p2m_size;
 extern unsigned long  xen_max_p2m_pfn;
 
+extern int xen_alloc_p2m_entry(unsigned long pfn);
+
 extern unsigned long get_phys_to_machine(unsigned long pfn);
 extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn);
 extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 8b7f18e..ef93ccf 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -503,7 +503,7 @@ static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *pte_pg)
  * the new pages are installed with cmpxchg; if we lose the race then
  * simply free the page we allocated and use the one that's there.
  */
-static bool alloc_p2m(unsigned long pfn)
+int xen_alloc_p2m_entry(unsigned long pfn)
 {
 	unsigned topidx, mididx;
 	unsigned long *top_mfn_p, *mid_mfn;
@@ -524,7 +524,7 @@ static bool alloc_p2m(unsigned long pfn)
 		/* PMD level is missing, allocate a new one */
 		ptep = alloc_p2m_pmd(addr, pte_pg);
 		if (!ptep)
-			return false;
+			return -ENOMEM;
 	}
 
 	if (p2m_top_mfn) {
@@ -541,7 +541,7 @@ static bool alloc_p2m(unsigned long pfn)
 
 			mid_mfn = alloc_p2m_page();
 			if (!mid_mfn)
-				return false;
+				return -ENOMEM;
 
 			p2m_mid_mfn_init(mid_mfn, p2m_missing);
 
@@ -567,7 +567,7 @@ static bool alloc_p2m(unsigned long pfn)
 
 		p2m = alloc_p2m_page();
 		if (!p2m)
-			return false;
+			return -ENOMEM;
 
 		if (p2m_pfn == PFN_DOWN(__pa(p2m_missing)))
 			p2m_init(p2m);
@@ -590,8 +590,9 @@ static bool alloc_p2m(unsigned long pfn)
 			free_p2m_page(p2m);
 	}
 
-	return true;
+	return 0;
 }
+EXPORT_SYMBOL(xen_alloc_p2m);
 
 unsigned long __init set_phys_range_identity(unsigned long pfn_s,
 				      unsigned long pfn_e)
@@ -648,7 +649,10 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
 	if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
-		if (!alloc_p2m(pfn))
+		int ret;
+
+		ret = xen_alloc_p2m_entry(pfn);
+		if (ret < 0)
 			return false;
 
 		return __set_phys_to_machine(pfn, mfn);
-- 
2.1.4

--
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/

[toc] | [prev] | [next] | [standalone]


#1191765 — [PATCHv2 04/10] xen/balloon: find non-conflicting regions to place hotplugged memory

FromDavid Vrabel <david.vrabel@citrix.com>
Date2015-07-24 14:00 +0200
Subject[PATCHv2 04/10] xen/balloon: find non-conflicting regions to place hotplugged memory
Message-ID<pPJNV-4T4-25@gated-at.bofh.it>
In reply to#1191753
Instead of placing hotplugged memory at the end of RAM (which may
conflict with PCI devices or reserved regions) use allocate_resource()
to get a new, suitably aligned resource that does not conflict.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 drivers/xen/balloon.c | 64 +++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 54 insertions(+), 10 deletions(-)

diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index fd93369..29aeb8f 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -54,6 +54,7 @@
 #include <linux/memory.h>
 #include <linux/memory_hotplug.h>
 #include <linux/percpu-defs.h>
+#include <linux/slab.h>
 
 #include <asm/page.h>
 #include <asm/pgalloc.h>
@@ -208,6 +209,43 @@ static bool balloon_is_inflated(void)
 		return false;
 }
 
+static struct resource *additional_memory_resource(phys_addr_t size)
+{
+	struct resource *res;
+	int ret;
+
+	res = kzalloc(sizeof(*res), GFP_KERNEL);
+	if (!res)
+		return NULL;
+
+	res->name = "System RAM";
+	res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+	ret = allocate_resource(&iomem_resource, res,
+				size, 0, -1,
+				PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
+	if (ret < 0) {
+		pr_err("Cannot allocate new System RAM resource\n");
+		kfree(res);
+		return NULL;
+	}
+
+	return res;
+}
+
+static void release_memory_resource(struct resource *resource)
+{
+	if (!resource)
+		return;
+
+	/*
+	 * No need to reset region to identity mapped since we now
+	 * know that no I/O can be in this region
+	 */
+	release_resource(resource);
+	kfree(resource);
+}
+
 /*
  * reserve_additional_memory() adds memory region of size >= credit above
  * max_pfn. New region is section aligned and size is modified to be multiple
@@ -221,13 +259,17 @@ static bool balloon_is_inflated(void)
 
 static enum bp_state reserve_additional_memory(long credit)
 {
+	struct resource *resource;
 	int nid, rc;
-	u64 hotplug_start_paddr;
-	unsigned long balloon_hotplug = credit;
+	unsigned long balloon_hotplug;
+
+	balloon_hotplug = round_up(credit, PAGES_PER_SECTION);
+
+	resource = additional_memory_resource(balloon_hotplug * PAGE_SIZE);
+	if (!resource)
+		goto err;
 
-	hotplug_start_paddr = PFN_PHYS(SECTION_ALIGN_UP(max_pfn));
-	balloon_hotplug = round_up(balloon_hotplug, PAGES_PER_SECTION);
-	nid = memory_add_physaddr_to_nid(hotplug_start_paddr);
+	nid = memory_add_physaddr_to_nid(resource->start);
 
 #ifdef CONFIG_XEN_HAVE_PVMMU
         /*
@@ -242,21 +284,20 @@ static enum bp_state reserve_additional_memory(long credit)
 	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
 		unsigned long pfn, i;
 
-		pfn = PFN_DOWN(hotplug_start_paddr);
+		pfn = PFN_DOWN(resource->start);
 		for (i = 0; i < balloon_hotplug; i++) {
 			if (!set_phys_to_machine(pfn + i, INVALID_P2M_ENTRY)) {
 				pr_warn("set_phys_to_machine() failed, no memory added\n");
-				return BP_ECANCELED;
+				goto err;
 			}
                 }
 	}
 #endif
 
-	rc = add_memory(nid, hotplug_start_paddr, balloon_hotplug << PAGE_SHIFT);
-
+	rc = add_memory_resource(nid, resource);
 	if (rc) {
 		pr_warn("Cannot add additional memory (%i)\n", rc);
-		return BP_ECANCELED;
+		goto err;
 	}
 
 	balloon_hotplug -= credit;
@@ -265,6 +306,9 @@ static enum bp_state reserve_additional_memory(long credit)
 	balloon_stats.balloon_hotplug = balloon_hotplug;
 
 	return BP_DONE;
+  err:
+	release_memory_resource(resource);
+	return BP_ECANCELED;
 }
 
 static void xen_online_page(struct page *page)
-- 
2.1.4

--
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/

[toc] | [prev] | [next] | [standalone]


#1191776 — [PATCHv2 10/10] xen/balloon: pre-allocate p2m entries for ballooned pages

FromDavid Vrabel <david.vrabel@citrix.com>
Date2015-07-24 14:20 +0200
Subject[PATCHv2 10/10] xen/balloon: pre-allocate p2m entries for ballooned pages
Message-ID<pPK7h-5uX-25@gated-at.bofh.it>
In reply to#1191753
Pages returned by alloc_xenballooned_pages() will be used for grant
mapping which will call set_phys_to_machine() (in PV guests).

Ballooned pages are set as INVALID_P2M_ENTRY in the p2m and thus may
be using the (shared) missing tables and a subsequent
set_phys_to_machine() will need to allocate new tables.

Since the grant mapping may be done from a context that cannot sleep,
the p2m entries must already be allocated.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
---
 drivers/xen/balloon.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index fd6970f3..8932d10 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -541,6 +541,7 @@ int alloc_xenballooned_pages(int nr_pages, struct page **pages)
 {
 	int pgno = 0;
 	struct page *page;
+	int ret = -ENOMEM;
 
 	mutex_lock(&balloon_mutex);
 
@@ -550,6 +551,11 @@ int alloc_xenballooned_pages(int nr_pages, struct page **pages)
 		page = balloon_retrieve(true);
 		if (page) {
 			pages[pgno++] = page;
+#ifdef CONFIG_XEN_HAVE_PVMMU
+			ret = xen_alloc_p2m_entry(page_to_pfn(page));
+			if (ret < 0)
+				goto out_undo;
+#endif
 		} else {
 			enum bp_state st;
 
@@ -576,7 +582,7 @@ int alloc_xenballooned_pages(int nr_pages, struct page **pages)
  out_undo:
 	mutex_unlock(&balloon_mutex);
 	free_xenballooned_pages(pgno, pages);
-	return -ENOMEM;
+	return ret;
 }
 EXPORT_SYMBOL(alloc_xenballooned_pages);
 
-- 
2.1.4

--
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/

[toc] | [prev] | [next] | [standalone]


#1192875 — Re: [Xen-devel] [PATCHv2 10/10] xen/balloon: pre-allocate p2m entries for ballooned pages

FromDavid Vrabel <david.vrabel@citrix.com>
Date2015-07-27 11:40 +0200
SubjectRe: [Xen-devel] [PATCHv2 10/10] xen/balloon: pre-allocate p2m entries for ballooned pages
Message-ID<pQN34-62M-13@gated-at.bofh.it>
In reply to#1191776
On 25/07/15 00:21, Julien Grall wrote:
> On 24/07/2015 12:47, David Vrabel wrote:
>> @@ -550,6 +551,11 @@ int alloc_xenballooned_pages(int nr_pages, struct
>> page **pages)
>>           page = balloon_retrieve(true);
>>           if (page) {
>>               pages[pgno++] = page;
>> +#ifdef CONFIG_XEN_HAVE_PVMMU
>> +            ret = xen_alloc_p2m_entry(page_to_pfn(page));
> 
> Don't you want to call this function only when the guest is not using
> auto-translated physmap?

xen_alloc_p2m_entry() is a nop in auto-xlate guests, so no need for an
additional check here.

David
--
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/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web