diff options
author | Kevin Hilman <khilman@linaro.org> | 2015-07-22 08:17:15 -0700 |
---|---|---|
committer | Kevin Hilman <khilman@linaro.org> | 2015-07-22 08:17:15 -0700 |
commit | 2447e09699cca5db52f86182f163f3a25d1089ab (patch) | |
tree | e16730dba489e5ea0f16737597525724daa5c770 /mm/kmemleak.c | |
parent | 5a277b6839c4ef6c6ccacff49b64f302598264bf (diff) | |
parent | c8bde72f9af412de57f0ceae218d648640118b0b (diff) |
Merge branch 'linux-4.1.y' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into linux-linaro-lsk-v4.1lsk-v4.1-15.07
* 'linux-4.1.y' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable: (126 commits)
Linux 4.1.3
Input: pixcir_i2c_ts - fix receive error
of/pci: Fix pci_address_to_pio() conversion of CPU address to I/O port
PCI: pciehp: Wait for hotplug command completion where necessary
PCI: Add pci_bus_addr_t
PCI: Propagate the "ignore hotplug" setting to parent
mtd: dc21285: use raw spinlock functions for nw_gpio_lock
mtd: fix: avoid race condition when accessing mtd->usecount
leds / PM: fix hibernation on arm when gpio-led used with CPU led trigger
video: mxsfb: Make sure axi clock is enabled when accessing registers
genirq: devres: Fix testing return value of request_any_context_irq()
IB/srp: Fix reconnection failure handling
IB/srp: Fix connection state tracking
IB/srp: Fix a connection setup race
IB/srp: Remove an extraneous scsi_host_put() from an error path
scsi_transport_srp: Fix a race condition
scsi_transport_srp: Introduce srp_wait_for_queuecommand()
spi: pl022: Specify 'num-cs' property as required in devicetree binding
spi: orion: Fix maximum baud rates for Armada 370/XP
spi: fix race freeing dummy_tx/rx before it is unmapped
...
Diffstat (limited to 'mm/kmemleak.c')
-rw-r--r-- | mm/kmemleak.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/mm/kmemleak.c b/mm/kmemleak.c index f0fe4f2c1fa7..3716cdb8ba42 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -195,6 +195,8 @@ static struct kmem_cache *scan_area_cache; /* set if tracing memory operations is enabled */ static int kmemleak_enabled; +/* same as above but only for the kmemleak_free() callback */ +static int kmemleak_free_enabled; /* set in the late_initcall if there were no errors */ static int kmemleak_initialized; /* enables or disables early logging of the memory operations */ @@ -907,12 +909,13 @@ EXPORT_SYMBOL_GPL(kmemleak_alloc); * kmemleak_alloc_percpu - register a newly allocated __percpu object * @ptr: __percpu pointer to beginning of the object * @size: size of the object + * @gfp: flags used for kmemleak internal memory allocations * * This function is called from the kernel percpu allocator when a new object - * (memory block) is allocated (alloc_percpu). It assumes GFP_KERNEL - * allocation. + * (memory block) is allocated (alloc_percpu). */ -void __ref kmemleak_alloc_percpu(const void __percpu *ptr, size_t size) +void __ref kmemleak_alloc_percpu(const void __percpu *ptr, size_t size, + gfp_t gfp) { unsigned int cpu; @@ -925,7 +928,7 @@ void __ref kmemleak_alloc_percpu(const void __percpu *ptr, size_t size) if (kmemleak_enabled && ptr && !IS_ERR(ptr)) for_each_possible_cpu(cpu) create_object((unsigned long)per_cpu_ptr(ptr, cpu), - size, 0, GFP_KERNEL); + size, 0, gfp); else if (kmemleak_early_log) log_early(KMEMLEAK_ALLOC_PERCPU, ptr, size, 0); } @@ -942,7 +945,7 @@ void __ref kmemleak_free(const void *ptr) { pr_debug("%s(0x%p)\n", __func__, ptr); - if (kmemleak_enabled && ptr && !IS_ERR(ptr)) + if (kmemleak_free_enabled && ptr && !IS_ERR(ptr)) delete_object_full((unsigned long)ptr); else if (kmemleak_early_log) log_early(KMEMLEAK_FREE, ptr, 0, 0); @@ -982,7 +985,7 @@ void __ref kmemleak_free_percpu(const void __percpu *ptr) pr_debug("%s(0x%p)\n", __func__, ptr); - if (kmemleak_enabled && ptr && !IS_ERR(ptr)) + if (kmemleak_free_enabled && ptr && !IS_ERR(ptr)) for_each_possible_cpu(cpu) delete_object_full((unsigned long)per_cpu_ptr(ptr, cpu)); @@ -1750,6 +1753,13 @@ static void kmemleak_do_cleanup(struct work_struct *work) mutex_lock(&scan_mutex); stop_scan_thread(); + /* + * Once the scan thread has stopped, it is safe to no longer track + * object freeing. Ordering of the scan thread stopping and the memory + * accesses below is guaranteed by the kthread_stop() function. + */ + kmemleak_free_enabled = 0; + if (!kmemleak_found_leaks) __kmemleak_do_cleanup(); else @@ -1776,6 +1786,8 @@ static void kmemleak_disable(void) /* check whether it is too early for a kernel thread */ if (kmemleak_initialized) schedule_work(&cleanup_work); + else + kmemleak_free_enabled = 0; pr_info("Kernel memory leak detector disabled\n"); } @@ -1840,8 +1852,10 @@ void __init kmemleak_init(void) if (kmemleak_error) { local_irq_restore(flags); return; - } else + } else { kmemleak_enabled = 1; + kmemleak_free_enabled = 1; + } local_irq_restore(flags); /* |