public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] failslab - failmalloc for slab allocator
@ 2006-08-13 10:22 Akinobu Mita
  2006-08-13 10:28 ` Akinobu Mita
  2006-08-13 19:17 ` Andrew Morton
  0 siblings, 2 replies; 4+ messages in thread
From: Akinobu Mita @ 2006-08-13 10:22 UTC (permalink / raw)
  To: linux-kernel; +Cc: okuji

This patch is not intended for inclusion. But I could find
several interesting crashes.

The idea behind failslab is to demonstrate what really happens if
slab allocation fails. The idea of failslab is completely taken
from failmalloc (http://www.nongnu.org/failmalloc/).

boot option:

failslab=<probability>,<interval>,<times>,<space>

<probability>
	specifies how often it should fail in percent.
<interval>
	specifies the interval of failures.
<times>
	specifies how many times failures may happen at most.
<space>
	specifies the size of free space where memory can be allocated
	safely in bytes.

examples:

failslab=100,10,-1,0

slab allocation (kmalloc, kmem_cache_alloc,..) fails once per 10 times.

Signed-off-by: Akinobu Mita <mita@miraclelinux.com>

 include/linux/failmalloc.h |   39 ++++++++++++++++++++++++++++++++
 lib/Kconfig.debug          |    6 +++++
 mm/Makefile                |    1 
 mm/failmalloc.c            |   54 +++++++++++++++++++++++++++++++++++++++++++++
 mm/slab.c                  |   19 +++++++++++++++
 5 files changed, 119 insertions(+)

Index: work-failmalloc/mm/failmalloc.c
===================================================================
--- /dev/null
+++ work-failmalloc/mm/failmalloc.c
@@ -0,0 +1,54 @@
+/* failmalloc - force to fail in allocating memory sometimes */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/failmalloc.h>
+
+int setup_failmalloc(struct failmalloc_data *failmalloc, char *str)
+{
+	struct failmalloc_data tmp;
+
+	/* "<probability>,<interval>,<times>,<space>" */
+	if (sscanf(str, "%d,%lu,%ld,%u", &tmp.failure_probability,
+		   &tmp.failure_interval, &tmp.max_failures,
+		   &tmp.max_space) < 4)
+		return 0;
+
+	*failmalloc = tmp;
+	return 1;
+}
+
+int should_fail(struct failmalloc_data *failmalloc, size_t size)
+{
+	if (failmalloc->max_failures == 0)
+		return 0;
+
+	if (failmalloc->max_space) {
+		if (failmalloc->current_space < failmalloc->max_space - size) {
+			failmalloc->current_space += size;
+			return 0;
+		}
+	}
+
+	if (failmalloc->failure_interval > 1) {
+		failmalloc->count++;
+		if (failmalloc->count < failmalloc->failure_interval)
+			return 0;
+
+		failmalloc->count = 0;
+	}
+
+	if (failmalloc->failure_probability == 100 ||
+	    INT_MAX / 100 * failmalloc->failure_probability > get_random_int())
+		goto fail;
+
+	return 0;
+
+fail:
+
+	if (failmalloc->max_failures > 0)
+		failmalloc->max_failures--;
+
+	return 1;
+}
Index: work-failmalloc/lib/Kconfig.debug
===================================================================
--- work-failmalloc.orig/lib/Kconfig.debug
+++ work-failmalloc/lib/Kconfig.debug
@@ -368,3 +368,9 @@ config RCU_TORTURE_TEST
 	  at boot time (you probably don't).
 	  Say M if you want the RCU torture tests to build as a module.
 	  Say N if you are unsure.
+
+config FAILMALLOC
+	bool "failmalloc"
+	depends on DEBUG_KERNEL
+	help
+	  This option enables failmalloc.
Index: work-failmalloc/mm/Makefile
===================================================================
--- work-failmalloc.orig/mm/Makefile
+++ work-failmalloc/mm/Makefile
@@ -23,4 +23,5 @@ obj-$(CONFIG_SLAB) += slab.o
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
 obj-$(CONFIG_FS_XIP) += filemap_xip.o
 obj-$(CONFIG_MIGRATION) += migrate.o
+obj-$(CONFIG_FAILMALLOC) += failmalloc.o
 
Index: work-failmalloc/include/linux/failmalloc.h
===================================================================
--- /dev/null
+++ work-failmalloc/include/linux/failmalloc.h
@@ -0,0 +1,39 @@
+#ifndef _LINUX_FAILMALLOC_H
+#define	_LINUX_FAILMALLOC_H
+
+#ifdef CONFIG_FAILMALLOC
+
+struct failmalloc_data {
+
+	/* how often it should fail, in percent. */
+	int failure_probability;
+
+	/* the interval of failures. */
+	unsigned long failure_interval;
+
+	/*
+	 * how many times failures may happen at most.
+	 * negative value means unlimited.
+	 */
+	long max_failures;
+
+	/*
+	 * the size of free space where memory can be allocated safely in bytes.
+	 * A value of '0' means infinity.
+	 */
+	size_t max_space;
+
+	unsigned long count;
+	size_t current_space;
+};
+
+int should_fail(struct failmalloc_data *failmalloc, size_t size);
+int setup_failmalloc(struct failmalloc_data *data, char *str);
+
+#else
+
+#define should_fail(failmalloc, size)	(0)
+
+#endif /* CONFIG_FAILMALLOC */
+
+#endif /* _LINUX_FAILMALLOC_H */
Index: work-failmalloc/mm/slab.c
===================================================================
--- work-failmalloc.orig/mm/slab.c
+++ work-failmalloc/mm/slab.c
@@ -108,6 +108,7 @@
 #include	<linux/mempolicy.h>
 #include	<linux/mutex.h>
 #include	<linux/rtmutex.h>
+#include	<linux/failmalloc.h>
 
 #include	<asm/uaccess.h>
 #include	<asm/cacheflush.h>
@@ -2963,11 +2964,29 @@ static void *cache_alloc_debugcheck_afte
 #define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
 #endif
 
+#ifdef CONFIG_FAILMALLOC
+
+struct failmalloc_data failslab;
+
+static int __init setup_failslab(char *str)
+{
+	return setup_failmalloc(&failslab, str);
+}
+
+__setup("failslab=", setup_failslab);
+
+#endif
+
 static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
 	void *objp;
 	struct array_cache *ac;
 
+	/* This is not SMP safe, but that's OK. */
+	if (!(flags & __GFP_NOFAIL) && cachep != &cache_cache &&
+			should_fail(&failslab, obj_size(cachep)))
+		return NULL;
+
 #ifdef CONFIG_NUMA
 	if (unlikely(current->flags & (PF_SPREAD_SLAB | PF_MEMPOLICY))) {
 		objp = alternate_node_alloc(cachep, flags);

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2006-08-14 10:18 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-13 10:22 [PATCH] failslab - failmalloc for slab allocator Akinobu Mita
2006-08-13 10:28 ` Akinobu Mita
2006-08-13 19:17 ` Andrew Morton
2006-08-14 10:18   ` Akinobu Mita

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox