[PATCH RFC] kmemleak vs. memory hotplug

From: Jason Baron
Date: Mon Mar 22 2010 - 15:52:24 EST


Hi,

I noticed in the Kconfig that kmemleak can not be set without
MEMORY_HOTPLUG being unset. I'd like to be able to enable both. Below,
is an rfc patch, completely untested, as a starting point. Hopefully,
ppl more knowledgeable in this area can comment.

thanks,

-Jason



diff --git a/include/linux/kmemleak.h b/include/linux/kmemleak.h
index 99d9a67..ad89f2d 100644
--- a/include/linux/kmemleak.h
+++ b/include/linux/kmemleak.h
@@ -54,6 +54,18 @@ static inline void kmemleak_erase(void **ptr)
*ptr = NULL;
}

+extern struct mutex kmemleak_hotplug;
+
+static inline void lock_system_kmemleak(void)
+{
+ mutex_lock(&kmemleak_hotplug);
+}
+
+static inline void unlock_system_kmemleak(void)
+{
+ mutex_unlock(&kmemleak_hotplug);
+}
+
#else

static inline void kmemleak_init(void)
@@ -93,6 +105,14 @@ static inline void kmemleak_no_scan(const void *ptr)
{
}

+static inline void lock_system_kmemleak(void)
+{
+}
+
+static inline void unlock_system_kmemleak(void)
+{
+}
+
#endif /* CONFIG_DEBUG_KMEMLEAK */

#endif /* __KMEMLEAK_H */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 4a50fc1..2e89153 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -365,14 +365,13 @@ config SLUB_STATS

config DEBUG_KMEMLEAK
bool "Kernel memory leak detector"
- depends on DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && \
+ depends on DEBUG_KERNEL && EXPERIMENTAL && \
(X86 || ARM || PPC || S390 || SUPERH)

select DEBUG_FS if SYSFS
select STACKTRACE if STACKTRACE_SUPPORT
select KALLSYMS
select CRC32
- depends on 0
help
Say Y here if you want to enable the memory leak
detector. The memory allocation/freeing is traced in a way
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 5b069e4..509a728 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -102,6 +102,9 @@
#include <linux/kmemcheck.h>
#include <linux/kmemleak.h>

+/* exlcludes memory hotplug */
+DEFINE_MUTEX(kmemleak_hotplug);
+
/*
* Kmemleak configuration and common defines.
*/
@@ -1178,6 +1181,7 @@ static void kmemleak_scan(void)
* Struct page scanning for each node. The code below is not yet safe
* with MEMORY_HOTPLUG.
*/
+ mutex_lock(&kmemleak_hotplug);
for_each_online_node(i) {
pg_data_t *pgdat = NODE_DATA(i);
unsigned long start_pfn = pgdat->node_start_pfn;
@@ -1196,6 +1200,7 @@ static void kmemleak_scan(void)
scan_block(page, page + 1, NULL, 1);
}
}
+ mutex_unlock(&kmemleak_hotplug);

/*
* Scanning the task stacks (may introduce false negatives).
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 78e34e6..01fc57d 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -34,6 +34,23 @@

#include "internal.h"

+/* exclude subsystems that hotplug might conflict with */
+static void lock_hotplug_exlucde(void)
+{
+ /* exclude hotplug */
+ lock_system_sleep();
+ /* exlucde kmemleak */
+ lock_system_kmemleak();
+}
+
+static void unlock_hotplug_exlucde(void)
+{
+ /* exclude hotplug */
+ unlock_system_sleep();
+ /* exlucde kmemleak */
+ unlock_system_kmemleak();
+}
+
/* add this memory to iomem resource */
static struct resource *register_memory_resource(u64 start, u64 size)
{
@@ -490,7 +507,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
struct resource *res;
int ret;

- lock_system_sleep();
+ lock_hotplug_exclude();

res = register_memory_resource(start, size);
ret = -EEXIST;
@@ -537,7 +554,7 @@ error:
release_memory_resource(res);

out:
- unlock_system_sleep();
+ unlock_hotplug_exclude();
return ret;
}
EXPORT_SYMBOL_GPL(add_memory);
@@ -777,7 +794,7 @@ static int offline_pages(unsigned long start_pfn,
if (!test_pages_in_a_zone(start_pfn, end_pfn))
return -EINVAL;

- lock_system_sleep();
+ lock_hotplug_exclude();

zone = page_zone(pfn_to_page(start_pfn));
node = zone_to_nid(zone);
@@ -868,7 +885,7 @@ repeat:
writeback_set_ratelimit();

memory_notify(MEM_OFFLINE, &arg);
- unlock_system_sleep();
+ unlock_hotplug_exclude();
return 0;

failed_removal:
@@ -879,7 +896,7 @@ failed_removal:
undo_isolate_page_range(start_pfn, end_pfn);

out:
- unlock_system_sleep();
+ unlock_hotplug_exclude();
return ret;
}


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/