aboutsummaryrefslogtreecommitdiffstats
path: root/mm/kmemleak.c
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2011-09-29 06:50:07 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2011-12-02 11:12:42 -0500
commit74341703edca6bc68a165a18453071b097828407 (patch)
tree8cb5c8423849acfb4c89a192548e95dfce49efd7 /mm/kmemleak.c
parentb66930052abf2e41b8a978ae265303917cbe6fa0 (diff)
kmemleak: Report previously found leaks even after an error
If an error fatal to kmemleak (like memory allocation failure) happens, kmemleak disables itself but it also removes the access to any previously found memory leaks. This patch allows read-only access to the kmemleak debugfs interface but disables any other action. Reported-by: Nick Bowler <nbowler@elliptictech.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'mm/kmemleak.c')
-rw-r--r--mm/kmemleak.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index e8c905b70aa8..b4f4e6021c1b 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1473,9 +1473,6 @@ static const struct seq_operations kmemleak_seq_ops = {
1473 1473
1474static int kmemleak_open(struct inode *inode, struct file *file) 1474static int kmemleak_open(struct inode *inode, struct file *file)
1475{ 1475{
1476 if (!atomic_read(&kmemleak_enabled))
1477 return -EBUSY;
1478
1479 return seq_open(file, &kmemleak_seq_ops); 1476 return seq_open(file, &kmemleak_seq_ops);
1480} 1477}
1481 1478
@@ -1549,6 +1546,9 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
1549 int buf_size; 1546 int buf_size;
1550 int ret; 1547 int ret;
1551 1548
1549 if (!atomic_read(&kmemleak_enabled))
1550 return -EBUSY;
1551
1552 buf_size = min(size, (sizeof(buf) - 1)); 1552 buf_size = min(size, (sizeof(buf) - 1));
1553 if (strncpy_from_user(buf, user_buf, buf_size) < 0) 1553 if (strncpy_from_user(buf, user_buf, buf_size) < 0)
1554 return -EFAULT; 1554 return -EFAULT;
@@ -1608,20 +1608,24 @@ static const struct file_operations kmemleak_fops = {
1608}; 1608};
1609 1609
1610/* 1610/*
1611 * Perform the freeing of the kmemleak internal objects after waiting for any 1611 * Stop the memory scanning thread and free the kmemleak internal objects if
1612 * current memory scan to complete. 1612 * no previous scan thread (otherwise, kmemleak may still have some useful
1613 * information on memory leaks).
1613 */ 1614 */
1614static void kmemleak_do_cleanup(struct work_struct *work) 1615static void kmemleak_do_cleanup(struct work_struct *work)
1615{ 1616{
1616 struct kmemleak_object *object; 1617 struct kmemleak_object *object;
1618 bool cleanup = scan_thread == NULL;
1617 1619
1618 mutex_lock(&scan_mutex); 1620 mutex_lock(&scan_mutex);
1619 stop_scan_thread(); 1621 stop_scan_thread();
1620 1622
1621 rcu_read_lock(); 1623 if (cleanup) {
1622 list_for_each_entry_rcu(object, &object_list, object_list) 1624 rcu_read_lock();
1623 delete_object_full(object->pointer); 1625 list_for_each_entry_rcu(object, &object_list, object_list)
1624 rcu_read_unlock(); 1626 delete_object_full(object->pointer);
1627 rcu_read_unlock();
1628 }
1625 mutex_unlock(&scan_mutex); 1629 mutex_unlock(&scan_mutex);
1626} 1630}
1627 1631