To avoid memory leaks, destroy ghes_estatus_pool and release memory allocated via vmalloc() on errors in ghes_estatus_pool_init(). Signed-off-by: Liguang Zhang <zhangliguang@xxxxxxxxxxxxxxxxx> --- drivers/acpi/apei/ghes.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index a66e00f..6d42ae1 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -153,10 +153,11 @@ static void ghes_unmap(void __iomem *vaddr, enum fixed_addresses fixmap_idx) int ghes_estatus_pool_init(int num_ghes) { unsigned long addr, len; + int rc = 0; ghes_estatus_pool = gen_pool_create(GHES_ESTATUS_POOL_MIN_ALLOC_ORDER, -1); if (!ghes_estatus_pool) - return -ENOMEM; + goto nomem; len = GHES_ESTATUS_CACHE_AVG_SIZE * GHES_ESTATUS_CACHE_ALLOCED_MAX; len += (num_ghes * GHES_ESOURCE_PREALLOC_MAX_SIZE); @@ -164,7 +165,7 @@ int ghes_estatus_pool_init(int num_ghes) ghes_estatus_pool_size_request = PAGE_ALIGN(len); addr = (unsigned long)vmalloc(PAGE_ALIGN(len)); if (!addr) - return -ENOMEM; + goto pool_destroy; /* * New allocation must be visible in all pgd before it can be found by @@ -172,7 +173,17 @@ int ghes_estatus_pool_init(int num_ghes) */ vmalloc_sync_all(); - return gen_pool_add(ghes_estatus_pool, addr, PAGE_ALIGN(len), -1); + rc = gen_pool_add(ghes_estatus_pool, addr, PAGE_ALIGN(len), -1); + if (rc) + goto pool_destroy; + return 0; + +pool_destroy: + gen_pool_destroy(ghes_estatus_pool); + if (addr) + vfree((void *)addr); +nomem: + return -ENOMEM; } static int map_gen_v2(struct ghes *ghes) -- 1.8.3.1