All of lore.kernel.org
 help / color / mirror / Atom feed
From: Konstantin Khlebnikov <khlebnikov@openvz.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-modules@vger.kernel.org, Jon Masters <jcm@redhat.com>
Subject: [PATCH 01/12] tools/testing/modules: introduce test which loads/unloads random modules
Date: Fri, 14 Dec 2012 15:02:29 +0400	[thread overview]
Message-ID: <20121214110229.11019.63713.stgit@zurg> (raw)

This test tries to expose bugs and races in modules' init/exit code blocks.

Loading and unloading random modules shouldn't lead to the kernel crash.
Kernel cannot load all modules at once due to limitations in per-cpu allocator.
By default this script runs 4 iterations of two-phased test: on first phase it
loads/unloads all modules one by one in random order. On the second phase it
loads modules until it got 10 fail in a row, after that it unloads all modules
and goes on. Script excludes from test all modules which are already loaded.

usage sample:

 make -C tools/testing/modules/ test_all test_normal test_staging

script modprobe-remove-test.sh takes configuration from the environment:

#  environment var      example         default
#
#  MODULES              "foo bar"       all, except loaded and excluded
#  INCLUDE_MODULES      "foo bar"       ""
#  EXCLUDE_MODULES      "foo bar"       ""
#  INCLUDE_DIRS         "net/ sound/"   ""
#  EXCLUDE_DIRS         "drivers/ foo/" ""
#  ITERATIONS           "0"             "4"
#  MAX_FAILS            "0"             "10"
#  MODULES_ROOT         "/foo"          ""
#  MODULES_DIR          "/foo/bar"      "$MODULES_ROOT/lib/modules/`uname -r`/kernel"
#  MODPROBE_ARGS        ""              "--verbose --ignore-remove --ignore-install"
#
#  overriding priority: MODULES > EXCLUDE_* = LOADED > INCLUDE_*

Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jon Masters <jcm@redhat.com>
Cc: linux-modules@vger.kernel.org
---
 tools/testing/modules/Makefile                |    8 +
 tools/testing/modules/modprobe-remove-test.sh |  167 +++++++++++++++++++++++++
 2 files changed, 175 insertions(+)
 create mode 100644 tools/testing/modules/Makefile
 create mode 100755 tools/testing/modules/modprobe-remove-test.sh

