From: Miaohe Lin linmiaohe@huawei.com
[ Upstream commit 0cbcc92917c5de80f15c24d033566539ad696892 ]
Since commit ebff7d8f270d ("mem hotunplug: fix kfree() of bootmem memory"), we could get a resource allocated during boot via alloc_resource(). And it's required to release the resource using free_resource(). Howerver, many people use kfree directly which will result in kernel BUG. In order to fix this without fixing every call site, just leak a couple of bytes in such corner case.
Link: https://lkml.kernel.org/r/20220217083619.19305-1-linmiaohe@huawei.com Fixes: ebff7d8f270d ("mem hotunplug: fix kfree() of bootmem memory") Signed-off-by: Miaohe Lin linmiaohe@huawei.com Suggested-by: David Hildenbrand david@redhat.com Cc: Dan Williams dan.j.williams@intel.com Cc: Alistair Popple apopple@nvidia.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: David Sauerwein dssauerw@amazon.de --- kernel/resource.c | 41 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-)
diff --git a/kernel/resource.c b/kernel/resource.c index 1087f33d70c4..ea4d7a02b8e8 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -53,14 +53,6 @@ struct resource_constraint {
static DEFINE_RWLOCK(resource_lock);
-/* - * For memory hotplug, there is no way to free resource entries allocated - * by boot mem after the system is up. So for reusing the resource entry - * we need to remember the resource. - */ -static struct resource *bootmem_resource_free; -static DEFINE_SPINLOCK(bootmem_resource_lock); - static struct resource *next_resource(struct resource *p, bool sibling_only) { /* Caller wants to traverse through siblings only */ @@ -149,36 +141,19 @@ __initcall(ioresources_init);
static void free_resource(struct resource *res) { - if (!res) - return; - - if (!PageSlab(virt_to_head_page(res))) { - spin_lock(&bootmem_resource_lock); - res->sibling = bootmem_resource_free; - bootmem_resource_free = res; - spin_unlock(&bootmem_resource_lock); - } else { + /** + * If the resource was allocated using memblock early during boot + * we'll leak it here: we can only return full pages back to the + * buddy and trying to be smart and reusing them eventually in + * alloc_resource() overcomplicates resource handling. + */ + if (res && PageSlab(virt_to_head_page(res))) kfree(res); - } }
static struct resource *alloc_resource(gfp_t flags) { - struct resource *res = NULL; - - spin_lock(&bootmem_resource_lock); - if (bootmem_resource_free) { - res = bootmem_resource_free; - bootmem_resource_free = res->sibling; - } - spin_unlock(&bootmem_resource_lock); - - if (res) - memset(res, 0, sizeof(struct resource)); - else - res = kzalloc(sizeof(struct resource), flags); - - return res; + return kzalloc(sizeof(struct resource), flags); }
/* Return the conflict entry if you can't request it */
[ Sasha's backport helper bot ]
Hi,
✅ All tests passed successfully. No issues detected. No action required from the submitter.
The upstream commit SHA1 provided is correct: 0cbcc92917c5de80f15c24d033566539ad696892
WARNING: Author mismatch between patch and upstream commit: Backport author: David Sauerweindssauerw@amazon.de Commit author: Miaohe Linlinmiaohe@huawei.com
Status in newer kernel trees: 6.14.y | Present (exact SHA1) 6.13.y | Present (exact SHA1) 6.12.y | Present (exact SHA1) 6.6.y | Present (exact SHA1) 6.1.y | Present (exact SHA1) 5.15.y | Present (different SHA1: a9e88c2618d2)
Note: The patch differs from the upstream commit: --- 1: 0cbcc92917c5d ! 1: ff999c67c7e5b kernel/resource: fix kfree() of bootmem memory again @@ Metadata ## Commit message ## kernel/resource: fix kfree() of bootmem memory again
+ [ Upstream commit 0cbcc92917c5de80f15c24d033566539ad696892 ] + Since commit ebff7d8f270d ("mem hotunplug: fix kfree() of bootmem memory"), we could get a resource allocated during boot via alloc_resource(). And it's required to release the resource using @@ Commit message Cc: Alistair Popple apopple@nvidia.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org + Signed-off-by: Sasha Levin sashal@kernel.org + Signed-off-by: David Sauerwein dssauerw@amazon.de
## kernel/resource.c ## @@ kernel/resource.c: struct resource_constraint { @@ kernel/resource.c: struct resource_constraint { -static struct resource *bootmem_resource_free; -static DEFINE_SPINLOCK(bootmem_resource_lock); - - static struct resource *next_resource(struct resource *p) + static struct resource *next_resource(struct resource *p, bool sibling_only) { - if (p->child) + /* Caller wants to traverse through siblings only */ @@ kernel/resource.c: __initcall(ioresources_init);
static void free_resource(struct resource *res) ---
Results of testing on various branches:
| Branch | Patch Apply | Build Test | |---------------------------|-------------|------------| | stable/linux-5.10.y | Success | Success |
linux-stable-mirror@lists.linaro.org