From fdcab13767a291ea0a5163da3946a99dee6d34f8 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Thu, 1 Jun 2017 17:48:04 -0700 Subject: [PATCH] qcacmn: Do not free leaked memory if halt on kmem leak is enabled If halt on memory leak is enabled then do not free the leaked memory because when leaked memory gets freed kernel poisons it with 0x6Bs and all useful data from leaked memory gets lost. In addition add the leaked memory in a global trash list such that leaked memory can be extracted for offline debugging. Change-Id: Ie37fd810199e845831c3c3f325ef1e9ff60c5f37 CRs-Fixed: 2055470 --- qdf/linux/src/qdf_mem.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/qdf/linux/src/qdf_mem.c b/qdf/linux/src/qdf_mem.c index 5d78dfb5f008..33781e9c39a0 100644 --- a/qdf/linux/src/qdf_mem.c +++ b/qdf/linux/src/qdf_mem.c @@ -58,8 +58,9 @@ #ifdef MEMORY_DEBUG #include -qdf_list_t qdf_mem_list; -qdf_spinlock_t qdf_mem_list_lock; +static qdf_list_t qdf_mem_list; +static qdf_list_t qdf_mem_trash_list; +static qdf_spinlock_t qdf_mem_list_lock; static uint8_t WLAN_MEM_HEADER[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68 }; @@ -804,11 +805,30 @@ static void qdf_mem_debug_init(void) { /* Initalizing the list with maximum size of 60000 */ qdf_list_create(&qdf_mem_list, 60000); + qdf_list_create(&qdf_mem_trash_list, 60000); qdf_spinlock_create(&qdf_mem_list_lock); qdf_net_buf_debug_init(); return; } +#ifdef CONFIG_HALT_KMEMLEAK +static void qdf_handle_leaked_memory(qdf_list_node_t *node) +{ + /* do not free the leaked memory if halt on memleak is enabled + * such that leaked memory does not get poisoned and can be + * used for offline debugging + */ + qdf_spin_lock(&qdf_mem_list_lock); + qdf_list_insert_front(&qdf_mem_trash_list, node); + qdf_spin_unlock(&qdf_mem_list_lock); +} +#else +static void qdf_handle_leaked_memory(qdf_list_node_t *node) +{ + kfree((void *)node); +} +#endif + /** * qdf_mem_debug_clean() - display memory leak debug info and free leaked * pointers @@ -863,7 +883,7 @@ static void qdf_mem_debug_clean(void) mleak_cnt = 0; } mleak_cnt++; - kfree((void *)mem_struct); + qdf_handle_leaked_memory(node); } } while (qdf_status == QDF_STATUS_SUCCESS);