diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2009-08-27 09:29:15 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2009-08-27 09:29:15 -0400 |
commit | 189d84ed54bbb05aac5b24d9d784d86c4d37f807 (patch) | |
tree | 6a856fddf93cd6688978d2d675623c96de4c46cd /mm | |
parent | af98603dad87e393d2fc57117fe8a2aa6d620a0c (diff) |
kmemleak: Dump object information on request
By writing dump=<addr> to the kmemleak file, kmemleak will look up an
object with that address and dump the information it has about it to
syslog. This is useful in debugging memory leaks.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/kmemleak.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 6debe0d80e64..c977f7a2f0e4 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c | |||
@@ -331,6 +331,7 @@ static void dump_object_info(struct kmemleak_object *object) | |||
331 | object->comm, object->pid, object->jiffies); | 331 | object->comm, object->pid, object->jiffies); |
332 | pr_notice(" min_count = %d\n", object->min_count); | 332 | pr_notice(" min_count = %d\n", object->min_count); |
333 | pr_notice(" count = %d\n", object->count); | 333 | pr_notice(" count = %d\n", object->count); |
334 | pr_notice(" flags = 0x%lx\n", object->flags); | ||
334 | pr_notice(" backtrace:\n"); | 335 | pr_notice(" backtrace:\n"); |
335 | print_stack_trace(&trace, 4); | 336 | print_stack_trace(&trace, 4); |
336 | } | 337 | } |
@@ -1307,6 +1308,27 @@ static int kmemleak_release(struct inode *inode, struct file *file) | |||
1307 | return seq_release(inode, file); | 1308 | return seq_release(inode, file); |
1308 | } | 1309 | } |
1309 | 1310 | ||
1311 | static int dump_str_object_info(const char *str) | ||
1312 | { | ||
1313 | unsigned long flags; | ||
1314 | struct kmemleak_object *object; | ||
1315 | unsigned long addr; | ||
1316 | |||
1317 | addr= simple_strtoul(str, NULL, 0); | ||
1318 | object = find_and_get_object(addr, 0); | ||
1319 | if (!object) { | ||
1320 | pr_info("Unknown object at 0x%08lx\n", addr); | ||
1321 | return -EINVAL; | ||
1322 | } | ||
1323 | |||
1324 | spin_lock_irqsave(&object->lock, flags); | ||
1325 | dump_object_info(object); | ||
1326 | spin_unlock_irqrestore(&object->lock, flags); | ||
1327 | |||
1328 | put_object(object); | ||
1329 | return 0; | ||
1330 | } | ||
1331 | |||
1310 | /* | 1332 | /* |
1311 | * File write operation to configure kmemleak at run-time. The following | 1333 | * File write operation to configure kmemleak at run-time. The following |
1312 | * commands can be written to the /sys/kernel/debug/kmemleak file: | 1334 | * commands can be written to the /sys/kernel/debug/kmemleak file: |
@@ -1318,6 +1340,7 @@ static int kmemleak_release(struct inode *inode, struct file *file) | |||
1318 | * scan=... - set the automatic memory scanning period in seconds (0 to | 1340 | * scan=... - set the automatic memory scanning period in seconds (0 to |
1319 | * disable it) | 1341 | * disable it) |
1320 | * scan - trigger a memory scan | 1342 | * scan - trigger a memory scan |
1343 | * dump=... - dump information about the object found at the given address | ||
1321 | */ | 1344 | */ |
1322 | static ssize_t kmemleak_write(struct file *file, const char __user *user_buf, | 1345 | static ssize_t kmemleak_write(struct file *file, const char __user *user_buf, |
1323 | size_t size, loff_t *ppos) | 1346 | size_t size, loff_t *ppos) |
@@ -1358,6 +1381,8 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf, | |||
1358 | } | 1381 | } |
1359 | } else if (strncmp(buf, "scan", 4) == 0) | 1382 | } else if (strncmp(buf, "scan", 4) == 0) |
1360 | kmemleak_scan(); | 1383 | kmemleak_scan(); |
1384 | else if (strncmp(buf, "dump=", 5) == 0) | ||
1385 | ret = dump_str_object_info(buf + 5); | ||
1361 | else | 1386 | else |
1362 | ret = -EINVAL; | 1387 | ret = -EINVAL; |
1363 | 1388 | ||