diff --git a/tools/testing/modules/Makefile b/tools/testing/modules/Makefile
new file mode 100644
index 0000000..7adc4b5
--- /dev/null
+++ b/tools/testing/modules/Makefile
@@ -0,0 +1,8 @@
+test_all:
+	./modprobe-remove-test.sh
+
+test_normal:
+	EXCLUDE_DIRS="drivers/staging/" ./modprobe-remove-test.sh
+
+test_staging:
+	INCLUDE_DIRS="drivers/staging/" ./modprobe-remove-test.sh
diff --git a/tools/testing/modules/modprobe-remove-test.sh b/tools/testing/modules/modprobe-remove-test.sh
new file mode 100755
index 0000000..1d30f64
--- /dev/null
+++ b/tools/testing/modules/modprobe-remove-test.sh
@@ -0,0 +1,167 @@
+#!/bin/bash
+#
+#  modprobe-remove-test.sh - load/unload modules in random order
+#
+#   - first phase  : load/unload all possible modules one by one
+#   - second phase : load multiple modules, remove all after $MAX_FAILS in a row
+#
+#  environment var	example		default
+#
+#  MODULES		"foo bar"	all, except loaded and excluded
+#  INCLUDE_MODULES	"foo bar"	""
+#  EXCLUDE_MODULES	"foo bar"	""
+#  INCLUDE_DIRS		"net/ sound/"	""
+#  EXCLUDE_DIRS		"drivers/ foo/"	""
+#  ITERATIONS		"0"		"4"
+#  MAX_FAILS		"100"		"10"
+#  MODULES_ROOT		"/foo"		""
+#  MODULES_DIR		"/foo/bar"	"$MODULES_ROOT/lib/modules/`uname -r`/kernel"
+#  MODPROBE_ARGS	""		"--verbose --ignore-remove --ignore-install"
+#
+#  overriding priority: MODULES > EXCLUDE_* = LOADED > INCLUDE_*
+#
+
+: ${MAX_FAILS=10}
+: ${ITERATIONS=4}
+
+: ${MODULES_ROOT=}
+: ${MODULES_DIR=$MODULES_ROOT/lib/modules/`uname -r`/kernel}
+
+: ${MODPROBE_ARGS=--verbose --ignore-remove --ignore-install}
+[ -n "$MODULES_ROOT" ] && MODULES_ARGS="--dirname=$MODULES_ROOT $MODULES_ARGS"
+
+set -o pipefail
+
+line_modules() {
+	for M in $@ ; do echo $M ; done
+}
+
+subtract_modules() {
+	comm -2 -3 <(echo "$1" | sort -u) <(echo "$2" | sort -u)
+}
+
+loaded_modules() {
+	lsmod | awk 'FNR != 1 { print $1 }' | sort -u
+}
+
+list_modules() {
+	(
+		cd "$MODULES_DIR" &&
+		find $@ -type f -name '*.ko' -printf '%f\n' |
+		sed 's/.ko$//;s/-/_/g'
+	)
+}
+
+load_module() {
+	modprobe ${MODPROBE_ARGS} "$1"
+}
+
+unload_module() {
+	modprobe ${MODPROBE_ARGS} --remove "$1"
+}
+
+topological_sort() {
+	local M
+	for M in $@ ; do
+		echo `modprobe ${MODPROBE_ARGS} --show-depends $M | wc -l` $M
+	done | sort -n -r | cut -d ' ' -f 2
+}
+
+unload_all_modules() {
+	local M
+
+	# try to unload in random order
+	LOADED_MODULES=`loaded_modules`
+	UNLOAD_MODULES=`subtract_modules "$LOADED_MODULES" "$EXCLUDE_MODULES"`
+	UNLOAD_MODULES=`echo "$UNLOAD_MODULES" | sort -R`
+	for M in $UNLOAD_MODULES ; do
+		unload_module $M
+	done
+
+	# unload the rest in topological order
+	LOADED_MODULES=`loaded_modules`
+	UNLOAD_MODULES=`subtract_modules "$LOADED_MODULES" "$EXCLUDE_MODULES"`
+	UNLOAD_MODULES=`topological_sort $UNLOAD_MODULES`
+	for M in $UNLOAD_MODULES ; do
+		unload_module $M
+	done
+}
+
+do_exit() {
+	unload_all_modules
+	echo "--- interrupted "
+	exit 2
+}
+
+trap do_exit INT TERM
+
+INITIAL_MODULES=`loaded_modules` || exit
+
+if [ -n "$EXCLUDE_DIRS" ] ; then
+	EXCLUDE_MODULES="$EXCLUDE_MODULES `list_modules $EXCLUDE_DIRS`" || exit
+fi
+
+EXCLUDE_MODULES=`line_modules $EXCLUDE_MODULES $INITIAL_MODULES`
+
+MODULES=`line_modules $MODULES`
+EXCLUDE_MODULES=`subtract_modules "$EXCLUDE_MODULES" "$MODULES"`
+
+if [ -n "$INCLUDE_DIRS" ] ; then
+	MODULES="$MODULES `list_modules $INCLUDE_DIRS`" || exit
+fi
+
+MODULES=`line_modules $MODULES $INCLUDE_MODULES`
+
+if [ -z "$MODULES" ] ; then
+	MODULES=`list_modules "."` || exit
+fi
+
+POSSIBLE_MODULES="$MODULES"
+
+MODULES=`subtract_modules "$MODULES" "$EXCLUDE_MODULES"`
+
+EXCLUDED_MODULES=`subtract_modules "$POSSIBLE_MODULES" "$MODULES"`
+
+echo "--- loaded modules:" $INITIAL_MODULES
+
+echo "--- modules under test:" $MODULES
+
+echo "--- excluded modules:" $EXCLUDED_MODULES
+
+for (( I=1 ; I <= $ITERATIONS ; I++ )) ; do
+	echo "--- iteration $I in $ITERATIONS"
+
+	echo "--- load/unload modules one by one"
+	for M in `echo "$MODULES" | sort -R` ; do
+		load_module "$M"
+		unload_module "$M"
+		unload_all_modules
+	done
+
+	echo "--- load multiple modules at once"
+	FAILS=0
+	for M in `echo "$MODULES" | sort -R` ; do
+		if load_module "$M" ; then
+			FAILS=0
+			continue
+		fi
+		if ((++FAILS >= MAX_FAILS)) ; then
+			echo "--- $FAILS fails in a row: unload all modules"
+			unload_all_modules
+			FAILS=0
+		fi
+	done
+	unload_all_modules
+	unload_all_modules
+done
+
+LOADED_MODULES=`loaded_modules`
+STUCK_MODULES=`subtract_modules "$LOADED_MODULES" "$INITIAL_MODULES"`
+MISSING_MODULES=`subtract_modules "$INITIAL_MODULES" "$LOADED_MODULES"`
+
+echo "--- stuck modules:" $STUCK_MODULES
+
+echo "--- missing modules:" $MISSING_MODULES
+
+echo "--- done"
+exit 0


             reply	other threads:[~2012-12-14 11:02 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-14 11:02 Konstantin Khlebnikov [this message]
2012-12-14 11:02 ` [PATCH 02/12] driver core: add debug-objects debug for device-drivers Konstantin Khlebnikov
2012-12-14 11:02 ` [PATCH 03/12] mISDN: fix race in timer canceling on module unloading Konstantin Khlebnikov
2012-12-14 18:16   ` David Miller
2012-12-14 11:02 ` [PATCH 04/12] pps: pps_parport: fix oops " Konstantin Khlebnikov
2012-12-14 11:02 ` [PATCH 05/12] staging: vme_pio2: " Konstantin Khlebnikov
2012-12-17 12:01   ` Martyn Welch
2012-12-14 11:02 ` [PATCH 06/12] media/rc: fix oops on unloading module rc-core Konstantin Khlebnikov
2012-12-14 11:02 ` [PATCH 07/12] stmmac: fix platform driver unregistering Konstantin Khlebnikov
2012-12-14 18:16   ` David Miller
2012-12-14 11:02 ` [PATCH 08/12] bonding: do not cancel works in bond_uninit() Konstantin Khlebnikov
2012-12-14 18:16   ` David Miller
2012-12-14 11:02 ` [PATCH 09/12] pps: fix device destruction ordering Konstantin Khlebnikov
2012-12-14 11:03 ` [PATCH 10/12] mac802154: fix destructon ordering for ieee802154 devices Konstantin Khlebnikov
2012-12-14 18:16   ` David Miller
2012-12-14 18:16     ` David Miller
2012-12-14 11:03 ` [PATCH 11/12] firmware/dmi-sysfs: fix sysfs warning on module unload Konstantin Khlebnikov
2012-12-14 11:03 ` [PATCH 12/12] edac: fix kernel panic on module unloading Konstantin Khlebnikov
2012-12-14 11:26   ` Alan Cox
2012-12-14 11:50     ` Borislav Petkov
2012-12-14 11:55     ` Konstantin Khlebnikov
2012-12-14 13:26       ` Alan Cox
2012-12-15 17:53   ` Borislav Petkov

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=20121214110229.11019.63713.stgit@zurg \
    --to=khlebnikov@openvz.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jcm@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-modules@vger.kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.