fio: update FSF address
[fio.git] / tools / genfio
index efc87a29514c72a48c54ff75baa1092c6c919e38..286d814de71506c0c187dd4a6b530b446b54e9b7 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/bash
 #
 #  Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #  Author: Erwan Velu  <erwan@enovance.com>
@@ -17,7 +17,7 @@
 #
 #  You should have received a copy of the GNU General Public License
 #  along with this program; if not, write to the Free Software
-#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
 BLK_SIZE=
 BLOCK_SIZE=4k
@@ -25,80 +25,123 @@ SEQ=-1
 TEMPLATE=/tmp/template.fio
 OUTFILE=
 DISKS=
+PRINTABLE_DISKS=
 RUNTIME=300
 ETA=0
-MODES="read,write,randread,randwrite"
+MODES="write,randwrite,read,randread"
 SHORT_HOSTNAME=
+CACHED_IO="FALSE"
+PREFIX=""
+PREFIX_FILENAME=""
+IODEPTH=1
 
 show_help() {
        PROG=$(basename $0)
        echo "usage of $PROG:"
        cat << EOF
 -h                             : Show this help & exit
+-c                             : Enable cached-based IOs
+                                       Disabled by default
 -a                             : Run sequential test then parallel one
+                                       Disabled by default
 -s                             : Run sequential test (default value)
                                        one test after another then one disk after another
+                                       Disabled by default
 -p                             : Run parallel test
                                        one test after anoter but all disks at the same time
+                                       Enabled by default
+-D iodepth                     : Run with the specified iodepth
+                                       Default is $IODEPTH
 -d disk1[,disk2,disk3,..]      : Run the tests on the selected disks
                                        Separated each disk with a comma
-                                       Disk name shall be "sdxx", /dev/ shall NOT be used here
--r seconds                     : Time in seconds per benchmark (300 as default)
+-z filesize                     : Specify the working file size, if you are passing filepaths to -d
+                                        Disabled by default
+-r seconds                     : Time in seconds per benchmark
                                        0 means till the end of the device
+                                       Default is $RUNTIME seconds
 -b blocksize[,blocksize1, ...]  : The blocksizes to test under fio format (4k, 1m, ...)
                                        Separated each blocksize with a comma
+                                       Default is $BLOCK_SIZE
 -m mode1,[mode2,mode3, ...]     : Define the fio IO profile to use like read, write, randread, randwrite
+                                       Default is "$MODES"
+-x prefix                      : Add a prefix to the fio filename
+                                       Useful to let a context associated with the file
+                                       If the prefix features a / (slash), prefix will be considered as a directory
+-A cmd_to_run                  : System command to run after each job (exec_postrun in fio)
+-B cmd_to_run                  : System command to run before each job (exec_prerun in fio)
 
 Example:
 
-$PROG -d sdb,sdc,sdd,sde -a -b 4k,128k,1m -r 100 -a
+$PROG -d /dev/sdb,/dev/sdc,/dev/sdd,/dev/sde -a -b 4k,128k,1m -r 100 -a -x dellr720-day2/
 
        Will generate an fio file that will run
-               - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 4k with read,write,randread,randwrite tests
+               - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 4k with write,randwrite,read,randread tests
                        ETA ~ 4 tests * 4 disks * 100 seconds
-               - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 128k with read,write,randread,randwrite tests
+               - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 128k with write,randwrite,read,randread tests
                        ETA ~ 4 tests * 4 disks * 100 seconds
-               - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 1m with read,write,randread,randwrite tests
+               - a sequential bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 1m with write,randwrite,read,randread tests
                        ETA ~ 4 tests * 4 disks * 100 seconds
-               - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 4k with read,write,randread,randwrite tests
+               - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 4k with write,randwrite,read,randread tests
                        ETA ~ 4 tests * 100 seconds
-               - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 128k with read,write,randread,randwrite tests
+               - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 128k with write,randwrite,read,randread tests
                        ETA ~ 4 tests * 100 seconds
-               - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 1m with read,write,randread,randwrite tests
+               - a parallel bench on /dev/sdb /dev/sdc /dev/sdd /dev/sde for block size = 1m with write,randwrite,read,randread tests
                        ETA ~ 4 tests * 100 seconds
 
-Generating localhost-4k,128k,1m-all-read,write,randread,randwrite-sdb,sdc,sdd,sde.fio
+Generating dellr720-day2/localhost-4k,128k,1m-all-write,randwrite,read,randread-sdb,sdc,sdd,sde.fio
 Estimated Time = 6000 seconds : 1 hour 40 minutes
 EOF
 }
 
