1#!/bin/bash
2#
3# NAME
4#	failcmd.sh - run a command with injecting slab/page allocation failures
5#
6# SYNOPSIS
7#	failcmd.sh --help
8#	failcmd.sh [<options>] command [arguments]
9#
10# DESCRIPTION
11#	Run command with injecting slab/page allocation failures by fault
12#	injection.
13#
14#	NOTE: you need to run this script as root.
15#
16
17usage()
18{
19	cat >&2 <<EOF
20Usage: $0 [options] command [arguments]
21
22OPTIONS
23	-p percent
24	--probability=percent
25		likelihood of failure injection, in percent.
26		Default value is 1
27
28	-t value
29	--times=value
30		specifies how many times failures may happen at most.
31		Default value is 1
32
33	--oom-kill-allocating-task=value
34		set /proc/sys/vm/oom_kill_allocating_task to specified value
35		before running the command.
36		Default value is 1
37
38	-h, --help
39		Display a usage message and exit
40
41	--interval=value, --space=value, --verbose=value, --task-filter=value,
42	--stacktrace-depth=value, --require-start=value, --require-end=value,
43	--reject-start=value, --reject-end=value, --ignore-gfp-wait=value
44		See Documentation/fault-injection/fault-injection.txt for more
45		information
46
47	failslab options:
48	--cache-filter=value
49
50	fail_page_alloc options:
51	--ignore-gfp-highmem=value, --min-order=value
52
53ENVIRONMENT
54	FAILCMD_TYPE
55		The following values for FAILCMD_TYPE are recognized:
56
57		failslab
58			inject slab allocation failures
59		fail_page_alloc
60			inject page allocation failures
61
62		If FAILCMD_TYPE is not defined, then failslab is used.
63EOF
64}
65
66if [ $UID != 0 ]; then
67	echo must be run as root >&2
68	exit 1
69fi
70
71DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3}'`
72
73if [ ! -d "$DEBUGFS" ]; then
74	echo debugfs is not mounted >&2
75	exit 1
76fi
77
78FAILCMD_TYPE=${FAILCMD_TYPE:-failslab}
79FAULTATTR=$DEBUGFS/$FAILCMD_TYPE
80
81if [ ! -d $FAULTATTR ]; then
82	echo $FAILCMD_TYPE is not available >&2
83	exit 1
84fi
85
86LONGOPTS=probability:,interval:,times:,space:,verbose:,task-filter:
87LONGOPTS=$LONGOPTS,stacktrace-depth:,require-start:,require-end:
88LONGOPTS=$LONGOPTS,reject-start:,reject-end:,oom-kill-allocating-task:,help
89
90if [ $FAILCMD_TYPE = failslab ]; then
91	LONGOPTS=$LONGOPTS,ignore-gfp-wait:,cache-filter:
92elif [ $FAILCMD_TYPE = fail_page_alloc ]; then
93	LONGOPTS=$LONGOPTS,ignore-gfp-wait:,ignore-gfp-highmem:,min-order:
94fi
95
96TEMP=`getopt -o p:i:t:s:v:h --long $LONGOPTS -n 'failcmd.sh' -- "$@"`
97
98if [ $? != 0 ]; then
99	usage
100	exit 1
101fi
102
103eval set -- "$TEMP"
104
105fault_attr_default()
106{
107	echo N > $FAULTATTR/task-filter
108	echo 0 > $FAULTATTR/probability
109	echo 1 > $FAULTATTR/times
110}
111
112fault_attr_default
113
114oom_kill_allocating_task_saved=`cat /proc/sys/vm/oom_kill_allocating_task`
115
116restore_values()
117{
118	fault_attr_default
119	echo $oom_kill_allocating_task_saved \
120		> /proc/sys/vm/oom_kill_allocating_task
121}
122
123#
124# Default options
125#
126declare -i oom_kill_allocating_task=1
127declare task_filter=Y
128declare -i probability=1
129declare -i times=1
130
131while true; do
132	case "$1" in
133	-p|--probability)
134		probability=$2
135		shift 2
136		;;
137	-i|--interval)
138		echo $2 > $FAULTATTR/interval
139		shift 2
140		;;
141	-t|--times)
142		times=$2
143		shift 2
144		;;
145	-s|--space)
146		echo $2 > $FAULTATTR/space
147		shift 2
148		;;
149	-v|--verbose)
150		echo $2 > $FAULTATTR/verbose
151		shift 2
152		;;
153	--task-filter)
154		task_filter=$2
155		shift 2
156		;;
157	--stacktrace-depth)
158		echo $2 > $FAULTATTR/stacktrace-depth
159		shift 2
160		;;
161	--require-start)
162		echo $2 > $FAULTATTR/require-start
163		shift 2
164		;;
165	--require-end)
166		echo $2 > $FAULTATTR/require-end
167		shift 2
168		;;
169	--reject-start)
170		echo $2 > $FAULTATTR/reject-start
171		shift 2
172		;;
173	--reject-end)
174		echo $2 > $FAULTATTR/reject-end
175		shift 2
176		;;
177	--oom-kill-allocating-task)
178		oom_kill_allocating_task=$2
179		shift 2
180		;;
181	--ignore-gfp-wait)
182		echo $2 > $FAULTATTR/ignore-gfp-wait
183		shift 2
184		;;
185	--cache-filter)
186		echo $2 > $FAULTATTR/cache_filter
187		shift 2
188		;;
189	--ignore-gfp-highmem)
190		echo $2 > $FAULTATTR/ignore-gfp-highmem
191		shift 2
192		;;
193	--min-order)
194		echo $2 > $FAULTATTR/min-order
195		shift 2
196		;;
197	-h|--help)
198		usage
199		exit 0
200		shift
201		;;
202	--)
203		shift
204		break
205		;;
206	esac
207done
208
209[ -z "$1" ] && exit 0
210
211echo $oom_kill_allocating_task > /proc/sys/vm/oom_kill_allocating_task
212echo $task_filter > $FAULTATTR/task-filter
213echo $probability > $FAULTATTR/probability
214echo $times > $FAULTATTR/times
215
216trap "restore_values" SIGINT SIGTERM EXIT
217
218cmd="echo 1 > /proc/self/make-it-fail && exec $@"
219bash -c "$cmd"
220