aboutsummaryrefslogtreecommitdiffstats
path: root/mm/kmemleak.c
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2009-07-07 05:33:00 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2009-07-08 09:25:14 -0400
commit53238a60dd4a679f6fe5613a7ed46899587205cf (patch)
treed2224ecfb18f7e9c6cc6fb2a48d81a87e5d5b62a /mm/kmemleak.c
parente4f7c0b44a8ac8935f223195af9ea637d0c08091 (diff)
kmemleak: Allow partial freeing of memory blocks
Functions like free_bootmem() are allowed to free only part of a memory block. This patch adds support for this via the kmemleak_free_part() callback which removes the original object and creates one or two additional objects as a result of the memory block split. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Ingo Molnar <mingo@elte.hu> Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Diffstat (limited to 'mm/kmemleak.c')
-rw-r--r--mm/kmemleak.c95
1 files changed, 81 insertions, 14 deletions
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 466d39007264..5aabd41ffb8f 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -210,6 +210,7 @@ static DEFINE_MUTEX(scan_mutex);
210enum { 210enum {
211 KMEMLEAK_ALLOC, 211 KMEMLEAK_ALLOC,
212 KMEMLEAK_FREE, 212 KMEMLEAK_FREE,
213 KMEMLEAK_FREE_PART,
213 KMEMLEAK_NOT_LEAK, 214 KMEMLEAK_NOT_LEAK,
214 KMEMLEAK_IGNORE, 215 KMEMLEAK_IGNORE,
215 KMEMLEAK_SCAN_AREA, 216 KMEMLEAK_SCAN_AREA,
@@ -523,27 +524,17 @@ out:
523 * Remove the metadata (struct kmemleak_object) for a memory block from the 524 * Remove the metadata (struct kmemleak_object) for a memory block from the
524 * object_list and object_tree_root and decrement its use_count. 525 * object_list and object_tree_root and decrement its use_count.
525 */ 526 */
526static void delete_object(unsigned long ptr) 527static void __delete_object(struct kmemleak_object *object)
527{ 528{
528 unsigned long flags; 529 unsigned long flags;
529 struct kmemleak_object *object;
530 530
531 write_lock_irqsave(&kmemleak_lock, flags); 531 write_lock_irqsave(&kmemleak_lock, flags);
532 object = lookup_object(ptr, 0);
533 if (!object) {
534#ifdef DEBUG
535 kmemleak_warn("Freeing unknown object at 0x%08lx\n",
536 ptr);
537#endif
538 write_unlock_irqrestore(&kmemleak_lock, flags);
539 return;
540 }
541 prio_tree_remove(&object_tree_root, &object->tree_node); 532 prio_tree_remove(&object_tree_root, &object->tree_node);
542 list_del_rcu(&object->object_list); 533 list_del_rcu(&object->object_list);
543 write_unlock_irqrestore(&kmemleak_lock, flags); 534 write_unlock_irqrestore(&kmemleak_lock, flags);
544 535
545 WARN_ON(!(object->flags & OBJECT_ALLOCATED)); 536 WARN_ON(!(object->flags & OBJECT_ALLOCATED));
546 WARN_ON(atomic_read(&object->use_count) < 1); 537 WARN_ON(atomic_read(&object->use_count) < 2);
547 538
548 /* 539 /*
549 * Locking here also ensures that the corresponding memory block 540 * Locking here also ensures that the corresponding memory block
@@ -556,6 +547,64 @@ static void delete_object(unsigned long ptr)
556} 547}
557 548
558/* 549/*
550 * Look up the metadata (struct kmemleak_object) corresponding to ptr and
551 * delete it.
552 */
553static void delete_object_full(unsigned long ptr)
554{
555 struct kmemleak_object *object;
556
557 object = find_and_get_object(ptr, 0);
558 if (!object) {
559#ifdef DEBUG
560 kmemleak_warn("Freeing unknown object at 0x%08lx\n",
561 ptr);
562#endif
563 return;
564 }
565 __delete_object(object);
566 put_object(object);
567}
568
569/*
570 * Look up the metadata (struct kmemleak_object) corresponding to ptr and
571 * delete it. If the memory block is partially freed, the function may create
572 * additional metadata for the remaining parts of the block.
573 */
574static void delete_object_part(unsigned long ptr, size_t size)
575{
576 struct kmemleak_object *object;
577 unsigned long start, end;
578
579 object = find_and_get_object(ptr, 1);
580 if (!object) {
581#ifdef DEBUG
582 kmemleak_warn("Partially freeing unknown object at 0x%08lx "
583 "(size %zu)\n", ptr, size);
584#endif
585 return;
586 }
587 __delete_object(object);
588
589 /*
590 * Create one or two objects that may result from the memory block
591 * split. Note that partial freeing is only done by free_bootmem() and
592 * this happens before kmemleak_init() is called. The path below is
593 * only executed during early log recording in kmemleak_init(), so
594 * GFP_KERNEL is enough.
595 */
596 start = object->pointer;
597 end = object->pointer + object->size;
598 if (ptr > start)
599 create_object(start, ptr - start, object->min_count,
600 GFP_KERNEL);
601 if (ptr + size < end)
602 create_object(ptr + size, end - ptr - size, object->min_count,
603 GFP_KERNEL);
604
605 put_object(object);
606}
607/*
559 * Make a object permanently as gray-colored so that it can no longer be 608 * Make a object permanently as gray-colored so that it can no longer be
560 * reported as a leak. This is used in general to mark a false positive. 609 * reported as a leak. This is used in general to mark a false positive.
561 */ 610 */
@@ -719,13 +768,28 @@ void kmemleak_free(const void *ptr)
719 pr_debug("%s(0x%p)\n", __func__, ptr); 768 pr_debug("%s(0x%p)\n", __func__, ptr);
720 769
721 if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr)) 770 if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
722 delete_object((unsigned long)ptr); 771 delete_object_full((unsigned long)ptr);
723 else if (atomic_read(&kmemleak_early_log)) 772 else if (atomic_read(&kmemleak_early_log))
724 log_early(KMEMLEAK_FREE, ptr, 0, 0, 0, 0); 773 log_early(KMEMLEAK_FREE, ptr, 0, 0, 0, 0);
725} 774}
726EXPORT_SYMBOL_GPL(kmemleak_free); 775EXPORT_SYMBOL_GPL(kmemleak_free);
727 776
728/* 777/*
778 * Partial memory freeing function callback. This function is usually called
779 * from bootmem allocator when (part of) a memory block is freed.
780 */
781void kmemleak_free_part(const void *ptr, size_t size)
782{
783 pr_debug("%s(0x%p)\n", __func__, ptr);
784
785 if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
786 delete_object_part((unsigned long)ptr, size);
787 else if (atomic_read(&kmemleak_early_log))
788 log_early(KMEMLEAK_FREE_PART, ptr, size, 0, 0, 0);
789}
790EXPORT_SYMBOL_GPL(kmemleak_free_part);
791
792/*
729 * Mark an already allocated memory block as a false positive. This will cause 793 * Mark an already allocated memory block as a false positive. This will cause
730 * the block to no longer be reported as leak and always be scanned. 794 * the block to no longer be reported as leak and always be scanned.
731 */ 795 */
@@ -1318,7 +1382,7 @@ static int kmemleak_cleanup_thread(void *arg)
1318 1382
1319 rcu_read_lock(); 1383 rcu_read_lock();
1320 list_for_each_entry_rcu(object, &object_list, object_list) 1384 list_for_each_entry_rcu(object, &object_list, object_list)
1321 delete_object(object->pointer); 1385 delete_object_full(object->pointer);
1322 rcu_read_unlock(); 1386 rcu_read_unlock();
1323 mutex_unlock(&scan_mutex); 1387 mutex_unlock(&scan_mutex);
1324 1388
@@ -1413,6 +1477,9 @@ void __init kmemleak_init(void)
1413 case KMEMLEAK_FREE: 1477 case KMEMLEAK_FREE:
1414 kmemleak_free(log->ptr); 1478 kmemleak_free(log->ptr);
1415 break; 1479 break;
1480 case KMEMLEAK_FREE_PART:
1481 kmemleak_free_part(log->ptr, log->size);
1482 break;
1416 case KMEMLEAK_NOT_LEAK: 1483 case KMEMLEAK_NOT_LEAK:
1417 kmemleak_not_leak(log->ptr); 1484 kmemleak_not_leak(log->ptr);
1418 break; 1485 break;