+finish_template() {
+echo "iodepth=$IODEPTH" >> $TEMPLATE
+
+if [ "$RUNTIME" != "0" ]; then
+       echo "runtime=$RUNTIME" >> $TEMPLATE
+       echo "time_based" >> $TEMPLATE
+fi
+
+if [ "$CACHED_IO" = "FALSE" ]; then
+       echo "direct=1" >> $TEMPLATE
+fi
+}
+
+
+diskname_to_printable() {
+COUNT=0
+for disk in $(echo $@ | tr "," " "); do
+       R=$(basename $disk | sed 's|/|_|g')
+       COUNT=$(($COUNT + 1))
+       if [ $COUNT -eq 1 ]; then
+               P="$R"
+       else
+               P="$P,$R"
+       fi
+done
+echo $P
+}
+
 gen_template() {
 cat >$TEMPLATE << EOF
 [global]
 ioengine=libaio
 invalidate=1
 ramp_time=5
-direct=1
-EOF
-
-if [ "$RUNTIME" != "0" ]; then
-cat >>$TEMPLATE << EOF
-runtime=$RUNTIME
 EOF
-fi
-
 }
 
 gen_seq_suite() {
 TYPE=$1
+disk=$2
+PRINTABLE_DISK=$(diskname_to_printable $disk)
 cat >> $OUTFILE << EOF
-[$TYPE-$disk-$BLK_SIZE-seq]
+[$TYPE-$PRINTABLE_DISK-$BLK_SIZE-seq]
 stonewall
 bs=$BLK_SIZE
-filename=/dev/$disk
+filename=$disk
 rw=$TYPE
-write_bw_log=$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-seq.results
-write_iops_log=$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-seq.results
+write_bw_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$PRINTABLE_DISK-$TYPE-seq.results
+write_iops_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$PRINTABLE_DISK-$TYPE-seq.results
 EOF
 ETA=$(($ETA + $RUNTIME))
 }
@@ -106,7 +149,7 @@ ETA=$(($ETA + $RUNTIME))
 gen_seq_fio() {
 for disk in $(echo $DISKS | tr "," " "); do
        for mode in $(echo $MODES | tr "," " "); do
-               gen_seq_suite "$mode"
+               gen_seq_suite "$mode" "$disk"
        done
 done
 }
@@ -117,8 +160,9 @@ TYPE=$1
 NEED_WALL=$2
 D=0
 for disk in $(echo $DISKS | tr "," " "); do
+    PRINTABLE_DISK=$(diskname_to_printable $disk)
     cat >> $OUTFILE << EOF
-[$TYPE-$disk-$BLK_SIZE-para]
+[$TYPE-$PRINTABLE_DISK-$BLK_SIZE-para]
 bs=$BLK_SIZE
 EOF
 
@@ -128,10 +172,10 @@ if [ "$D" = 0 ]; then
 fi
 
 cat >> $OUTFILE << EOF
-filename=/dev/$disk
+filename=$disk
 rw=$TYPE
-write_bw_log=$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-para.results
-write_iops_log=$SHORT_HOSTNAME-$BLK_SIZE-$disk-$TYPE-para.results
+write_bw_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$PRINTABLE_DISK-$TYPE-para.results
+write_iops_log=${PREFIX_FILENAME}$SHORT_HOSTNAME-$BLK_SIZE-$PRINTABLE_DISK-$TYPE-para.results
 EOF
 done
 
@@ -161,7 +205,7 @@ esac
 }
 
 parse_cmdline() {
-while getopts "hapsd:b:r:m:" opt; do
+while getopts "hacpsd:b:r:m:x:z:D:A:B:" opt; do
   case $opt in
     h)
        show_help
@@ -170,11 +214,27 @@ while getopts "hapsd:b:r:m:" opt; do
     b)
        BLOCK_SIZE=$OPTARG
        ;;
+    c)
+       CACHED_IO="TRUE"
+       ;;
     s)
        if [ "$SEQ" = "-1" ]; then
                SEQ=1
        fi
       ;;
