linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Nadav Amit <namit@vmware.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Arnd Bergmann <arnd@arndb.de>
Cc: <linux-kernel@vger.kernel.org>,
	Xavier Deguillard <xdeguillard@vmware.com>,
	Nadav Amit <namit@vmware.com>
Subject: [PATCH v2 20/20] vmw_balloon: split refused pages
Date: Thu, 20 Sep 2018 10:30:26 -0700	[thread overview]
Message-ID: <20180920173026.141333-21-namit@vmware.com> (raw)
In-Reply-To: <20180920173026.141333-1-namit@vmware.com>

The hypervisor might refuse to inflate pages. While the balloon driver
handles this scenario correctly, a refusal to inflate a 2MB pages might
cause the same page to be allocated again later just for its inflation
to be refused again. This wastes energy and time.

To avoid this situation we split the 2MB page to 4KB pages, and then try
to inflate each one individually. Most of the 4KB pages out of the 2MB
should be inflated successfully, and we are likely to prevent the
scenario of repeated refused inflation.

Reviewed-by: Xavier Deguillard <xdeguillard@vmware.com>
Signed-off-by: Nadav Amit <namit@vmware.com>
---
 drivers/misc/vmw_balloon.c | 63 +++++++++++++++++++++++++++++++-------
 1 file changed, 52 insertions(+), 11 deletions(-)

diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 75407be8ddbc..34fceb82fe85 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -233,6 +233,7 @@ static DEFINE_STATIC_KEY_FALSE(balloon_stat_enabled);
 struct vmballoon_ctl {
 	struct list_head pages;
 	struct list_head refused_pages;
+	struct list_head prealloc_pages;
 	unsigned int n_refused_pages;
 	unsigned int n_pages;
 	enum vmballoon_page_size_type page_size;
@@ -632,15 +633,25 @@ static int vmballoon_alloc_page_list(struct vmballoon *b,
 	unsigned int i;
 
 	for (i = 0; i < req_n_pages; i++) {
-		if (ctl->page_size == VMW_BALLOON_2M_PAGE)
-			page = alloc_pages(__GFP_HIGHMEM|__GFP_NOWARN|
+		/*
+		 * First check if we happen to have pages that were allocated
+		 * before. This happens when 2MB page rejected during inflation
+		 * by the hypervisor, and then split into 4KB pages.
+		 */
+		if (!list_empty(&ctl->prealloc_pages)) {
+			page = list_first_entry(&ctl->prealloc_pages,
+						struct page, lru);
+			list_del(&page->lru);
+		} else {
+			if (ctl->page_size == VMW_BALLOON_2M_PAGE)
+				page = alloc_pages(__GFP_HIGHMEM|__GFP_NOWARN|
 					__GFP_NOMEMALLOC, VMW_BALLOON_2M_ORDER);
-		else
-			page = balloon_page_alloc();
+			else
+				page = balloon_page_alloc();
 
-		/* Update statistics */
-		vmballoon_stats_page_inc(b, VMW_BALLOON_PAGE_STAT_ALLOC,
-					 ctl->page_size);
+			vmballoon_stats_page_inc(b, VMW_BALLOON_PAGE_STAT_ALLOC,
+						 ctl->page_size);
+		}
 
 		if (page) {
 			/* Success. Add the page to the list and continue. */
@@ -884,7 +895,8 @@ static void vmballoon_release_page_list(struct list_head *page_list,
 		__free_pages(page, vmballoon_page_order(page_size));
 	}
 
-	*n_pages = 0;
+	if (n_pages)
+		*n_pages = 0;
 }
 
 
@@ -1016,6 +1028,32 @@ static void vmballoon_dequeue_page_list(struct vmballoon *b,
 	*n_pages = i;
 }
 
+/**
+ * vmballoon_split_refused_pages() - Split the 2MB refused pages to 4k.
+ *
+ * If inflation of 2MB pages was denied by the hypervisor, it is likely to be
+ * due to one or few 4KB pages. These 2MB pages may keep being allocated and
+ * then being refused. To prevent this case, this function splits the refused
+ * pages into 4KB pages and adds them into @prealloc_pages list.
+ *
+ * @ctl: pointer for the %struct vmballoon_ctl, which defines the operation.
+ */
+static void vmballoon_split_refused_pages(struct vmballoon_ctl *ctl)
+{
+	struct page *page, *tmp;
+	unsigned int i, order;
+
+	order = vmballoon_page_order(ctl->page_size);
+
+	list_for_each_entry_safe(page, tmp, &ctl->refused_pages, lru) {
+		list_del(&page->lru);
+		split_page(page, order);
+		for (i = 0; i < (1 << order); i++)
+			list_add(&page[i].lru, &ctl->prealloc_pages);
+	}
+	ctl->n_refused_pages = 0;
+}
+
 /**
  * vmballoon_inflate() - Inflate the balloon towards its target size.
  *
@@ -1027,6 +1065,7 @@ static void vmballoon_inflate(struct vmballoon *b)
 	struct vmballoon_ctl ctl = {
 		.pages = LIST_HEAD_INIT(ctl.pages),
 		.refused_pages = LIST_HEAD_INIT(ctl.refused_pages),
+		.prealloc_pages = LIST_HEAD_INIT(ctl.prealloc_pages),
 		.page_size = b->max_page_size,
 		.op = VMW_BALLOON_INFLATE
 	};
@@ -1074,10 +1113,10 @@ static void vmballoon_inflate(struct vmballoon *b)
 				break;
 
 			/*
-			 * Ignore errors from locking as we now switch to 4k
-			 * pages and we might get different errors.
+			 * Split the refused pages to 4k. This will also empty
+			 * the refused pages list.
 			 */
-			vmballoon_release_refused_pages(b, &ctl);
+			vmballoon_split_refused_pages(&ctl);
 			ctl.page_size--;
 		}
 
@@ -1091,6 +1130,8 @@ static void vmballoon_inflate(struct vmballoon *b)
 	 */
 	if (ctl.n_refused_pages != 0)
 		vmballoon_release_refused_pages(b, &ctl);
+
+	vmballoon_release_page_list(&ctl.prealloc_pages, NULL, ctl.page_size);
 }
 
 /**
-- 
2.17.1


  parent reply	other threads:[~2018-09-20 17:32 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-20 17:30 [PATCH v2 00/20] vmw_balloon: compaction, shrinker, 64-bit, etc Nadav Amit
2018-09-20 17:30 ` [PATCH v2 01/20] vmw_balloon: handle commands in a single function Nadav Amit
2018-09-20 17:30 ` [PATCH v2 02/20] vmw_balloon: unify commands tracing and stats Nadav Amit
2018-09-20 17:30 ` [PATCH v2 03/20] vmw_balloon: merge send_lock and send_unlock path Nadav Amit
2018-09-20 17:30 ` [PATCH v2 04/20] vmw_balloon: simplifying batch access Nadav Amit
2018-09-20 17:30 ` [PATCH v2 05/20] vmw_balloon: remove sleeping allocations Nadav Amit
2018-09-20 17:30 ` [PATCH v2 06/20] vmw_balloon: change batch/single lock abstractions Nadav Amit
2018-09-20 17:30 ` [PATCH v2 07/20] vmw_balloon: treat all refused pages equally Nadav Amit
2018-09-20 17:30 ` [PATCH v2 08/20] vmw_balloon: rename VMW_BALLOON_2M_SHIFT to VMW_BALLOON_2M_ORDER Nadav Amit
2018-09-20 17:30 ` [PATCH v2 09/20] vmw_balloon: refactor change size from vmballoon_work Nadav Amit
2018-09-20 17:30 ` [PATCH v2 10/20] vmw_balloon: simplify vmballoon_send_get_target() Nadav Amit
2018-09-20 17:30 ` [PATCH v2 11/20] vmw_balloon: stats rework Nadav Amit
2018-09-20 17:30 ` [PATCH v2 12/20] vmw_balloon: rework the inflate and deflate loops Nadav Amit
2018-09-20 17:30 ` [PATCH v2 13/20] vmw_balloon: general style cleanup Nadav Amit
2018-09-20 17:30 ` [PATCH v2 14/20] vmw_balloon: add reset stat Nadav Amit
2018-09-20 17:30 ` [PATCH v2 15/20] mm/balloon_compaction: suppress allocation warnings Nadav Amit
2018-09-20 17:30 ` [PATCH v2 16/20] mm/balloon_compaction: list interfaces Nadav Amit
2018-09-20 17:30 ` [PATCH v2 17/20] vmw_balloon: compaction support Nadav Amit
2018-09-25 18:15   ` Greg Kroah-Hartman
2018-09-20 17:30 ` [PATCH v2 18/20] vmw_balloon: support 64-bit memory limit Nadav Amit
2018-09-20 17:30 ` [PATCH v2 19/20] vmw_balloon: memory shrinker Nadav Amit
2018-09-20 17:30 ` Nadav Amit [this message]
2018-09-25 18:15 ` [PATCH v2 00/20] vmw_balloon: compaction, shrinker, 64-bit, etc Greg Kroah-Hartman
2018-09-25 19:55   ` Nadav Amit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180920173026.141333-21-namit@vmware.com \
    --to=namit@vmware.com \
    --cc=arnd@arndb.de \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=xdeguillard@vmware.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).