aboutsummaryrefslogtreecommitdiffstats
path: root/mm/percpu.c
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2011-09-26 12:12:53 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2011-12-02 11:12:42 -0500
commitf528f0b8e53d73b18be71e96693cfab9322f33c7 (patch)
tree5a25d6ac1c2f18561e554074aa7c06bf3d899183 /mm/percpu.c
parent74341703edca6bc68a165a18453071b097828407 (diff)
kmemleak: Handle percpu memory allocation
This patch adds kmemleak callbacks from the percpu allocator, reducing a number of false positives caused by kmemleak not scanning such memory blocks. The percpu chunks are never reported as leaks because of current kmemleak limitations with the __percpu pointer not pointing directly to the actual chunks. Reported-by: Huajun Li <huajun.li.lee@gmail.com> Acked-by: Christoph Lameter <cl@gentwo.org> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'mm/percpu.c')
-rw-r--r--mm/percpu.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/mm/percpu.c b/mm/percpu.c
index 3bb810a72006..86c5bdbdc370 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -67,6 +67,7 @@
67#include <linux/spinlock.h> 67#include <linux/spinlock.h>
68#include <linux/vmalloc.h> 68#include <linux/vmalloc.h>
69#include <linux/workqueue.h> 69#include <linux/workqueue.h>
70#include <linux/kmemleak.h>
70 71
71#include <asm/cacheflush.h> 72#include <asm/cacheflush.h>
72#include <asm/sections.h> 73#include <asm/sections.h>
@@ -710,6 +711,7 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
710 const char *err; 711 const char *err;
711 int slot, off, new_alloc; 712 int slot, off, new_alloc;
712 unsigned long flags; 713 unsigned long flags;
714 void __percpu *ptr;
713 715
714 if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) { 716 if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) {
715 WARN(true, "illegal size (%zu) or align (%zu) for " 717 WARN(true, "illegal size (%zu) or align (%zu) for "
@@ -802,7 +804,9 @@ area_found:
802 mutex_unlock(&pcpu_alloc_mutex); 804 mutex_unlock(&pcpu_alloc_mutex);
803 805
804 /* return address relative to base address */ 806 /* return address relative to base address */
805 return __addr_to_pcpu_ptr(chunk->base_addr + off); 807 ptr = __addr_to_pcpu_ptr(chunk->base_addr + off);
808 kmemleak_alloc_percpu(ptr, size);
809 return ptr;
806 810
807fail_unlock: 811fail_unlock:
808 spin_unlock_irqrestore(&pcpu_lock, flags); 812 spin_unlock_irqrestore(&pcpu_lock, flags);
@@ -916,6 +920,8 @@ void free_percpu(void __percpu *ptr)
916 if (!ptr) 920 if (!ptr)
917 return; 921 return;
918 922
923 kmemleak_free_percpu(ptr);
924
919 addr = __pcpu_ptr_to_addr(ptr); 925 addr = __pcpu_ptr_to_addr(ptr);
920 926
921 spin_lock_irqsave(&pcpu_lock, flags); 927 spin_lock_irqsave(&pcpu_lock, flags);
@@ -1637,6 +1643,8 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,
1637 rc = -ENOMEM; 1643 rc = -ENOMEM;
1638 goto out_free_areas; 1644 goto out_free_areas;
1639 } 1645 }
1646 /* kmemleak tracks the percpu allocations separately */
1647 kmemleak_free(ptr);
1640 areas[group] = ptr; 1648 areas[group] = ptr;
1641 1649
1642 base = min(ptr, base); 1650 base = min(ptr, base);
@@ -1751,6 +1759,8 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
1751 "for cpu%u\n", psize_str, cpu); 1759 "for cpu%u\n", psize_str, cpu);
1752 goto enomem; 1760 goto enomem;
1753 } 1761 }
1762 /* kmemleak tracks the percpu allocations separately */
1763 kmemleak_free(ptr);
1754 pages[j++] = virt_to_page(ptr); 1764 pages[j++] = virt_to_page(ptr);
1755 } 1765 }
1756 1766