kmemleak: Add the vmalloc memory allocation/freeing hooks
authorCatalin Marinas <catalin.marinas@arm.com>
Thu, 11 Jun 2009 12:23:19 +0000 (13:23 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Thu, 11 Jun 2009 16:03:30 +0000 (17:03 +0100)
This patch adds the callbacks to kmemleak_(alloc|free) functions from
vmalloc/vfree.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
mm/vmalloc.c

index 083716ea38c9f7ba636cababe6859cd8e3c14106..b7db93572797e1477c1648c454a909b29766e3ce 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/rcupdate.h>
 #include <linux/bootmem.h>
 #include <linux/pfn.h>
+#include <linux/kmemleak.h>
 
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
@@ -1327,6 +1328,9 @@ static void __vunmap(const void *addr, int deallocate_pages)
 void vfree(const void *addr)
 {
        BUG_ON(in_interrupt());
+
+       kmemleak_free(addr);
+
        __vunmap(addr, 1);
 }
 EXPORT_SYMBOL(vfree);
@@ -1439,8 +1443,17 @@ fail:
 
 void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
 {
-       return __vmalloc_area_node(area, gfp_mask, prot, -1,
-                                       __builtin_return_address(0));
+       void *addr = __vmalloc_area_node(area, gfp_mask, prot, -1,
+                                        __builtin_return_address(0));
+
+       /*
+        * A ref_count = 3 is needed because the vm_struct and vmap_area
+        * structures allocated in the __get_vm_area_node() function contain
+        * references to the virtual address of the vmalloc'ed block.
+        */
+       kmemleak_alloc(addr, area->size - PAGE_SIZE, 3, gfp_mask);
+
+       return addr;
 }
 
 /**
@@ -1459,6 +1472,8 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
                                                int node, void *caller)
 {
        struct vm_struct *area;
+       void *addr;
+       unsigned long real_size = size;
 
        size = PAGE_ALIGN(size);
        if (!size || (size >> PAGE_SHIFT) > num_physpages)
@@ -1470,7 +1485,16 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
        if (!area)
                return NULL;
 
-       return __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+       addr = __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+
+       /*
+        * A ref_count = 3 is needed because the vm_struct and vmap_area
+        * structures allocated in the __get_vm_area_node() function contain
+        * references to the virtual address of the vmalloc'ed block.
+        */
+       kmemleak_alloc(addr, real_size, 3, gfp_mask);
+
+       return addr;
 }
 
 void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)