aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/kmemleak.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 7cfb7d014a20..466d39007264 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -106,6 +106,7 @@
106#define MSECS_MIN_AGE 5000 /* minimum object age for reporting */ 106#define MSECS_MIN_AGE 5000 /* minimum object age for reporting */
107#define SECS_FIRST_SCAN 60 /* delay before the first scan */ 107#define SECS_FIRST_SCAN 60 /* delay before the first scan */
108#define SECS_SCAN_WAIT 600 /* subsequent auto scanning delay */ 108#define SECS_SCAN_WAIT 600 /* subsequent auto scanning delay */
109#define GRAY_LIST_PASSES 25 /* maximum number of gray list scans */
109 110
110#define BYTES_PER_POINTER sizeof(void *) 111#define BYTES_PER_POINTER sizeof(void *)
111 112
@@ -157,6 +158,8 @@ struct kmemleak_object {
157#define OBJECT_REPORTED (1 << 1) 158#define OBJECT_REPORTED (1 << 1)
158/* flag set to not scan the object */ 159/* flag set to not scan the object */
159#define OBJECT_NO_SCAN (1 << 2) 160#define OBJECT_NO_SCAN (1 << 2)
161/* flag set on newly allocated objects */
162#define OBJECT_NEW (1 << 3)
160 163
161/* the list of all allocated objects */ 164/* the list of all allocated objects */
162static LIST_HEAD(object_list); 165static LIST_HEAD(object_list);
@@ -270,6 +273,11 @@ static int color_gray(const struct kmemleak_object *object)
270 return object->min_count != -1 && object->count >= object->min_count; 273 return object->min_count != -1 && object->count >= object->min_count;
271} 274}
272 275
276static int color_black(const struct kmemleak_object *object)
277{
278 return object->min_count == -1;
279}
280
273/* 281/*
274 * Objects are considered unreferenced only if their color is white, they have 282 * Objects are considered unreferenced only if their color is white, they have
275 * not be deleted and have a minimum age to avoid false positives caused by 283 * not be deleted and have a minimum age to avoid false positives caused by
@@ -447,7 +455,7 @@ static void create_object(unsigned long ptr, size_t size, int min_count,
447 INIT_HLIST_HEAD(&object->area_list); 455 INIT_HLIST_HEAD(&object->area_list);
448 spin_lock_init(&object->lock); 456 spin_lock_init(&object->lock);
449 atomic_set(&object->use_count, 1); 457 atomic_set(&object->use_count, 1);
450 object->flags = OBJECT_ALLOCATED; 458 object->flags = OBJECT_ALLOCATED | OBJECT_NEW;
451 object->pointer = ptr; 459 object->pointer = ptr;
452 object->size = size; 460 object->size = size;
453 object->min_count = min_count; 461 object->min_count = min_count;
@@ -901,6 +909,7 @@ static void kmemleak_scan(void)
901 struct task_struct *task; 909 struct task_struct *task;
902 int i; 910 int i;
903 int new_leaks = 0; 911 int new_leaks = 0;
912 int gray_list_pass = 0;
904 913
905 jiffies_last_scan = jiffies; 914 jiffies_last_scan = jiffies;
906 915
@@ -921,6 +930,7 @@ static void kmemleak_scan(void)
921#endif 930#endif
922 /* reset the reference count (whiten the object) */ 931 /* reset the reference count (whiten the object) */
923 object->count = 0; 932 object->count = 0;
933 object->flags &= ~OBJECT_NEW;
924 if (color_gray(object) && get_object(object)) 934 if (color_gray(object) && get_object(object))
925 list_add_tail(&object->gray_list, &gray_list); 935 list_add_tail(&object->gray_list, &gray_list);
926 936
@@ -983,6 +993,7 @@ static void kmemleak_scan(void)
983 * kmemleak objects cannot be freed from outside the loop because their 993 * kmemleak objects cannot be freed from outside the loop because their
984 * use_count was increased. 994 * use_count was increased.
985 */ 995 */
996repeat:
986 object = list_entry(gray_list.next, typeof(*object), gray_list); 997 object = list_entry(gray_list.next, typeof(*object), gray_list);
987 while (&object->gray_list != &gray_list) { 998 while (&object->gray_list != &gray_list) {
988 cond_resched(); 999 cond_resched();
@@ -1000,12 +1011,38 @@ static void kmemleak_scan(void)
1000 1011
1001 object = tmp; 1012 object = tmp;
1002 } 1013 }
1014
1015 if (scan_should_stop() || ++gray_list_pass >= GRAY_LIST_PASSES)
1016 goto scan_end;
1017
1018 /*
1019 * Check for new objects allocated during this scanning and add them
1020 * to the gray list.
1021 */
1022 rcu_read_lock();
1023 list_for_each_entry_rcu(object, &object_list, object_list) {
1024 spin_lock_irqsave(&object->lock, flags);
1025 if ((object->flags & OBJECT_NEW) && !color_black(object) &&
1026 get_object(object)) {
1027 object->flags &= ~OBJECT_NEW;
1028 list_add_tail(&object->gray_list, &gray_list);
1029 }
1030 spin_unlock_irqrestore(&object->lock, flags);
1031 }
1032 rcu_read_unlock();
1033
1034 if (!list_empty(&gray_list))
1035 goto repeat;
1036
1037scan_end:
1003 WARN_ON(!list_empty(&gray_list)); 1038 WARN_ON(!list_empty(&gray_list));
1004 1039
1005 /* 1040 /*
1006 * If scanning was stopped do not report any new unreferenced objects. 1041 * If scanning was stopped or new objects were being allocated at a
1042 * higher rate than gray list scanning, do not report any new
1043 * unreferenced objects.
1007 */ 1044 */
1008 if (scan_should_stop()) 1045 if (scan_should_stop() || gray_list_pass >= GRAY_LIST_PASSES)
1009 return; 1046 return;
1010 1047
1011 /* 1048 /*