xen: let alloc_xenballooned_pages() fail if not enough memory free [Linux 4.9.187]

This Linux kernel change "xen: let alloc_xenballooned_pages() fail if not enough memory free" is included in the Linux 4.9.187 release. This change is authored by Juergen Gross <jgross [at] suse.com> on Wed Jun 19 11:00:56 2019 +0200. The commit for this change in Linux stable tree is 259b0fc (patch) which is from upstream commit a1078e8. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream a1078e8.

xen: let alloc_xenballooned_pages() fail if not enough memory free

commit a1078e821b605813b63bf6bca414a85f804d5c66 upstream.

Instead of trying to allocate pages with GFP_USER in
add_ballooned_pages() check the available free memory via
si_mem_available(). GFP_USER is far less limiting memory exhaustion
than the test via si_mem_available().

This will avoid dom0 running out of memory due to excessive foreign
page mappings especially on ARM and on x86 in PVH mode, as those don't
have a pre-ballooned area which can be used for foreign mappings.

As the normal ballooning suffers from the same problem don't balloon
down more than si_mem_available() pages in one iteration. At the same
time limit the default maximum number of retries.

This is part of XSA-300.

Signed-off-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 16 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/xen/balloon.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index e4db19e..6af117a 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -591,8 +591,15 @@ static void balloon_process(struct work_struct *work)
                state = reserve_additional_memory();

-       if (credit < 0)
-           state = decrease_reservation(-credit, GFP_BALLOON);
+       if (credit < 0) {
+           long n_pages;
+           n_pages = min(-credit, si_mem_available());
+           state = decrease_reservation(n_pages, GFP_BALLOON);
+           if (state == BP_DONE && n_pages != -credit &&
+               n_pages < totalreserve_pages)
+               state = BP_EAGAIN;
+       }

        state = update_schedule(state);

@@ -631,6 +638,9 @@ static int add_ballooned_pages(int nr_pages)

+   if (si_mem_available() < nr_pages)
+       return -ENOMEM;
    st = decrease_reservation(nr_pages, GFP_USER);
    if (st != BP_DONE)
        return -ENOMEM;
@@ -754,7 +764,7 @@ static int __init balloon_init(void)
    balloon_stats.schedule_delay = 1;
    balloon_stats.max_schedule_delay = 32;
    balloon_stats.retry_count = 1;
-   balloon_stats.max_retry_count = RETRY_UNLIMITED;
+   balloon_stats.max_retry_count = 4;


Leave a Reply

Your email address will not be published. Required fields are marked *