4c1e710d2b2784d79bae4737d95d758920113a8d
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22 BLK_SIZE=
23 BLOCK_SIZE=4k
24 SEQ=-1
25 TEMPLATE=/tmp/template.fio
26 OUTFILE=
27 DISKS=
28 RUNTIME=300
29 ETA=0
30 MODES="write,randwrite,read,randread"
31 SHORT_HOSTNAME=
32 CACHED_IO="FALSE"
33 PREFIX=""
34 PREFIX_FILENAME=""
35 IODEPTH=1
36
37 show_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
69 Example:
70
71 $PROG -d sdb,sdc,sdd,sde -a -b 4k,128k,1m -r 100 -a -x dellr720-day2/
72
73         Will generate an fio file that will run
74                 - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 4k with write,randwrite,read,randread tests
75                         ETA ~ 4 tests * 4 disks * 100 seconds
76                 - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 128k 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 = 1m with write,randwrite,read,randread tests
79                         ETA ~ 4 tests * 4 disks * 100 seconds
80                 - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 4k with write,randwrite,read,randread tests
81                         ETA ~ 4 tests * 100 seconds
82                 - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 128k 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 = 1m with write,randwrite,read,randread tests
85                         ETA ~ 4 tests * 100 seconds
86
87 Generating dellr720-day2/localhost-4k,128k,1m-all-write,randwrite,read,randread-sdb,sdc,sdd,sde.fio
88 Estimated Time = 6000 seconds : 1 hour 40 minutes
89 EOF
90 }
91
92 gen_template() {
93 cat >$TEMPLATE << EOF
94 [global]
95 ioengine=libaio
96 iodepth=$IODEPTH
97 invalidate=1
98 ramp_time=5
99 EOF
100
101 if [ "$RUNTIME" != "0" ]; then
102 cat >>$TEMPLATE << EOF
103 runtime=$RUNTIME
104 EOF
105 fi
106
107 if [ "$CACHED_IO" = "FALSE" ]; then
108 cat >>$TEMPLATE << EOF
109 direct=1
110 EOF
111 fi
112
113 }
114
115 gen_seq_suite() {
116 TYPE=$1
117 cat >> $OUTFILE << EOF
118 [$TYPE-$disk-$BLK_SIZE-seq]
119 stonewall
120 bs=$BLK_SIZE
121 filename=/dev/$disk
122 rw=$TYPE
123 write_bw_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-seq.results
124 write_iops_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-seq.results
125 EOF
126 ETA=$(($ETA + $RUNTIME))
127 }
128
129 gen_seq_fio() {
130 for disk in $(echo $DISKS | tr "," " "); do
131         for mode in $(echo $MODES | tr "," " "); do
132                 gen_seq_suite "$mode"
133         done
134 done
135 }
136
137
138 gen_para_suite() {
139 TYPE=$1
140 NEED_WALL=$2
141 D=0
142 for disk in $(echo $DISKS | tr "," " "); do
143     cat >> $OUTFILE << EOF
144 [$TYPE-$disk-$BLK_SIZE-para]
145 bs=$BLK_SIZE
146 EOF
147
148 if [ "$D" = 0 ]; then
149     echo "stonewall" >> $OUTFILE
150     D=1
151 fi
152
153 cat >> $OUTFILE << EOF
154 filename=/dev/$disk
155 rw=$TYPE
156 write_bw_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-para.results
157 write_iops_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-para.results
158 EOF
159 done
160
161 ETA=$(($ETA + $RUNTIME))
162 echo >> $OUTFILE
163 }
164
165 gen_para_fio() {
166 for mode in $(echo $MODES | tr "," " "); do
167         gen_para_suite "$mode"
168 done
169 }
170
171 gen_fio() {
172 case $SEQ in
173         2)
174                 gen_seq_fio
175                 gen_para_fio
176         ;;
177         1)
178                 gen_seq_fio
179         ;;
180         0)
181                 gen_para_fio
182         ;;
183 esac
184 }
185
186 parse_cmdline() {
187 while getopts "hacpsd:b:r:m:x:D:" opt; do
188   case $opt in
189     h)
190         show_help
191         exit 0
192         ;;
193     b)
194         BLOCK_SIZE=$OPTARG
195         ;;
196     c)
197         CACHED_IO="TRUE"
198         ;;
199     s)
200         if [ "$SEQ" = "-1" ]; then
201                 SEQ=1
202         fi
203       ;;
204     x)
205         PREFIX=$OPTARG
206         echo "$PREFIX" | grep -q "/"
207         if [ "$?" -eq 0 ]; then
208                 mkdir -p $PREFIX
209                 # No need to keep the prefix for the log files
210                 # we do have a directory for that
211                 PREFIX_FILENAME=""
212         else
213                 # We need to keep the prefix for the log files
214                 PREFIX_FILENAME=$PREFIX
215         fi
216         ;;
217     r)
218         RUNTIME=$OPTARG
219       ;;
220     p)
221         if [ "$SEQ" = "-1" ]; then
222                 SEQ=0
223         fi
224       ;;
225     m)
226         MODES=$OPTARG;
227       ;;
228     d)
229         DISKS=$OPTARG
230       ;;
231     D)
232         IODEPTH=$OPTARG
233       ;;
234     a)
235         SEQ=2
236       ;;
237     \?)
238       echo "Invalid option: -$OPTARG" >&2
239       ;;
240   esac
241 done
242
243 if [ "$SEQ" = "-1" ]; then
244         SEQ=0
245 fi
246
247 SHORT_HOSTNAME=$(hostname -s)
248 case $SEQ in
249         2)
250                 OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-all-$MODES-$DISKS.fio
251         ;;
252
253         1)
254                 OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-sequential-$MODES-$DISKS.fio
255         ;;
256         0)
257                 OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-parallel-$MODES-$DISKS.fio
258         ;;
259 esac
260
261 if [ -z "$DISKS" ]; then
262         echo "Missing DISKS !"
263         echo "Please read the help !"
264         show_help
265         exit 1
266 fi
267
268 }
269
270 check_mode_order() {
271 FOUND_WRITE="NO"
272 CAUSE="You are reading data before writing them          "
273
274 # If no write occurs, let's show a different message
275 echo $MODES | grep -q "write"
276 if [ "$?" -ne 0 ]; then
277         CAUSE="You are reading data while never wrote them before"
278 fi
279
280 for mode in $(echo $MODES | tr "," " "); do
281         echo $mode | grep -q write
282         if [ "$?" -eq 0 ]; then
283                 FOUND_WRITE="YES"
284         fi
285         echo $mode | grep -q "read"
286         if [ "$?" -eq 0 ]; then
287                 if [ "$FOUND_WRITE" = "NO" ]; then
288                         echo "###############################################################"
289                         echo "# Warning : $CAUSE#"
290                         echo "# On some storage devices, this could lead to invalid results #"
291                         echo "#                                                             #"
292                         echo "# Press Ctrl-C to adjust pattern order if you have doubts     #"
293                         echo "# Or Wait 5 seconds before the file will be created           #"
294                         echo "###############################################################"
295                         sleep 5
296                         # No need to try showing the message more than one time
297                         return
298                 fi
299         fi
300 done
301 }
302
303
304 ########## MAIN
305 parse_cmdline $@
306 check_mode_order
307 gen_template
308
309 echo "Generating $OUTFILE"
310 cp -f $TEMPLATE $OUTFILE
311 echo >> $OUTFILE
312
313 for BLK_SIZE in $(echo $BLOCK_SIZE | tr "," " "); do
314         gen_fio
315 done
316 ETA_H=$(($ETA / 3600))
317 ETA_M=$((($ETA - ($ETA_H*3600)) / 60))
318 if [ "$ETA" = "0" ]; then
319         echo "Cannot estimate ETA as RUNTIME=0"
320 else
321         echo "Estimated Time = $ETA seconds : $ETA_H hour $ETA_M minutes"
322 fi