xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/kmod/kmod.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun#
3*4882a593Smuzhiyun# Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
4*4882a593Smuzhiyun#
5*4882a593Smuzhiyun# This program is free software; you can redistribute it and/or modify it
6*4882a593Smuzhiyun# under the terms of the GNU General Public License as published by the Free
7*4882a593Smuzhiyun# Software Foundation; either version 2 of the License, or at your option any
8*4882a593Smuzhiyun# later version; or, when distributed separately from the Linux kernel or
9*4882a593Smuzhiyun# when incorporated into other software packages, subject to the following
10*4882a593Smuzhiyun# license:
11*4882a593Smuzhiyun#
12*4882a593Smuzhiyun# This program is free software; you can redistribute it and/or modify it
13*4882a593Smuzhiyun# under the terms of copyleft-next (version 0.3.1 or later) as published
14*4882a593Smuzhiyun# at http://copyleft-next.org/.
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun# This is a stress test script for kmod, the kernel module loader. It uses
17*4882a593Smuzhiyun# test_kmod which exposes a series of knobs for the API for us so we can
18*4882a593Smuzhiyun# tweak each test in userspace rather than in kernelspace.
19*4882a593Smuzhiyun#
20*4882a593Smuzhiyun# The way kmod works is it uses the kernel's usermode helper API to eventually
21*4882a593Smuzhiyun# call /sbin/modprobe. It has a limit of the number of concurrent calls
22*4882a593Smuzhiyun# possible. The kernel interface to load modules is request_module(), however
23*4882a593Smuzhiyun# mount uses get_fs_type(). Both behave slightly differently, but the
24*4882a593Smuzhiyun# differences are important enough to test each call separately. For this
25*4882a593Smuzhiyun# reason test_kmod starts by providing tests for both calls.
26*4882a593Smuzhiyun#
27*4882a593Smuzhiyun# The test driver test_kmod assumes a series of defaults which you can
28*4882a593Smuzhiyun# override by exporting to your environment prior running this script.
29*4882a593Smuzhiyun# For instance this script assumes you do not have xfs loaded upon boot.
30*4882a593Smuzhiyun# If this is false, export DEFAULT_KMOD_FS="ext4" prior to running this
31*4882a593Smuzhiyun# script if the filesystem module you don't have loaded upon bootup
32*4882a593Smuzhiyun# is ext4 instead. Refer to allow_user_defaults() for a list of user
33*4882a593Smuzhiyun# override variables possible.
34*4882a593Smuzhiyun#
35*4882a593Smuzhiyun# You'll want at least 4 GiB of RAM to expect to run these tests
36*4882a593Smuzhiyun# without running out of memory on them. For other requirements refer
37*4882a593Smuzhiyun# to test_reqs()
38*4882a593Smuzhiyun
39*4882a593Smuzhiyunset -e
40*4882a593Smuzhiyun
41*4882a593SmuzhiyunTEST_NAME="kmod"
42*4882a593SmuzhiyunTEST_DRIVER="test_${TEST_NAME}"
43*4882a593SmuzhiyunTEST_DIR=$(dirname $0)
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun# This represents
46*4882a593Smuzhiyun#
47*4882a593Smuzhiyun# TEST_ID:TEST_COUNT:ENABLED
48*4882a593Smuzhiyun#
49*4882a593Smuzhiyun# TEST_ID: is the test id number
50*4882a593Smuzhiyun# TEST_COUNT: number of times we should run the test
51*4882a593Smuzhiyun# ENABLED: 1 if enabled, 0 otherwise
52*4882a593Smuzhiyun#
53*4882a593Smuzhiyun# Once these are enabled please leave them as-is. Write your own test,
54*4882a593Smuzhiyun# we have tons of space.
55*4882a593SmuzhiyunALL_TESTS="0001:3:1"
56*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0002:3:1"
57*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0003:1:1"
58*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0004:1:1"
59*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0005:10:1"
60*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0006:10:1"
61*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0007:5:1"
62*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0008:150:1"
63*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0009:150:1"
64*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0010:1:1"
65*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0011:1:1"
66*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0012:1:1"
67*4882a593SmuzhiyunALL_TESTS="$ALL_TESTS 0013:1:1"
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun# Kselftest framework requirement - SKIP code is 4.
70*4882a593Smuzhiyunksft_skip=4
71*4882a593Smuzhiyun
72*4882a593Smuzhiyuntest_modprobe()
73*4882a593Smuzhiyun{
74*4882a593Smuzhiyun       if [ ! -d $DIR ]; then
75*4882a593Smuzhiyun               echo "$0: $DIR not present" >&2
76*4882a593Smuzhiyun               echo "You must have the following enabled in your kernel:" >&2
77*4882a593Smuzhiyun               cat $TEST_DIR/config >&2
78*4882a593Smuzhiyun               exit $ksft_skip
79*4882a593Smuzhiyun       fi
80*4882a593Smuzhiyun}
81*4882a593Smuzhiyun
82*4882a593Smuzhiyunfunction allow_user_defaults()
83*4882a593Smuzhiyun{
84*4882a593Smuzhiyun	if [ -z $DEFAULT_KMOD_DRIVER ]; then
85*4882a593Smuzhiyun		DEFAULT_KMOD_DRIVER="test_module"
86*4882a593Smuzhiyun	fi
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun	if [ -z $DEFAULT_KMOD_FS ]; then
89*4882a593Smuzhiyun		DEFAULT_KMOD_FS="xfs"
90*4882a593Smuzhiyun	fi
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun	if [ -z $PROC_DIR ]; then
93*4882a593Smuzhiyun		PROC_DIR="/proc/sys/kernel/"
94*4882a593Smuzhiyun	fi
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun	if [ -z $MODPROBE_LIMIT ]; then
97*4882a593Smuzhiyun		MODPROBE_LIMIT=50
98*4882a593Smuzhiyun	fi
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun	if [ -z $DIR ]; then
101*4882a593Smuzhiyun		DIR="/sys/devices/virtual/misc/${TEST_DRIVER}0/"
102*4882a593Smuzhiyun	fi
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun	if [ -z $DEFAULT_NUM_TESTS ]; then
105*4882a593Smuzhiyun		DEFAULT_NUM_TESTS=150
106*4882a593Smuzhiyun	fi
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun	MODPROBE_LIMIT_FILE="${PROC_DIR}/kmod-limit"
109*4882a593Smuzhiyun}
110*4882a593Smuzhiyun
111*4882a593Smuzhiyuntest_reqs()
112*4882a593Smuzhiyun{
113*4882a593Smuzhiyun	if ! which modprobe 2> /dev/null > /dev/null; then
114*4882a593Smuzhiyun		echo "$0: You need modprobe installed" >&2
115*4882a593Smuzhiyun		exit $ksft_skip
116*4882a593Smuzhiyun	fi
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun	if ! which kmod 2> /dev/null > /dev/null; then
119*4882a593Smuzhiyun		echo "$0: You need kmod installed" >&2
120*4882a593Smuzhiyun		exit $ksft_skip
121*4882a593Smuzhiyun	fi
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun	# kmod 19 has a bad bug where it returns 0 when modprobe
124*4882a593Smuzhiyun	# gets called *even* if the module was not loaded due to
125*4882a593Smuzhiyun	# some bad heuristics. For details see:
126*4882a593Smuzhiyun	#
127*4882a593Smuzhiyun	# A work around is possible in-kernel but its rather
128*4882a593Smuzhiyun	# complex.
129*4882a593Smuzhiyun	KMOD_VERSION=$(kmod --version | awk '{print $3}')
130*4882a593Smuzhiyun	if [[ $KMOD_VERSION  -le 19 ]]; then
131*4882a593Smuzhiyun		echo "$0: You need at least kmod 20" >&2
132*4882a593Smuzhiyun		echo "kmod <= 19 is buggy, for details see:" >&2
133*4882a593Smuzhiyun		echo "https://git.kernel.org/cgit/utils/kernel/kmod/kmod.git/commit/libkmod/libkmod-module.c?id=fd44a98ae2eb5eb32161088954ab21e58e19dfc4" >&2
134*4882a593Smuzhiyun		exit $ksft_skip
135*4882a593Smuzhiyun	fi
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun	uid=$(id -u)
138*4882a593Smuzhiyun	if [ $uid -ne 0 ]; then
139*4882a593Smuzhiyun		echo $msg must be run as root >&2
140*4882a593Smuzhiyun		exit $ksft_skip
141*4882a593Smuzhiyun	fi
142*4882a593Smuzhiyun}
143*4882a593Smuzhiyun
144*4882a593Smuzhiyunfunction load_req_mod()
145*4882a593Smuzhiyun{
146*4882a593Smuzhiyun	trap "test_modprobe" EXIT
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun	if [ ! -d $DIR ]; then
149*4882a593Smuzhiyun		# Alanis: "Oh isn't it ironic?"
150*4882a593Smuzhiyun		modprobe $TEST_DRIVER
151*4882a593Smuzhiyun	fi
152*4882a593Smuzhiyun}
153*4882a593Smuzhiyun
154*4882a593Smuzhiyuntest_finish()
155*4882a593Smuzhiyun{
156*4882a593Smuzhiyun	echo "$MODPROBE" > /proc/sys/kernel/modprobe
157*4882a593Smuzhiyun	echo "Test completed"
158*4882a593Smuzhiyun}
159*4882a593Smuzhiyun
160*4882a593Smuzhiyunerrno_name_to_val()
161*4882a593Smuzhiyun{
162*4882a593Smuzhiyun	case "$1" in
163*4882a593Smuzhiyun	# kmod calls modprobe and upon of a module not found
164*4882a593Smuzhiyun	# modprobe returns just 1... However in the kernel we
165*4882a593Smuzhiyun	# *sometimes* see 256...
166*4882a593Smuzhiyun	MODULE_NOT_FOUND)
167*4882a593Smuzhiyun		echo 256;;
168*4882a593Smuzhiyun	SUCCESS)
169*4882a593Smuzhiyun		echo 0;;
170*4882a593Smuzhiyun	-EPERM)
171*4882a593Smuzhiyun		echo -1;;
172*4882a593Smuzhiyun	-ENOENT)
173*4882a593Smuzhiyun		echo -2;;
174*4882a593Smuzhiyun	-EINVAL)
175*4882a593Smuzhiyun		echo -22;;
176*4882a593Smuzhiyun	-ERR_ANY)
177*4882a593Smuzhiyun		echo -123456;;
178*4882a593Smuzhiyun	*)
179*4882a593Smuzhiyun		echo invalid;;
180*4882a593Smuzhiyun	esac
181*4882a593Smuzhiyun}
182*4882a593Smuzhiyun
183*4882a593Smuzhiyunerrno_val_to_name()
184*4882a593Smuzhiyun	case "$1" in
185*4882a593Smuzhiyun	256)
186*4882a593Smuzhiyun		echo MODULE_NOT_FOUND;;
187*4882a593Smuzhiyun	0)
188*4882a593Smuzhiyun		echo SUCCESS;;
189*4882a593Smuzhiyun	-1)
190*4882a593Smuzhiyun		echo -EPERM;;
191*4882a593Smuzhiyun	-2)
192*4882a593Smuzhiyun		echo -ENOENT;;
193*4882a593Smuzhiyun	-22)
194*4882a593Smuzhiyun		echo -EINVAL;;
195*4882a593Smuzhiyun	-123456)
196*4882a593Smuzhiyun		echo -ERR_ANY;;
197*4882a593Smuzhiyun	*)
198*4882a593Smuzhiyun		echo invalid;;
199*4882a593Smuzhiyun	esac
200*4882a593Smuzhiyun
201*4882a593Smuzhiyunconfig_set_test_case_driver()
202*4882a593Smuzhiyun{
203*4882a593Smuzhiyun	if ! echo -n 1 >$DIR/config_test_case; then
204*4882a593Smuzhiyun		echo "$0: Unable to set to test case to driver" >&2
205*4882a593Smuzhiyun		exit 1
206*4882a593Smuzhiyun	fi
207*4882a593Smuzhiyun}
208*4882a593Smuzhiyun
209*4882a593Smuzhiyunconfig_set_test_case_fs()
210*4882a593Smuzhiyun{
211*4882a593Smuzhiyun	if ! echo -n 2 >$DIR/config_test_case; then
212*4882a593Smuzhiyun		echo "$0: Unable to set to test case to fs" >&2
213*4882a593Smuzhiyun		exit 1
214*4882a593Smuzhiyun	fi
215*4882a593Smuzhiyun}
216*4882a593Smuzhiyun
217*4882a593Smuzhiyunconfig_num_threads()
218*4882a593Smuzhiyun{
219*4882a593Smuzhiyun	if ! echo -n $1 >$DIR/config_num_threads; then
220*4882a593Smuzhiyun		echo "$0: Unable to set to number of threads" >&2
221*4882a593Smuzhiyun		exit 1
222*4882a593Smuzhiyun	fi
223*4882a593Smuzhiyun}
224*4882a593Smuzhiyun
225*4882a593Smuzhiyunconfig_get_modprobe_limit()
226*4882a593Smuzhiyun{
227*4882a593Smuzhiyun	if [[ -f ${MODPROBE_LIMIT_FILE} ]] ; then
228*4882a593Smuzhiyun		MODPROBE_LIMIT=$(cat $MODPROBE_LIMIT_FILE)
229*4882a593Smuzhiyun	fi
230*4882a593Smuzhiyun	echo $MODPROBE_LIMIT
231*4882a593Smuzhiyun}
232*4882a593Smuzhiyun
233*4882a593Smuzhiyunconfig_num_thread_limit_extra()
234*4882a593Smuzhiyun{
235*4882a593Smuzhiyun	MODPROBE_LIMIT=$(config_get_modprobe_limit)
236*4882a593Smuzhiyun	let EXTRA_LIMIT=$MODPROBE_LIMIT+$1
237*4882a593Smuzhiyun	config_num_threads $EXTRA_LIMIT
238*4882a593Smuzhiyun}
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun# For special characters use printf directly,
241*4882a593Smuzhiyun# refer to kmod_test_0001
242*4882a593Smuzhiyunconfig_set_driver()
243*4882a593Smuzhiyun{
244*4882a593Smuzhiyun	if ! echo -n $1 >$DIR/config_test_driver; then
245*4882a593Smuzhiyun		echo "$0: Unable to set driver" >&2
246*4882a593Smuzhiyun		exit 1
247*4882a593Smuzhiyun	fi
248*4882a593Smuzhiyun}
249*4882a593Smuzhiyun
250*4882a593Smuzhiyunconfig_set_fs()
251*4882a593Smuzhiyun{
252*4882a593Smuzhiyun	if ! echo -n $1 >$DIR/config_test_fs; then
253*4882a593Smuzhiyun		echo "$0: Unable to set driver" >&2
254*4882a593Smuzhiyun		exit 1
255*4882a593Smuzhiyun	fi
256*4882a593Smuzhiyun}
257*4882a593Smuzhiyun
258*4882a593Smuzhiyunconfig_get_driver()
259*4882a593Smuzhiyun{
260*4882a593Smuzhiyun	cat $DIR/config_test_driver
261*4882a593Smuzhiyun}
262*4882a593Smuzhiyun
263*4882a593Smuzhiyunconfig_get_test_result()
264*4882a593Smuzhiyun{
265*4882a593Smuzhiyun	cat $DIR/test_result
266*4882a593Smuzhiyun}
267*4882a593Smuzhiyun
268*4882a593Smuzhiyunconfig_reset()
269*4882a593Smuzhiyun{
270*4882a593Smuzhiyun	if ! echo -n "1" >"$DIR"/reset; then
271*4882a593Smuzhiyun		echo "$0: reset should have worked" >&2
272*4882a593Smuzhiyun		exit 1
273*4882a593Smuzhiyun	fi
274*4882a593Smuzhiyun}
275*4882a593Smuzhiyun
276*4882a593Smuzhiyunconfig_show_config()
277*4882a593Smuzhiyun{
278*4882a593Smuzhiyun	echo "----------------------------------------------------"
279*4882a593Smuzhiyun	cat "$DIR"/config
280*4882a593Smuzhiyun	echo "----------------------------------------------------"
281*4882a593Smuzhiyun}
282*4882a593Smuzhiyun
283*4882a593Smuzhiyunconfig_trigger()
284*4882a593Smuzhiyun{
285*4882a593Smuzhiyun	if ! echo -n "1" >"$DIR"/trigger_config 2>/dev/null; then
286*4882a593Smuzhiyun		echo "$1: FAIL - loading should have worked"
287*4882a593Smuzhiyun		config_show_config
288*4882a593Smuzhiyun		exit 1
289*4882a593Smuzhiyun	fi
290*4882a593Smuzhiyun	echo "$1: OK! - loading kmod test"
291*4882a593Smuzhiyun}
292*4882a593Smuzhiyun
293*4882a593Smuzhiyunconfig_trigger_want_fail()
294*4882a593Smuzhiyun{
295*4882a593Smuzhiyun	if echo "1" > $DIR/trigger_config 2>/dev/null; then
296*4882a593Smuzhiyun		echo "$1: FAIL - test case was expected to fail"
297*4882a593Smuzhiyun		config_show_config
298*4882a593Smuzhiyun		exit 1
299*4882a593Smuzhiyun	fi
300*4882a593Smuzhiyun	echo "$1: OK! - kmod test case failed as expected"
301*4882a593Smuzhiyun}
302*4882a593Smuzhiyun
303*4882a593Smuzhiyunconfig_expect_result()
304*4882a593Smuzhiyun{
305*4882a593Smuzhiyun	RC=$(config_get_test_result)
306*4882a593Smuzhiyun	RC_NAME=$(errno_val_to_name $RC)
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun	ERRNO_NAME=$2
309*4882a593Smuzhiyun	ERRNO=$(errno_name_to_val $ERRNO_NAME)
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun	if [[ $ERRNO_NAME = "-ERR_ANY" ]]; then
312*4882a593Smuzhiyun		if [[ $RC -ge 0 ]]; then
313*4882a593Smuzhiyun			echo "$1: FAIL, test expects $ERRNO_NAME - got $RC_NAME ($RC)" >&2
314*4882a593Smuzhiyun			config_show_config
315*4882a593Smuzhiyun			exit 1
316*4882a593Smuzhiyun		fi
317*4882a593Smuzhiyun	elif [[ $RC != $ERRNO ]]; then
318*4882a593Smuzhiyun		echo "$1: FAIL, test expects $ERRNO_NAME ($ERRNO) - got $RC_NAME ($RC)" >&2
319*4882a593Smuzhiyun		config_show_config
320*4882a593Smuzhiyun		exit 1
321*4882a593Smuzhiyun	fi
322*4882a593Smuzhiyun	echo "$1: OK! - Return value: $RC ($RC_NAME), expected $ERRNO_NAME"
323*4882a593Smuzhiyun}
324*4882a593Smuzhiyun
325*4882a593Smuzhiyunkmod_defaults_driver()
326*4882a593Smuzhiyun{
327*4882a593Smuzhiyun	config_reset
328*4882a593Smuzhiyun	modprobe -r $DEFAULT_KMOD_DRIVER
329*4882a593Smuzhiyun	config_set_driver $DEFAULT_KMOD_DRIVER
330*4882a593Smuzhiyun}
331*4882a593Smuzhiyun
332*4882a593Smuzhiyunkmod_defaults_fs()
333*4882a593Smuzhiyun{
334*4882a593Smuzhiyun	config_reset
335*4882a593Smuzhiyun	modprobe -r $DEFAULT_KMOD_FS
336*4882a593Smuzhiyun	config_set_fs $DEFAULT_KMOD_FS
337*4882a593Smuzhiyun	config_set_test_case_fs
338*4882a593Smuzhiyun}
339*4882a593Smuzhiyun
340*4882a593Smuzhiyunkmod_test_0001_driver()
341*4882a593Smuzhiyun{
342*4882a593Smuzhiyun	NAME='\000'
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun	kmod_defaults_driver
345*4882a593Smuzhiyun	config_num_threads 1
346*4882a593Smuzhiyun	printf $NAME >"$DIR"/config_test_driver
347*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
348*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} MODULE_NOT_FOUND
349*4882a593Smuzhiyun}
350*4882a593Smuzhiyun
351*4882a593Smuzhiyunkmod_test_0001_fs()
352*4882a593Smuzhiyun{
353*4882a593Smuzhiyun	NAME='\000'
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun	kmod_defaults_fs
356*4882a593Smuzhiyun	config_num_threads 1
357*4882a593Smuzhiyun	printf $NAME >"$DIR"/config_test_fs
358*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
359*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} -EINVAL
360*4882a593Smuzhiyun}
361*4882a593Smuzhiyun
362*4882a593Smuzhiyunkmod_test_0001()
363*4882a593Smuzhiyun{
364*4882a593Smuzhiyun	kmod_test_0001_driver
365*4882a593Smuzhiyun	kmod_test_0001_fs
366*4882a593Smuzhiyun}
367*4882a593Smuzhiyun
368*4882a593Smuzhiyunkmod_test_0002_driver()
369*4882a593Smuzhiyun{
370*4882a593Smuzhiyun	NAME="nope-$DEFAULT_KMOD_DRIVER"
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun	kmod_defaults_driver
373*4882a593Smuzhiyun	config_set_driver $NAME
374*4882a593Smuzhiyun	config_num_threads 1
375*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
376*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} MODULE_NOT_FOUND
377*4882a593Smuzhiyun}
378*4882a593Smuzhiyun
379*4882a593Smuzhiyunkmod_test_0002_fs()
380*4882a593Smuzhiyun{
381*4882a593Smuzhiyun	NAME="nope-$DEFAULT_KMOD_FS"
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun	kmod_defaults_fs
384*4882a593Smuzhiyun	config_set_fs $NAME
385*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
386*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} -EINVAL
387*4882a593Smuzhiyun}
388*4882a593Smuzhiyun
389*4882a593Smuzhiyunkmod_test_0002()
390*4882a593Smuzhiyun{
391*4882a593Smuzhiyun	kmod_test_0002_driver
392*4882a593Smuzhiyun	kmod_test_0002_fs
393*4882a593Smuzhiyun}
394*4882a593Smuzhiyun
395*4882a593Smuzhiyunkmod_test_0003()
396*4882a593Smuzhiyun{
397*4882a593Smuzhiyun	kmod_defaults_fs
398*4882a593Smuzhiyun	config_num_threads 1
399*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
400*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} SUCCESS
401*4882a593Smuzhiyun}
402*4882a593Smuzhiyun
403*4882a593Smuzhiyunkmod_test_0004()
404*4882a593Smuzhiyun{
405*4882a593Smuzhiyun	kmod_defaults_fs
406*4882a593Smuzhiyun	config_num_threads 2
407*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
408*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} SUCCESS
409*4882a593Smuzhiyun}
410*4882a593Smuzhiyun
411*4882a593Smuzhiyunkmod_test_0005()
412*4882a593Smuzhiyun{
413*4882a593Smuzhiyun	kmod_defaults_driver
414*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
415*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} SUCCESS
416*4882a593Smuzhiyun}
417*4882a593Smuzhiyun
418*4882a593Smuzhiyunkmod_test_0006()
419*4882a593Smuzhiyun{
420*4882a593Smuzhiyun	kmod_defaults_fs
421*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
422*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} SUCCESS
423*4882a593Smuzhiyun}
424*4882a593Smuzhiyun
425*4882a593Smuzhiyunkmod_test_0007()
426*4882a593Smuzhiyun{
427*4882a593Smuzhiyun	kmod_test_0005
428*4882a593Smuzhiyun	kmod_test_0006
429*4882a593Smuzhiyun}
430*4882a593Smuzhiyun
431*4882a593Smuzhiyunkmod_test_0008()
432*4882a593Smuzhiyun{
433*4882a593Smuzhiyun	kmod_defaults_driver
434*4882a593Smuzhiyun	MODPROBE_LIMIT=$(config_get_modprobe_limit)
435*4882a593Smuzhiyun	let EXTRA=$MODPROBE_LIMIT/6
436*4882a593Smuzhiyun	config_num_thread_limit_extra $EXTRA
437*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
438*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} SUCCESS
439*4882a593Smuzhiyun}
440*4882a593Smuzhiyun
441*4882a593Smuzhiyunkmod_test_0009()
442*4882a593Smuzhiyun{
443*4882a593Smuzhiyun	kmod_defaults_fs
444*4882a593Smuzhiyun	MODPROBE_LIMIT=$(config_get_modprobe_limit)
445*4882a593Smuzhiyun	let EXTRA=$MODPROBE_LIMIT/4
446*4882a593Smuzhiyun	config_num_thread_limit_extra $EXTRA
447*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
448*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} SUCCESS
449*4882a593Smuzhiyun}
450*4882a593Smuzhiyun
451*4882a593Smuzhiyunkmod_test_0010()
452*4882a593Smuzhiyun{
453*4882a593Smuzhiyun	kmod_defaults_driver
454*4882a593Smuzhiyun	config_num_threads 1
455*4882a593Smuzhiyun	echo "/KMOD_TEST_NONEXISTENT" > /proc/sys/kernel/modprobe
456*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
457*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} -ENOENT
458*4882a593Smuzhiyun	echo "$MODPROBE" > /proc/sys/kernel/modprobe
459*4882a593Smuzhiyun}
460*4882a593Smuzhiyun
461*4882a593Smuzhiyunkmod_test_0011()
462*4882a593Smuzhiyun{
463*4882a593Smuzhiyun	kmod_defaults_driver
464*4882a593Smuzhiyun	config_num_threads 1
465*4882a593Smuzhiyun	# This causes the kernel to not even try executing modprobe.  The error
466*4882a593Smuzhiyun	# code is still -ENOENT like when modprobe doesn't exist, so we can't
467*4882a593Smuzhiyun	# easily test for the exact difference.  But this still is a useful test
468*4882a593Smuzhiyun	# since there was a bug where request_module() returned 0 in this case.
469*4882a593Smuzhiyun	echo > /proc/sys/kernel/modprobe
470*4882a593Smuzhiyun	config_trigger ${FUNCNAME[0]}
471*4882a593Smuzhiyun	config_expect_result ${FUNCNAME[0]} -ENOENT
472*4882a593Smuzhiyun	echo "$MODPROBE" > /proc/sys/kernel/modprobe
473*4882a593Smuzhiyun}
474*4882a593Smuzhiyun
475*4882a593Smuzhiyunkmod_check_visibility()
476*4882a593Smuzhiyun{
477*4882a593Smuzhiyun	local name="$1"
478*4882a593Smuzhiyun	local cmd="$2"
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun	modprobe $DEFAULT_KMOD_DRIVER
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun	local priv=$(eval $cmd)
483*4882a593Smuzhiyun	local unpriv=$(capsh --drop=CAP_SYSLOG -- -c "$cmd")
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun	if [ "$priv" = "$unpriv" ] || \
486*4882a593Smuzhiyun	   [ "${priv:0:3}" = "0x0" ] || \
487*4882a593Smuzhiyun	   [ "${unpriv:0:3}" != "0x0" ] ; then
488*4882a593Smuzhiyun		echo "${FUNCNAME[0]}: FAIL, $name visible to unpriv: '$priv' vs '$unpriv'" >&2
489*4882a593Smuzhiyun		exit 1
490*4882a593Smuzhiyun	else
491*4882a593Smuzhiyun		echo "${FUNCNAME[0]}: OK!"
492*4882a593Smuzhiyun	fi
493*4882a593Smuzhiyun}
494*4882a593Smuzhiyun
495*4882a593Smuzhiyunkmod_test_0012()
496*4882a593Smuzhiyun{
497*4882a593Smuzhiyun	kmod_check_visibility /proc/modules \
498*4882a593Smuzhiyun		"grep '^${DEFAULT_KMOD_DRIVER}\b' /proc/modules | awk '{print \$NF}'"
499*4882a593Smuzhiyun}
500*4882a593Smuzhiyun
501*4882a593Smuzhiyunkmod_test_0013()
502*4882a593Smuzhiyun{
503*4882a593Smuzhiyun	kmod_check_visibility '/sys/module/*/sections/*' \
504*4882a593Smuzhiyun		"cat /sys/module/${DEFAULT_KMOD_DRIVER}/sections/.*text | head -n1"
505*4882a593Smuzhiyun}
506*4882a593Smuzhiyun
507*4882a593Smuzhiyunlist_tests()
508*4882a593Smuzhiyun{
509*4882a593Smuzhiyun	echo "Test ID list:"
510*4882a593Smuzhiyun	echo
511*4882a593Smuzhiyun	echo "TEST_ID x NUM_TEST"
512*4882a593Smuzhiyun	echo "TEST_ID:   Test ID"
513*4882a593Smuzhiyun	echo "NUM_TESTS: Number of recommended times to run the test"
514*4882a593Smuzhiyun	echo
515*4882a593Smuzhiyun	echo "0001 x $(get_test_count 0001) - Simple test - 1 thread  for empty string"
516*4882a593Smuzhiyun	echo "0002 x $(get_test_count 0002) - Simple test - 1 thread  for modules/filesystems that do not exist"
517*4882a593Smuzhiyun	echo "0003 x $(get_test_count 0003) - Simple test - 1 thread  for get_fs_type() only"
518*4882a593Smuzhiyun	echo "0004 x $(get_test_count 0004) - Simple test - 2 threads for get_fs_type() only"
519*4882a593Smuzhiyun	echo "0005 x $(get_test_count 0005) - multithreaded tests with default setup - request_module() only"
520*4882a593Smuzhiyun	echo "0006 x $(get_test_count 0006) - multithreaded tests with default setup - get_fs_type() only"
521*4882a593Smuzhiyun	echo "0007 x $(get_test_count 0007) - multithreaded tests with default setup test request_module() and get_fs_type()"
522*4882a593Smuzhiyun	echo "0008 x $(get_test_count 0008) - multithreaded - push kmod_concurrent over max_modprobes for request_module()"
523*4882a593Smuzhiyun	echo "0009 x $(get_test_count 0009) - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()"
524*4882a593Smuzhiyun	echo "0010 x $(get_test_count 0010) - test nonexistent modprobe path"
525*4882a593Smuzhiyun	echo "0011 x $(get_test_count 0011) - test completely disabling module autoloading"
526*4882a593Smuzhiyun	echo "0012 x $(get_test_count 0012) - test /proc/modules address visibility under CAP_SYSLOG"
527*4882a593Smuzhiyun	echo "0013 x $(get_test_count 0013) - test /sys/module/*/sections/* visibility under CAP_SYSLOG"
528*4882a593Smuzhiyun}
529*4882a593Smuzhiyun
530*4882a593Smuzhiyunusage()
531*4882a593Smuzhiyun{
532*4882a593Smuzhiyun	NUM_TESTS=$(grep -o ' ' <<<"$ALL_TESTS" | grep -c .)
533*4882a593Smuzhiyun	let NUM_TESTS=$NUM_TESTS+1
534*4882a593Smuzhiyun	MAX_TEST=$(printf "%04d\n" $NUM_TESTS)
535*4882a593Smuzhiyun	echo "Usage: $0 [ -t <4-number-digit> ] | [ -w <4-number-digit> ] |"
536*4882a593Smuzhiyun	echo "		 [ -s <4-number-digit> ] | [ -c <4-number-digit> <test- count>"
537*4882a593Smuzhiyun	echo "           [ all ] [ -h | --help ] [ -l ]"
538*4882a593Smuzhiyun	echo ""
539*4882a593Smuzhiyun	echo "Valid tests: 0001-$MAX_TEST"
540*4882a593Smuzhiyun	echo ""
541*4882a593Smuzhiyun	echo "    all     Runs all tests (default)"
542*4882a593Smuzhiyun	echo "    -t      Run test ID the number amount of times is recommended"
543*4882a593Smuzhiyun	echo "    -w      Watch test ID run until it runs into an error"
544*4882a593Smuzhiyun	echo "    -s      Run test ID once"
545*4882a593Smuzhiyun	echo "    -c      Run test ID x test-count number of times"
546*4882a593Smuzhiyun	echo "    -l      List all test ID list"
547*4882a593Smuzhiyun	echo " -h|--help  Help"
548*4882a593Smuzhiyun	echo
549*4882a593Smuzhiyun	echo "If an error every occurs execution will immediately terminate."
550*4882a593Smuzhiyun	echo "If you are adding a new test try using -w <test-ID> first to"
551*4882a593Smuzhiyun	echo "make sure the test passes a series of tests."
552*4882a593Smuzhiyun	echo
553*4882a593Smuzhiyun	echo Example uses:
554*4882a593Smuzhiyun	echo
555*4882a593Smuzhiyun	echo "${TEST_NAME}.sh		-- executes all tests"
556*4882a593Smuzhiyun	echo "${TEST_NAME}.sh -t 0008	-- Executes test ID 0008 number of times is recommended"
557*4882a593Smuzhiyun	echo "${TEST_NAME}.sh -w 0008	-- Watch test ID 0008 run until an error occurs"
558*4882a593Smuzhiyun	echo "${TEST_NAME}.sh -s 0008	-- Run test ID 0008 once"
559*4882a593Smuzhiyun	echo "${TEST_NAME}.sh -c 0008 3	-- Run test ID 0008 three times"
560*4882a593Smuzhiyun	echo
561*4882a593Smuzhiyun	list_tests
562*4882a593Smuzhiyun	exit 1
563*4882a593Smuzhiyun}
564*4882a593Smuzhiyun
565*4882a593Smuzhiyunfunction test_num()
566*4882a593Smuzhiyun{
567*4882a593Smuzhiyun	re='^[0-9]+$'
568*4882a593Smuzhiyun	if ! [[ $1 =~ $re ]]; then
569*4882a593Smuzhiyun		usage
570*4882a593Smuzhiyun	fi
571*4882a593Smuzhiyun}
572*4882a593Smuzhiyun
573*4882a593Smuzhiyunfunction get_test_data()
574*4882a593Smuzhiyun{
575*4882a593Smuzhiyun	test_num $1
576*4882a593Smuzhiyun	local field_num=$(echo $1 | sed 's/^0*//')
577*4882a593Smuzhiyun	echo $ALL_TESTS | awk '{print $'$field_num'}'
578*4882a593Smuzhiyun}
579*4882a593Smuzhiyun
580*4882a593Smuzhiyunfunction get_test_count()
581*4882a593Smuzhiyun{
582*4882a593Smuzhiyun	TEST_DATA=$(get_test_data $1)
583*4882a593Smuzhiyun	LAST_TWO=${TEST_DATA#*:*}
584*4882a593Smuzhiyun	echo ${LAST_TWO%:*}
585*4882a593Smuzhiyun}
586*4882a593Smuzhiyun
587*4882a593Smuzhiyunfunction get_test_enabled()
588*4882a593Smuzhiyun{
589*4882a593Smuzhiyun	TEST_DATA=$(get_test_data $1)
590*4882a593Smuzhiyun	echo ${TEST_DATA#*:*:}
591*4882a593Smuzhiyun}
592*4882a593Smuzhiyun
593*4882a593Smuzhiyunfunction run_all_tests()
594*4882a593Smuzhiyun{
595*4882a593Smuzhiyun	for i in $ALL_TESTS ; do
596*4882a593Smuzhiyun		TEST_ID=${i%:*:*}
597*4882a593Smuzhiyun		ENABLED=$(get_test_enabled $TEST_ID)
598*4882a593Smuzhiyun		TEST_COUNT=$(get_test_count $TEST_ID)
599*4882a593Smuzhiyun		if [[ $ENABLED -eq "1" ]]; then
600*4882a593Smuzhiyun			test_case $TEST_ID $TEST_COUNT
601*4882a593Smuzhiyun		fi
602*4882a593Smuzhiyun	done
603*4882a593Smuzhiyun}
604*4882a593Smuzhiyun
605*4882a593Smuzhiyunfunction watch_log()
606*4882a593Smuzhiyun{
607*4882a593Smuzhiyun	if [ $# -ne 3 ]; then
608*4882a593Smuzhiyun		clear
609*4882a593Smuzhiyun	fi
610*4882a593Smuzhiyun	date
611*4882a593Smuzhiyun	echo "Running test: $2 - run #$1"
612*4882a593Smuzhiyun}
613*4882a593Smuzhiyun
614*4882a593Smuzhiyunfunction watch_case()
615*4882a593Smuzhiyun{
616*4882a593Smuzhiyun	i=0
617*4882a593Smuzhiyun	while [ 1 ]; do
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun		if [ $# -eq 1 ]; then
620*4882a593Smuzhiyun			test_num $1
621*4882a593Smuzhiyun			watch_log $i ${TEST_NAME}_test_$1
622*4882a593Smuzhiyun			${TEST_NAME}_test_$1
623*4882a593Smuzhiyun		else
624*4882a593Smuzhiyun			watch_log $i all
625*4882a593Smuzhiyun			run_all_tests
626*4882a593Smuzhiyun		fi
627*4882a593Smuzhiyun		let i=$i+1
628*4882a593Smuzhiyun	done
629*4882a593Smuzhiyun}
630*4882a593Smuzhiyun
631*4882a593Smuzhiyunfunction test_case()
632*4882a593Smuzhiyun{
633*4882a593Smuzhiyun	NUM_TESTS=$DEFAULT_NUM_TESTS
634*4882a593Smuzhiyun	if [ $# -eq 2 ]; then
635*4882a593Smuzhiyun		NUM_TESTS=$2
636*4882a593Smuzhiyun	fi
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun	i=0
639*4882a593Smuzhiyun	while [ $i -lt $NUM_TESTS ]; do
640*4882a593Smuzhiyun		test_num $1
641*4882a593Smuzhiyun		watch_log $i ${TEST_NAME}_test_$1 noclear
642*4882a593Smuzhiyun		RUN_TEST=${TEST_NAME}_test_$1
643*4882a593Smuzhiyun		$RUN_TEST
644*4882a593Smuzhiyun		let i=$i+1
645*4882a593Smuzhiyun	done
646*4882a593Smuzhiyun}
647*4882a593Smuzhiyun
648*4882a593Smuzhiyunfunction parse_args()
649*4882a593Smuzhiyun{
650*4882a593Smuzhiyun	if [ $# -eq 0 ]; then
651*4882a593Smuzhiyun		run_all_tests
652*4882a593Smuzhiyun	else
653*4882a593Smuzhiyun		if [[ "$1" = "all" ]]; then
654*4882a593Smuzhiyun			run_all_tests
655*4882a593Smuzhiyun		elif [[ "$1" = "-w" ]]; then
656*4882a593Smuzhiyun			shift
657*4882a593Smuzhiyun			watch_case $@
658*4882a593Smuzhiyun		elif [[ "$1" = "-t" ]]; then
659*4882a593Smuzhiyun			shift
660*4882a593Smuzhiyun			test_num $1
661*4882a593Smuzhiyun			test_case $1 $(get_test_count $1)
662*4882a593Smuzhiyun		elif [[ "$1" = "-c" ]]; then
663*4882a593Smuzhiyun			shift
664*4882a593Smuzhiyun			test_num $1
665*4882a593Smuzhiyun			test_num $2
666*4882a593Smuzhiyun			test_case $1 $2
667*4882a593Smuzhiyun		elif [[ "$1" = "-s" ]]; then
668*4882a593Smuzhiyun			shift
669*4882a593Smuzhiyun			test_case $1 1
670*4882a593Smuzhiyun		elif [[ "$1" = "-l" ]]; then
671*4882a593Smuzhiyun			list_tests
672*4882a593Smuzhiyun		elif [[ "$1" = "-h" || "$1" = "--help" ]]; then
673*4882a593Smuzhiyun			usage
674*4882a593Smuzhiyun		else
675*4882a593Smuzhiyun			usage
676*4882a593Smuzhiyun		fi
677*4882a593Smuzhiyun	fi
678*4882a593Smuzhiyun}
679*4882a593Smuzhiyun
680*4882a593Smuzhiyuntest_reqs
681*4882a593Smuzhiyunallow_user_defaults
682*4882a593Smuzhiyunload_req_mod
683*4882a593Smuzhiyun
684*4882a593SmuzhiyunMODPROBE=$(</proc/sys/kernel/modprobe)
685*4882a593Smuzhiyuntrap "test_finish" EXIT
686*4882a593Smuzhiyun
687*4882a593Smuzhiyunparse_args $@
688*4882a593Smuzhiyun
689*4882a593Smuzhiyunexit 0
690