genfio: Don't use cat EOF for small prints
[fio.git] / tools / genfio
... / ...
CommitLineData
1#!/bin/bash
2#
3# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
4# Author: Erwan Velu <erwan@enovance.com>
5#
6# The license below covers all files distributed with fio unless otherwise
7# noted in the file itself.
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22BLK_SIZE=
23BLOCK_SIZE=4k
24SEQ=-1
25TEMPLATE=/tmp/template.fio
26OUTFILE=
27DISKS=
28RUNTIME=300
29ETA=0
30MODES="write,randwrite,read,randread"
31SHORT_HOSTNAME=
32CACHED_IO="FALSE"
33PREFIX=""
34PREFIX_FILENAME=""
35IODEPTH=1
36
37show_help() {
38 PROG=$(basename $0)
39 echo "usage of $PROG:"
40 cat << EOF
41-h : Show this help & exit
42-c : Enable cached-based IOs
43 Disabled by default
44-a : Run sequential test then parallel one
45 Disabled by default
46-s : Run sequential test (default value)
47 one test after another then one disk after another
48 Disabled by default
49-p : Run parallel test
50 one test after anoter but all disks at the same time
51 Enabled by default
52-D iodepth : Run with the specified iodepth
53 Default is 32
54-d disk1[,disk2,disk3,..] : Run the tests on the selected disks
55 Separated each disk with a comma
56 Disk name shall be "sdxx", /dev/ shall NOT be used here
57-r seconds : Time in seconds per benchmark
58 0 means till the end of the device
59 Default is 300 seconds
60-b blocksize[,blocksize1, ...] : The blocksizes to test under fio format (4k, 1m, ...)
61 Separated each blocksize with a comma
62 Default is 4k
63-m mode1,[mode2,mode3, ...] : Define the fio IO profile to use like read, write, randread, randwrite
64 Default is "write,randwrite,read,randread"
65-x prefix : Add a prefix to the fio filename
66 Useful to let a context associated with the file
67 If the prefix features a / (slash), prefix will be considered as a directory
68-A cmd_to_run : System command to run after each job (exec_postrun in fio)
69-B cmd_to_run : System command to run before each job (exec_prerun in fio)
70
71Example:
72
73$PROG -d sdb,sdc,sdd,sde -a -b 4k,128k,1m -r 100 -a -x dellr720-day2/
74
75 Will generate an fio file that will run
76 - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 4k with write,randwrite,read,randread tests
77 ETA ~ 4 tests * 4 disks * 100 seconds
78 - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 128k with write,randwrite,read,randread tests
79 ETA ~ 4 tests * 4 disks * 100 seconds
80 - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 1m with write,randwrite,read,randread tests
81 ETA ~ 4 tests * 4 disks * 100 seconds
82 - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 4k with write,randwrite,read,randread tests
83 ETA ~ 4 tests * 100 seconds
84 - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 128k with write,randwrite,read,randread tests
85 ETA ~ 4 tests * 100 seconds
86 - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 1m with write,randwrite,read,randread tests
87 ETA ~ 4 tests * 100 seconds
88
89Generating dellr720-day2/localhost-4k,128k,1m-all-write,randwrite,read,randread-sdb,sdc,sdd,sde.fio
90Estimated Time = 6000 seconds : 1 hour 40 minutes
91EOF
92}
93
94finish_template() {
95echo "iodepth=$IODEPTH" >> $TEMPLATE
96
97if [ "$RUNTIME" != "0" ]; then
98 echo "runtime=$RUNTIME" >> $TEMPLATE
99 echo "time_based" >> $TEMPLATE
100fi
101
102if [ "$CACHED_IO" = "FALSE" ]; then
103 echo "direct=1" >> $TEMPLATE
104fi
105}
106
107gen_template() {
108cat >$TEMPLATE << EOF
109[global]
110ioengine=libaio
111invalidate=1
112ramp_time=5
113EOF
114}
115
116gen_seq_suite() {
117TYPE=$1
118cat >> $OUTFILE << EOF
119[$TYPE-$disk-$BLK_SIZE-seq]
120stonewall
121bs=$BLK_SIZE
122filename=/dev/$disk
123rw=$TYPE
124write_bw_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-seq.results
125write_iops_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-seq.results
126EOF
127ETA=$(($ETA + $RUNTIME))
128}
129
130gen_seq_fio() {
131for disk in $(echo $DISKS | tr "," " "); do
132 for mode in $(echo $MODES | tr "," " "); do
133 gen_seq_suite "$mode"
134 done
135done
136}
137
138
139gen_para_suite() {
140TYPE=$1
141NEED_WALL=$2
142D=0
143for disk in $(echo $DISKS | tr "," " "); do
144 cat >> $OUTFILE << EOF
145[$TYPE-$disk-$BLK_SIZE-para]
146bs=$BLK_SIZE
147EOF
148
149if [ "$D" = 0 ]; then
150 echo "stonewall" >> $OUTFILE
151 D=1
152fi
153
154cat >> $OUTFILE << EOF
155filename=/dev/$disk
156rw=$TYPE
157write_bw_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-para.results
158write_iops_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-para.results
159EOF
160done
161
162ETA=$(($ETA + $RUNTIME))
163echo >> $OUTFILE
164}
165
166gen_para_fio() {
167for mode in $(echo $MODES | tr "," " "); do
168 gen_para_suite "$mode"
169done
170}
171
172gen_fio() {
173case $SEQ in
174 2)
175 gen_seq_fio
176 gen_para_fio
177 ;;
178 1)
179 gen_seq_fio
180 ;;
181 0)
182 gen_para_fio
183 ;;
184esac
185}
186
187parse_cmdline() {
188while getopts "hacpsd:b:r:m:x:D:A:B:" opt; do
189 case $opt in
190 h)
191 show_help
192 exit 0
193 ;;
194 b)
195 BLOCK_SIZE=$OPTARG
196 ;;
197 c)
198 CACHED_IO="TRUE"
199 ;;
200 s)
201 if [ "$SEQ" = "-1" ]; then
202 SEQ=1
203 fi
204 ;;
205 x)
206 PREFIX=$OPTARG
207 echo "$PREFIX" | grep -q "/"
208 if [ "$?" -eq 0 ]; then
209 mkdir -p $PREFIX
210 # No need to keep the prefix for the log files
211 # we do have a directory for that
212 PREFIX_FILENAME=""
213 else
214 # We need to keep the prefix for the log files
215 PREFIX_FILENAME=$PREFIX
216 fi
217 ;;
218 r)
219 RUNTIME=$OPTARG
220 ;;
221 p)
222 if [ "$SEQ" = "-1" ]; then
223 SEQ=0
224 fi
225 ;;
226 m)
227 MODES=$OPTARG;
228 ;;
229 d)
230 DISKS=$OPTARG
231 ;;
232 D)
233 IODEPTH=$OPTARG
234 ;;
235 a)
236 SEQ=2
237 ;;
238 B)
239 echo "exec_prerun=$OPTARG" >> $TEMPLATE
240 ;;
241 A)
242 echo "exec_postrun=$OPTARG" >> $TEMPLATE
243 ;;
244 \?)
245 echo "Invalid option: -$OPTARG" >&2
246 ;;
247 esac
248done
249
250if [ "$SEQ" = "-1" ]; then
251 SEQ=0
252fi
253
254SHORT_HOSTNAME=$(hostname -s)
255case $SEQ in
256 2)
257 OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-all-$MODES-$DISKS.fio
258 ;;
259
260 1)
261 OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-sequential-$MODES-$DISKS.fio
262 ;;
263 0)
264 OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-parallel-$MODES-$DISKS.fio
265 ;;
266esac
267
268if [ -z "$DISKS" ]; then
269 echo "Missing DISKS !"
270 echo "Please read the help !"
271 show_help
272 exit 1
273fi
274
275}
276
277check_mode_order() {
278FOUND_WRITE="NO"
279CAUSE="You are reading data before writing them "
280
281# If no write occurs, let's show a different message
282echo $MODES | grep -q "write"
283if [ "$?" -ne 0 ]; then
284 CAUSE="You are reading data while never wrote them before"
285fi
286
287for mode in $(echo $MODES | tr "," " "); do
288 echo $mode | grep -q write
289 if [ "$?" -eq 0 ]; then
290 FOUND_WRITE="YES"
291 fi
292 echo $mode | grep -q "read"
293 if [ "$?" -eq 0 ]; then
294 if [ "$FOUND_WRITE" = "NO" ]; then
295 echo "###############################################################"
296 echo "# Warning : $CAUSE#"
297 echo "# On some storage devices, this could lead to invalid results #"
298 echo "# #"
299 echo "# Press Ctrl-C to adjust pattern order if you have doubts #"
300 echo "# Or Wait 5 seconds before the file will be created #"
301 echo "###############################################################"
302 sleep 5
303 # No need to try showing the message more than one time
304 return
305 fi
306 fi
307done
308}
309
310
311########## MAIN
312gen_template
313parse_cmdline $@
314finish_template
315check_mode_order
316
317echo "Generating $OUTFILE"
318cp -f $TEMPLATE $OUTFILE
319echo >> $OUTFILE
320
321for BLK_SIZE in $(echo $BLOCK_SIZE | tr "," " "); do
322 gen_fio
323done
324ETA_H=$(($ETA / 3600))
325ETA_M=$((($ETA - ($ETA_H*3600)) / 60))
326if [ "$ETA" = "0" ]; then
327 echo "Cannot estimate ETA as RUNTIME=0"
328else
329 echo "Estimated Time = $ETA seconds : $ETA_H hour $ETA_M minutes"
330fi