t/nvmept_trim: increase transfer size for some tests
[fio.git] / tools / genfio
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
22 BLK_SIZE=
23 BLOCK_SIZE=4k
24 SEQ=-1
25 TEMPLATE=$(mktemp "${TMPDIR:-${TEMP:-/tmp}}/template.fio.XXXXXX") || exit $?
26 trap 'rm -f "$TEMPLATE"' EXIT
27 OUTFILE=
28 DISKS=
29 PRINTABLE_DISKS=
30 RUNTIME=300
31 ETA=0
32 MODES="write,randwrite,read,randread"
33 SHORT_HOSTNAME=
34 CACHED_IO="FALSE"
35 PREFIX=""
36 PREFIX_FILENAME=""
37 IODEPTH=1
38
39 show_help() {
40         PROG=$(basename $0)
41         echo "usage of $PROG:"
42         cat << EOF
43 -h                              : Show this help & exit
44 -c                              : Enable cached-based IOs
45                                         Disabled by default
46 -a                              : Run sequential test then parallel one
47                                         Disabled by default
48 -s                              : Run sequential test (default value)
49                                         one test after another then one disk after another
50                                         Disabled by default
51 -p                              : Run parallel test
52                                         one test after another but all disks at the same time
53                                         Enabled by default
54 -D iodepth                      : Run with the specified iodepth
55                                         Default is $IODEPTH
56 -d disk1[,disk2,disk3,..]       : Run the tests on the selected disks
57                                         Separated each disk with a comma
58 -z filesize                     : Specify the working file size, if you are passing filepaths to -d
59                                         Disabled by default
60 -r seconds                      : Time in seconds per benchmark
61                                         0 means till the end of the device
62                                         Default is $RUNTIME seconds
63 -b blocksize[,blocksize1, ...]  : The blocksizes to test under fio format (4k, 1m, ...)
64                                         Separated each blocksize with a comma
65                                         Default is $BLOCK_SIZE
66 -m mode1,[mode2,mode3, ...]     : Define the fio IO profile to use like read, write, randread, randwrite
67                                         Default is "$MODES"
68 -x prefix                       : Add a prefix to the fio filename
69                                         Useful to let a context associated with the file
70                                         If the prefix features a / (slash), prefix will be considered as a directory
71 -A cmd_to_run                   : System command to run after each job (exec_postrun in fio)
72 -B cmd_to_run                   : System command to run before each job (exec_prerun in fio)
73
74 Example:
75
76 $PROG -d /dev/sdb,/dev/sdc,/dev/sdd,/dev/sde -a -b 4k,128k,1m -r 100 -a -x dellr720-day2/
77
78         Will generate an fio file that will run
79                 - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 4k with write,randwrite,read,randread tests
80                         ETA ~ 4 tests * 4 disks * 100 seconds
81                 - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 128k with write,randwrite,read,randread tests
82                         ETA ~ 4 tests * 4 disks * 100 seconds
83                 - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 1m with write,randwrite,read,randread tests
84                         ETA ~ 4 tests * 4 disks * 100 seconds
85                 - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 4k with write,randwrite,read,randread tests
86                         ETA ~ 4 tests * 100 seconds
87                 - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 128k with write,randwrite,read,randread tests
88                         ETA ~ 4 tests * 100 seconds
89                 - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 1m with write,randwrite,read,randread tests
90                         ETA ~ 4 tests * 100 seconds
91
92 Generating dellr720-day2/localhost-4k,128k,1m-all-write,randwrite,read,randread-sdb,sdc,sdd,sde.fio
93 Estimated Time = 6000 seconds : 1 hour 40 minutes
94 EOF
95 }
96
97 finish_template() {
98 echo "iodepth=$IODEPTH" >> $TEMPLATE
99
100 if [ "$RUNTIME" != "0" ]; then
101         echo "runtime=$RUNTIME" >> $TEMPLATE
102         echo "time_based" >> $TEMPLATE
103 fi
104
105 if [ "$CACHED_IO" = "FALSE" ]; then
106         echo "direct=1" >> $TEMPLATE
107 fi
108 }
109
110
111 diskname_to_printable() {
112 COUNT=0
113 for disk in $(echo $@ | tr "," " "); do
114         R=$(basename $disk | sed 's|/|_|g')
115         COUNT=$(($COUNT + 1))
116         if [ $COUNT -eq 1 ]; then
117                 P="$R"
118         else
119                 P="$P,$R"
120         fi
121 done
122 echo $P
123 }
124
125 gen_template() {
126 cat >$TEMPLATE << EOF
127 [global]
128 ioengine=libaio
129 invalidate=1
130 ramp_time=5
131 EOF
132 }
133
134 gen_seq_suite() {
135 TYPE=$1
136 disk=$2
137 PRINTABLE_DISK=$(diskname_to_printable $disk)
138 cat >> $OUTFILE << EOF
139 [$TYPE-$PRINTABLE_DISK-$BLK_SIZE-seq]
140 stonewall
141 bs=$BLK_SIZE
142 filename=$disk
143 rw=$TYPE
144 write_bw_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$PRINTABLE_DISK-$TYPE-seq.results
145 write_iops_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$PRINTABLE_DISK-$TYPE-seq.results
146 EOF
147 ETA=$(($ETA + $RUNTIME))
148 }
149
150 gen_seq_fio() {
151 for disk in $(echo $DISKS | tr "," " "); do
152         for mode in $(echo $MODES | tr "," " "); do
153                 gen_seq_suite "$mode" "$disk"
154         done
155 done
156 }
157
158
159 gen_para_suite() {
160 TYPE=$1
161 NEED_WALL=$2
162 D=0
163 for disk in $(echo $DISKS | tr "," " "); do
164     PRINTABLE_DISK=$(diskname_to_printable $disk)
165     cat >> $OUTFILE << EOF
166 [$TYPE-$PRINTABLE_DISK-$BLK_SIZE-para]
167 bs=$BLK_SIZE
168 EOF
169
170 if [ "$D" = 0 ]; then
171     echo "stonewall" >> $OUTFILE
172     D=1
173 fi
174
175 cat >> $OUTFILE << EOF
176 filename=$disk
177 rw=$TYPE
178 write_bw_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$PRINTABLE_DISK-$TYPE-para.results
179 write_iops_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$PRINTABLE_DISK-$TYPE-para.results
180 EOF
181 done
182
183 ETA=$(($ETA + $RUNTIME))
184 echo >> $OUTFILE
185 }
186
187 gen_para_fio() {
188 for mode in $(echo $MODES | tr "," " "); do
189         gen_para_suite "$mode"
190 done
191 }
192
193 gen_fio() {
194 case $SEQ in
195         2)
196                 gen_seq_fio
197                 gen_para_fio
198         ;;
199         1)
200                 gen_seq_fio
201         ;;
202         0)
203                 gen_para_fio
204         ;;
205 esac
206 }
207
208 parse_cmdline() {
209 while getopts "hacpsd:b:r:m:x:z:D:A:B:" opt; do
210   case $opt in
211     h)
212         show_help
213         exit 0
214         ;;
215     b)
216         BLOCK_SIZE=$OPTARG
217         ;;
218     c)
219         CACHED_IO="TRUE"
220         ;;
221     s)
222         if [ "$SEQ" = "-1" ]; then
223                 SEQ=1
224         fi
225       ;;
226     x)
227         PREFIX=$OPTARG
228         echo "$PREFIX" | grep -q "/"
229         if [ "$?" -eq 0 ]; then
230                 mkdir -p $PREFIX
231                 # No need to keep the prefix for the log files
232                 # we do have a directory for that
233                 PREFIX_FILENAME=""
234         else
235                 # We need to keep the prefix for the log files
236                 PREFIX_FILENAME=$PREFIX
237         fi
238         ;;
239     r)
240         RUNTIME=$OPTARG
241       ;;
242     p)
243         if [ "$SEQ" = "-1" ]; then
244                 SEQ=0
245         fi
246       ;;
247     m)
248         MODES=$OPTARG;
249       ;;
250     d)
251         DISKS=$OPTARG
252         PRINTABLE_DISKS=$(diskname_to_printable "$DISKS")
253       ;;
254     D)
255         IODEPTH=$OPTARG
256       ;;
257     a)
258         SEQ=2
259       ;;
260     B)
261         echo "exec_prerun=$OPTARG" >> $TEMPLATE
262       ;;
263     A)
264         echo "exec_postrun=$OPTARG" >> $TEMPLATE
265       ;;
266     z)
267         FSIZE=$OPTARG
268         echo "size=$FSIZE" >> $TEMPLATE
269       ;;
270     \?)
271       echo "Invalid option: -$OPTARG" >&2
272       ;;
273   esac
274 done
275
276 if [ "$SEQ" = "-1" ]; then
277         SEQ=0
278 fi
279
280 SHORT_HOSTNAME=$(hostname -s)
281 case $SEQ in
282         2)
283                 OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-all-$MODES-$PRINTABLE_DISKS.fio
284         ;;
285
286         1)
287                 OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-sequential-$MODES-$PRINTABLE_DISKS.fio
288         ;;
289         0)
290                 OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-parallel-$MODES-$PRINTABLE_DISKS.fio
291         ;;
292 esac
293
294 if [ -z "$DISKS" ]; then
295         echo "Missing DISKS !"
296         echo "Please read the help !"
297         show_help
298         exit 1
299 fi
300
301 }
302
303 check_mode_order() {
304 FOUND_WRITE="NO"
305 CAUSE="You are reading data before writing them          "
306
307 # If no write occurs, let's show a different message
308 echo $MODES | grep -q "write"
309 if [ "$?" -ne 0 ]; then
310         CAUSE="You are reading data while never wrote them before"
311 fi
312
313 for mode in $(echo $MODES | tr "," " "); do
314         echo $mode | grep -q write
315         if [ "$?" -eq 0 ]; then
316                 FOUND_WRITE="YES"
317         fi
318         echo $mode | grep -q "read"
319         if [ "$?" -eq 0 ]; then
320                 if [ "$FOUND_WRITE" = "NO" ]; then
321                         echo "###############################################################"
322                         echo "# Warning : $CAUSE#"
323                         echo "# On some storage devices, this could lead to invalid results #"
324                         echo "#                                                             #"
325                         echo "# Press Ctrl-C to adjust pattern order if you have doubts     #"
326                         echo "# Or Wait 5 seconds before the file will be created           #"
327                         echo "###############################################################"
328                         sleep 5
329                         # No need to try showing the message more than one time
330                         return
331                 fi
332         fi
333 done
334 }
335
336
337 ########## MAIN
338 gen_template
339 parse_cmdline "$@"
340 finish_template
341 check_mode_order
342
343 echo "Generating $OUTFILE"
344 cp -f $TEMPLATE $OUTFILE
345 echo >> $OUTFILE
346
347 for BLK_SIZE in $(echo $BLOCK_SIZE | tr "," " "); do
348         gen_fio
349 done
350 ETA_H=$(($ETA / 3600))
351 ETA_M=$((($ETA - ($ETA_H*3600)) / 60))
352 if [ "$ETA" = "0" ]; then
353         echo "Cannot estimate ETA as RUNTIME=0"
354 else
355         echo "Estimated Time = $ETA seconds : $ETA_H hour $ETA_M minutes"
356 fi