+    x)
+       PREFIX=$OPTARG
+       echo "$PREFIX" | grep -q "/"
+       if [ "$?" -eq 0 ]; then
+               mkdir -p $PREFIX
+               # No need to keep the prefix for the log files
+               # we do have a directory for that
+               PREFIX_FILENAME=""
+       else
+               # We need to keep the prefix for the log files
+               PREFIX_FILENAME=$PREFIX
+       fi
+       ;;
     r)
        RUNTIME=$OPTARG
       ;;
@@ -188,10 +248,24 @@ while getopts "hapsd:b:r:m:" opt; do
       ;;
     d)
        DISKS=$OPTARG
+       PRINTABLE_DISKS=$(diskname_to_printable "$DISKS")
+      ;;
+    D)
+       IODEPTH=$OPTARG
       ;;
     a)
        SEQ=2
       ;;
+    B)
+       echo "exec_prerun=$OPTARG" >> $TEMPLATE
+      ;;
+    A)
+       echo "exec_postrun=$OPTARG" >> $TEMPLATE
+      ;;
+    z)
+       FSIZE=$OPTARG
+       echo "size=$FSIZE" >> $TEMPLATE
+      ;;
     \?)
       echo "Invalid option: -$OPTARG" >&2
       ;;
@@ -205,29 +279,65 @@ fi
 SHORT_HOSTNAME=$(hostname -s)
 case $SEQ in
        2)
-               OUTFILE=$SHORT_HOSTNAME-$BLOCK_SIZE-all-$MODES-$DISKS.fio
+               OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-all-$MODES-$PRINTABLE_DISKS.fio
        ;;
 
        1)
-               OUTFILE=$SHORT_HOSTNAME-$BLOCK_SIZE-sequential-$MODES-$DISKS.fio
+               OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-sequential-$MODES-$PRINTABLE_DISKS.fio
        ;;
        0)
-               OUTFILE=$SHORT_HOSTNAME-$BLOCK_SIZE-parallel-$MODES-$DISKS.fio
+               OUTFILE=${PREFIX}$SHORT_HOSTNAME-$BLOCK_SIZE-parallel-$MODES-$PRINTABLE_DISKS.fio
        ;;
 esac
 
 if [ -z "$DISKS" ]; then
        echo "Missing DISKS !"
-       echo "Exiting !"
+       echo "Please read the help !"
+       show_help
        exit 1
 fi
 
 }
 
+check_mode_order() {
+FOUND_WRITE="NO"
+CAUSE="You are reading data before writing them          "
+
+# If no write occurs, let's show a different message
+echo $MODES | grep -q "write"
+if [ "$?" -ne 0 ]; then
+       CAUSE="You are reading data while never wrote them before"
+fi
+
+for mode in $(echo $MODES | tr "," " "); do
+       echo $mode | grep -q write
+       if [ "$?" -eq 0 ]; then
+               FOUND_WRITE="YES"
+       fi
+       echo $mode | grep -q "read"
+       if [ "$?" -eq 0 ]; then
+               if [ "$FOUND_WRITE" = "NO" ]; then
+                       echo "###############################################################"
+                       echo "# Warning : $CAUSE#"
+                       echo "# On some storage devices, this could lead to invalid results #"
+                       echo "#                                                             #"
+                       echo "# Press Ctrl-C to adjust pattern order if you have doubts     #"
+                       echo "# Or Wait 5 seconds before the file will be created           #"
+                       echo "###############################################################"
+                       sleep 5
+                       # No need to try showing the message more than one time
+                       return
+               fi
+       fi
+done
+}
+
 
 ########## MAIN
-parse_cmdline $@
 gen_template
+parse_cmdline "$@"
+finish_template
+check_mode_order
 
 echo "Generating $OUTFILE"
 cp -f $TEMPLATE $OUTFILE
@@ -238,7 +348,7 @@ for BLK_SIZE in $(echo $BLOCK_SIZE | tr "," " "); do
 done
 ETA_H=$(($ETA / 3600))
 ETA_M=$((($ETA - ($ETA_H*3600)) / 60))
-if [ "$ETA_M" = "0" ]; then
+if [ "$ETA" = "0" ]; then
        echo "Cannot estimate ETA as RUNTIME=0"
 else
        echo "Estimated Time = $ETA seconds : $ETA_H hour $ETA_M minutes"