diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2011-09-26 12:12:53 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2011-12-02 11:12:42 -0500 |
commit | f528f0b8e53d73b18be71e96693cfab9322f33c7 (patch) | |
tree | 5a25d6ac1c2f18561e554074aa7c06bf3d899183 /mm/percpu.c | |
parent | 74341703edca6bc68a165a18453071b097828407 (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.c | 12 |
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 | ||
807 | fail_unlock: | 811 | fail_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 | ||