From: Nick Piggin <npiggin@suse.de>
To: Linux Memory Management <linux-mm@kvack.org>
Cc: Nick Piggin <npiggin@suse.de>, Andrew Morton <akpm@linux-foundation.org>
Subject: [patch 9/9] mm: lockless test threads
Date: Thu, 12 Apr 2007 14:46:20 +0200 (CEST) [thread overview]
Message-ID: <20070412103330.5564.31067.sendpatchset@linux.site> (raw)
In-Reply-To: <20070412103151.5564.16127.sendpatchset@linux.site>
Introduce a basic lockless pagecache test harness. I don't know what value
this has, because it hasn't caught a bug yet, but it might help with testing.
Signed-off-by: Nick Piggin <npiggin@suse.de>
lib/Kconfig.debug | 12 +++
mm/Makefile | 1
mm/lpctest.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 207 insertions(+)
Index: linux-2.6/lib/Kconfig.debug
===================================================================
--- linux-2.6.orig/lib/Kconfig.debug
+++ linux-2.6/lib/Kconfig.debug
@@ -379,6 +379,18 @@ config FORCED_INLINING
become the default in the future, until then this option is there to
test gcc for this.
+config LPC_TEST
+ tristate "Background tests for lockless pagecache"
+ depends on DEBUG_KERNEL
+ default n
+ help
+ This option provides a kernel module that runs some background
+ threads that exercise lockless pagecache races more than usual.
+
+ Say Y here if you want LPC test threads start automatically at
+ boot. Say M to be able to start them by inserting the module.
+ Say N if you are unsure.
+
config RCU_TORTURE_TEST
tristate "torture tests for RCU"
depends on DEBUG_KERNEL
Index: linux-2.6/mm/Makefile
===================================================================
--- linux-2.6.orig/mm/Makefile
+++ linux-2.6/mm/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_MEMORY_HOTPLUG) += memory_h
obj-$(CONFIG_FS_XIP) += filemap_xip.o
obj-$(CONFIG_MIGRATION) += migrate.o
obj-$(CONFIG_SMP) += allocpercpu.o
+obj-$(CONFIG_LPC_TEST) += lpctest.o
Index: linux-2.6/mm/lpctest.c
===================================================================
--- /dev/null
+++ linux-2.6/mm/lpctest.c
@@ -0,0 +1,194 @@
+/*
+ * Lockless pagecache test thread
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Based on kernel/rcutorture.c, which is
+ * Copyright (C) IBM Corporation, 2005, 2006
+ *
+ * Copyright (C) Nick Piggin, SUSE Labs, Novell Inc, 2007
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/moduleparam.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/byteorder/swabb.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nick Piggin <npiggin@suse.de");
+
+static int random_threads = 2; /* # random pfn threads */
+static int verbose; /* Print more debug info. */
+
+module_param(random_threads, int, 0444);
+MODULE_PARM_DESC(nreaders, "Number of random pfn threads");
+module_param(verbose, bool, 0444);
+MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
+
+static struct task_struct **random_tasks;
+
+struct lpc_random_state {
+ unsigned long rrs_state;
+ long rrs_count;
+};
+
+#define LPC_RANDOM_MULT 39916801 /* prime */
+#define LPC_RANDOM_ADD 479001701 /* prime */
+#define LPC_RANDOM_REFRESH 10000
+
+#define DEFINE_LPC_RANDOM(name) struct lpc_random_state name = { 0, 0 }
+
+/*
+ * Crude but fast random-number generator. Uses a linear congruential
+ * generator, with occasional help from get_random_bytes().
+ */
+static unsigned long lpc_random(struct lpc_random_state *rrsp)
+{
+ long refresh;
+
+ if (--rrsp->rrs_count < 0) {
+ get_random_bytes(&refresh, sizeof(refresh));
+ rrsp->rrs_state += refresh;
+ rrsp->rrs_count = LPC_RANDOM_REFRESH;
+ }
+ rrsp->rrs_state = rrsp->rrs_state * LPC_RANDOM_MULT + LPC_RANDOM_ADD;
+ return swahw32(rrsp->rrs_state);
+}
+
+/*
+ * Definitions for lpc testing.
+ */
+static void lpc_page_delay(struct lpc_random_state *rrsp)
+{
+ long rnd;
+
+ /* We want there to be long-held pages, but not all the time. */
+
+ rnd = lpc_random(rrsp);
+ if (rnd % 200 == 0)
+ udelay(20);
+ else if (rnd % 300 == 0)
+ schedule_timeout(2);
+
+}
+
+/*
+ * LPC test random kthread. Repeatedly takes speculative references on
+ * random pages, then dropping them (possibly after a delay).
+ *
+ * This will not work properly if things start using synchronize_rcu to
+ * ensure a page will not be touched by speculative references, but so
+ * far we have avoided that.
+ */
+static int lpc_random_thread(void *arg)
+{
+ DEFINE_LPC_RANDOM(rand);
+
+ set_user_nice(current, 19);
+ current->flags |= PF_NOFREEZE;
+
+ do {
+ struct zone *zone;
+ for_each_zone(zone) {
+ unsigned long pfn;
+ unsigned int times;
+ struct page *page;
+
+ pfn = zone->zone_start_pfn +
+ lpc_random(&rand) % zone->spanned_pages;
+ if (!pfn_valid(pfn))
+ continue;
+
+ page = pfn_to_page(pfn);
+
+ for (times = 1+lpc_random(&rand)%100; times; times--) {
+ int ret;
+ rcu_read_lock();
+ ret = page_cache_get_speculative(page);
+ rcu_read_unlock();
+ if (ret) {
+ lpc_page_delay(&rand);
+ page_cache_release(page);
+ }
+ lpc_page_delay(&rand);
+ }
+ }
+ } while (!kthread_should_stop());
+
+ return 0;
+}
+
+static void lpc_test_cleanup(void)
+{
+ int i;
+
+ if (random_tasks != NULL) {
+ for (i = 0; i < random_threads; i++) {
+ if (random_tasks[i] != NULL) {
+ kthread_stop(random_tasks[i]);
+ random_tasks[i] = NULL;
+ }
+ }
+ kfree(random_tasks);
+ random_tasks = NULL;
+ }
+}
+
+static int lpc_test_init(void)
+{
+ int i;
+ int err = 0;
+
+ random_tasks = kzalloc(random_threads * sizeof(random_tasks[0]),
+ GFP_KERNEL);
+ if (random_tasks == NULL) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < random_threads; i++) {
+ random_tasks[i] = kthread_run(lpc_random_thread, NULL,
+ "lpc_random_thread");
+ if (IS_ERR(random_tasks[i])) {
+ err = PTR_ERR(random_tasks[i]);
+ random_tasks[i] = NULL;
+ goto out;
+ }
+ }
+
+out:
+ if (err)
+ lpc_test_cleanup();
+ return err;
+}
+
+module_init(lpc_test_init);
+module_exit(lpc_test_cleanup);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2007-04-12 12:46 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-12 12:44 [patch 0/9] lockless pagecache for 2.6.21-rc6 Nick Piggin
2007-04-12 12:44 ` [patch 1/9] mm: prep find_lock_page Nick Piggin
2007-04-12 12:45 ` [patch 2/9] radix-tree: use indirect bit Nick Piggin
2007-04-12 12:45 ` [patch 3/9] radix-tree: gang slot lookups Nick Piggin
2007-06-01 10:31 ` Peter Zijlstra
2007-04-12 12:45 ` [patch 4/9] mm: __add_to_swap_cache stuff Nick Piggin
2007-04-12 12:45 ` [patch 5/9] mm: lockless probe Nick Piggin
2007-04-12 12:45 ` [patch 6/9] mm: speculative get page Nick Piggin
2007-04-16 18:54 ` Hugh Dickins
2007-04-17 3:09 ` Nick Piggin
2007-04-12 12:45 ` [patch 7/9] mm: lockless pagecache lookups Nick Piggin
2007-04-12 12:46 ` [patch 8/9] mm: spinlock tree_lock Nick Piggin
2007-04-12 12:46 ` Nick Piggin [this message]
2007-04-13 16:54 ` [patch 9/9] mm: lockless test threads Hugh Dickins
2007-04-13 23:31 ` Nick Piggin
2007-04-12 12:46 ` [rfc] rename page_count for lockless pagecache Nick Piggin
2007-04-12 17:03 ` Peter Zijlstra
2007-04-12 23:27 ` Nick Piggin
2007-04-13 11:53 ` Hugh Dickins
2007-04-13 12:13 ` Nick Piggin
2007-04-14 2:24 ` Nick Piggin
2007-04-16 18:28 ` Hugh Dickins
2007-04-17 3:07 ` Nick Piggin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070412103330.5564.31067.sendpatchset@linux.site \
--to=npiggin@suse.de \
--cc=akpm@linux-foundation.org \
--cc=linux-mm@kvack.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox