aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2009-09-07 05:14:42 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2009-09-08 11:31:15 -0400
commit179a8100e12d0053f4b368ea3358dd9a0fc6cb94 (patch)
tree2513119dabe3d4c0ccb2f10f5c2b581461f7c335 /mm
parent43ed5d6ee0f9bfd655d6bc3cb2d964b80c4422c0 (diff)
kmemleak: Do no create the clean-up thread during kmemleak_disable()
The kmemleak_disable() function could be called from various contexts including IRQ. It creates a clean-up thread but the kthread_create() function has restrictions on which contexts it can be called from, mainly because of the kthread_create_lock. The patch changes the kmemleak clean-up thread to a workqueue. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Reported-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'mm')
-rw-r--r--mm/kmemleak.c22
1 files changed, 5 insertions, 17 deletions
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 74d4089d7588..1563de456441 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -92,6 +92,7 @@
92#include <linux/string.h> 92#include <linux/string.h>
93#include <linux/nodemask.h> 93#include <linux/nodemask.h>
94#include <linux/mm.h> 94#include <linux/mm.h>
95#include <linux/workqueue.h>
95 96
96#include <asm/sections.h> 97#include <asm/sections.h>
97#include <asm/processor.h> 98#include <asm/processor.h>
@@ -1499,7 +1500,7 @@ static const struct file_operations kmemleak_fops = {
1499 * Perform the freeing of the kmemleak internal objects after waiting for any 1500 * Perform the freeing of the kmemleak internal objects after waiting for any
1500 * current memory scan to complete. 1501 * current memory scan to complete.
1501 */ 1502 */
1502static int kmemleak_cleanup_thread(void *arg) 1503static void kmemleak_do_cleanup(struct work_struct *work)
1503{ 1504{
1504 struct kmemleak_object *object; 1505 struct kmemleak_object *object;
1505 1506
@@ -1511,22 +1512,9 @@ static int kmemleak_cleanup_thread(void *arg)
1511 delete_object_full(object->pointer); 1512 delete_object_full(object->pointer);
1512 rcu_read_unlock(); 1513 rcu_read_unlock();
1513 mutex_unlock(&scan_mutex); 1514 mutex_unlock(&scan_mutex);
1514
1515 return 0;
1516} 1515}
1517 1516
1518/* 1517static DECLARE_WORK(cleanup_work, kmemleak_do_cleanup);
1519 * Start the clean-up thread.
1520 */
1521static void kmemleak_cleanup(void)
1522{
1523 struct task_struct *cleanup_thread;
1524
1525 cleanup_thread = kthread_run(kmemleak_cleanup_thread, NULL,
1526 "kmemleak-clean");
1527 if (IS_ERR(cleanup_thread))
1528 pr_warning("Failed to create the clean-up thread\n");
1529}
1530 1518
1531/* 1519/*
1532 * Disable kmemleak. No memory allocation/freeing will be traced once this 1520 * Disable kmemleak. No memory allocation/freeing will be traced once this
@@ -1544,7 +1532,7 @@ static void kmemleak_disable(void)
1544 1532
1545 /* check whether it is too early for a kernel thread */ 1533 /* check whether it is too early for a kernel thread */
1546 if (atomic_read(&kmemleak_initialized)) 1534 if (atomic_read(&kmemleak_initialized))
1547 kmemleak_cleanup(); 1535 schedule_work(&cleanup_work);
1548 1536
1549 pr_info("Kernel memory leak detector disabled\n"); 1537 pr_info("Kernel memory leak detector disabled\n");
1550} 1538}
@@ -1640,7 +1628,7 @@ static int __init kmemleak_late_init(void)
1640 * after setting kmemleak_initialized and we may end up with 1628 * after setting kmemleak_initialized and we may end up with
1641 * two clean-up threads but serialized by scan_mutex. 1629 * two clean-up threads but serialized by scan_mutex.
1642 */ 1630 */
1643 kmemleak_cleanup(); 1631 schedule_work(&cleanup_work);
1644 return -ENOMEM; 1632 return -ENOMEM;
1645 } 1633 }
1646 1634