grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] mm: Adjust new region size to take management cost into acco


From: Zhang Boyang
Subject: [PATCH 1/2] mm: Adjust new region size to take management cost into account
Date: Tue, 29 Nov 2022 22:17:33 +0800

When grub_memalign() encounters out-of-memory, it will try
grub_mm_add_region_fn() to request more memory from system firmware.
However, the size passed to it doesn't take region management cost into
account. Adding a memory area of `size` bytes will result in a heap
region of less than `size` bytes truely avaliable. Thus, the new region
might not adequate for current allocation request, confusing
out-of-memory handling code.

This patch introduces GRUB_MM_MAX_COST to address the region management
cost (e.g. metadata, alignment). The value of this new constant should
make `grub_malloc (size)` always success after a successful call to
`grub_mm_init_region (addr, size + GRUB_MM_MAX_COST)`.

The new region size is now set to `size + GRUB_MM_MAX_COST`, thus if
grub_mm_add_region_fn() succeeded, current allocation request can always
success.

Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
---
 grub-core/kern/mm.c       | 15 ++++++++++++---
 include/grub/mm_private.h |  9 +++++++++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
index ae2279133..973cb6b15 100644
--- a/grub-core/kern/mm.c
+++ b/grub-core/kern/mm.c
@@ -410,7 +410,9 @@ grub_memalign (grub_size_t align, grub_size_t size)
 {
   grub_mm_region_t r;
   grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1;
+  grub_size_t bound;
   int count = 0;
+  grub_size_t grow;
 
   if (!grub_mm_base)
     goto fail;
@@ -418,10 +420,13 @@ grub_memalign (grub_size_t align, grub_size_t size)
   if (size > ~(grub_size_t) align)
     goto fail;
 
+  /* If largest free chunk in region >= bound, allocation can always success */
+  bound = size + align;
+
   /* We currently assume at least a 32-bit grub_size_t,
      so limiting allocations to <adress space size> - 1MiB
      in name of sanity is beneficial. */
-  if ((size + align) > ~(grub_size_t) 0x100000)
+  if (bound > ~(grub_size_t) 0x100000)
     goto fail;
 
   align = (align >> GRUB_MM_ALIGN_LOG2);
@@ -443,11 +448,15 @@ grub_memalign (grub_size_t align, grub_size_t size)
   switch (count)
     {
     case 0:
+      /* Adjust heap growth to address the region management cost. */
+      if (grub_add (bound, GRUB_MM_MAX_COST, &grow))
+       goto fail;
+
       /* Request additional pages, contiguous */
       count++;
 
       if (grub_mm_add_region_fn != NULL &&
-          grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == 
GRUB_ERR_NONE)
+          grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_CONSECUTIVE) == 
GRUB_ERR_NONE)
        goto again;
 
       /* fallthrough  */
@@ -462,7 +471,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
            * Try again even if this fails, in case it was able to partially
            * satisfy the request
            */
-          grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE);
+          grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_NONE);
           goto again;
         }
 
diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h
index 96c2d816b..f212110e4 100644
--- a/include/grub/mm_private.h
+++ b/include/grub/mm_private.h
@@ -95,6 +95,15 @@ typedef struct grub_mm_region
 }
 *grub_mm_region_t;
 
+/*
+ * Set an upper bound of management cost of each region,
+ * with sizeof(struct grub_mm_region), sizeof(struct grub_mm_header) and
+ * any possible alignment or padding taken into account.
+ * The value should make `grub_malloc (size)` always success after a successful
+ * call to `grub_mm_init_region (addr, size + GRUB_MM_MAX_COST)`.
+ */
+#define GRUB_MM_MAX_COST 0x1000
+
 #ifndef GRUB_MACHINE_EMU
 extern grub_mm_region_t EXPORT_VAR (grub_mm_base);
 #endif
-- 
2.30.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]