diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2009-09-07 05:14:42 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2009-09-08 11:31:15 -0400 |
commit | 179a8100e12d0053f4b368ea3358dd9a0fc6cb94 (patch) | |
tree | 2513119dabe3d4c0ccb2f10f5c2b581461f7c335 /mm/kmemleak.c | |
parent | 43ed5d6ee0f9bfd655d6bc3cb2d964b80c4422c0 (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/kmemleak.c')
-rw-r--r-- | mm/kmemleak.c | 22 |
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 | */ |
1502 | static int kmemleak_cleanup_thread(void *arg) | 1503 | static 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 | /* | 1517 | static DECLARE_WORK(cleanup_work, kmemleak_do_cleanup); |
1519 | * Start the clean-up thread. | ||
1520 | */ | ||
1521 | static 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 | ||