#!/bin/sh # # (c) evil@g-house.de, All rights reversed ;) # # # There are lies, damn lies and benchmarks... # # We'll try to provide a nice wrapper for these benchmarks: # - bonnie++ # - iozone # - tiobench # # We'll test these filesystems: # - ext3 # - jfs # - xfs # - reiserfs # - reiser4 # # We'll test several crypto algorithms # (via loop-aes: http://loop-aes.sf.net) # - aes128 # - twofish128 # - serpent128 # (no blowfish encryption, as it needs single-key only setup) # # v0.1.0, 02/2005 - inital release, based on some older attempts of # mine to provide a generic "bench wrapper" # v0.2.0 - still debug() hooks all over the place, but it's all in # good shape. # v0.2.1 - don't remove keyfile/passphrase too soon # - move old results to old/ # v0.2.2 - fix JFS error # - use "set -x" for better debugging # v0.2.3 - clean up our results, so that it is actually usable. # v0.2.4 - minor output format fixes # v0.2.5 - added support for Reiser4 # v0.2.6 - make lo_prealloc a command-line argument (used for loop.ko) # - lots of minor clean-ups # - added global SIZE parameter # v0.2.7 - not all versions of gnupg support --passphrase-file, use # --passphrase-fd instead # - abort if missing program files are missing (loop-aes-utils!) # v0.2.8 - redirect benchmark stdout and stderr to its proper places # - fix error handling when we try to create a JFS on a file # - fix sanity-checks logic # - indenting is still a mess :( # - /dev/loop/5 -> /dev/loop5 # - added -F flag to force program run # - make lo_prealloc a constant again # v.0.2.9 - minor cleanups, fixed breakage when checking for missing # binaries (which still needs surgery) # # ######################### BEGIN CONFIG ##################################### LANG="C" PATH="/bin:/usr/bin:/sbin:/usr/sbin" # devicefile to test. all data on this will be erased! DEV="/dev/sda6" # mountpoint for the device (NO TRAILING SLASH!) DIR="/mnt/bench" # results go in... RESULTS="/root/benchmark_results" # turn on for debugging, unset for normal use # DEBUG=echo # the filesystems to test #FS="ext3 jfs reiser4 reiserfs xfs" FS="ext3 jfs reiserfs xfs" # the algorithm to test with, space seperated #ALG="aes128 serpent128 twofish128 none" ALG="aes128" # the benchmarks to run #BM="bonnie tiobench generic iozone" BM="bonnie tiobench generic" # filesize in MB to test SIZE="2048" # which loopdevice to use # (no need to change this) LOOP="/dev/loop5" # temporary files for gpg key and passphrase. security is NOT an issue here. PWFILE=/tmp/.cryptobench_pass KEYFILE=/tmp/.cryptobench_key ######################### END CONFIG ####################################### ######################### BEGIN FUNCTIONS ################################## # routines to the mkfs derivatives m_ext2 () { $DEBUG mkfs.ext2 -Fq $1 MOUNTOPTIONS="-o noatime" } m_ext3 () { $DEBUG mkfs.ext3 -Fq $1 MOUNTOPTIONS="-o noatime,data=ordered" # data=... # - journal -> journal first, then data # - ordered -> data first, then journal (default) # - writeback -> journal first, data anytime after this (fastest) } m_jfs () { $DEBUG mkfs.jfs -q $1 1>/dev/null MOUNTOPTIONS="-o noatime,integrity" } m_xfs () { $DEBUG mkfs.xfs -fq $1 MOUNTOPTIONS="-o noatime" # osyncisdsync - Make writes to files opened with the O_SYNC flag set behave # as if the O_DSYNC flag had been used instead } m_reiserfs () { $DEBUG mkreiserfs -qff $1 1>/dev/null MOUNTOPTIONS="-o noatime,notail" # no_unhashed_relocation - Tunes the block allocator # noborder - Disable the border allocator algorithm } m_reiser4 () { $DEBUG /sbin/mkfs.reiser4 -yf $1 1>/dev/null MOUNTOPTIONS="-o noatime" } # what to do before the benchmark b_pre () { # DEBUG! #set -x $DEBUG dmesg -n1 $DEBUG mount $MOUNTOPTIONS -t "$i" "$1" "$DIR" $DEBUG dmesg -n7 #set +x } # benchmarks... b_bonnie () { if [ -x "`which bonnie++`" ]; then $DEBUG mkdir -p $DIR/bonnie 1>/dev/null $DEBUG chown -R nobody:nogroup $DIR/bonnie 1>/dev/null $DEBUG bonnie++ -f -s "$SIZE"m -r 0 -n 100:10240:10 -m $i-$j -u nobody:nogroup -q -d $DIR/bonnie 1> $RESULTS/bonnie-$i-$j.csv 2>>$RESULTS/error_bonnie.log else echo "Bonnie++ skipped!" fi } b_tiobench () { # tiobench.pl makes use of tiotest! if [ -x "`which tiotest`" ]; then $DEBUG mkdir -p $DIR/tiobench 1>/dev/null $DEBUG chown -R nobody:nogroup $DIR/tiobench 1>/dev/null $DEBUG tiobench --identifier $i-$j --size "$SIZE" --numruns 1 --dir $DIR/tiobench 1> $RESULTS/tiobench-$i-$j.txt 2>>$RESULTS/error_tiobench.log else echo "Tiobench skipped!" fi } b_iozone () { if [ -x "`which /usr/sbin/iozone`" ]; then $DEBUG mkdir -p $DIR/iozone 1>/dev/null $DEBUG chown -R nobody:nogroup $DIR/iozone 1>/dev/null $DEBUG iozone -b $RESULTS/iozone-$i-$j.xls -s "$SIZE"m -f $DIR/iozone/iozone.img 1> $RESULTS/iozone-$i-$j.txt 2>>$RESULTS/error_iozone.log else echo "IoZone skipped!" fi } b_generic () { # FIXME: move to config-section! TARBALL="/root/trash/linux-2.6.12.tar.bz2" $DEBUG mkdir -p $DIR/generic/tarball 1>/dev/null $DEBUG cp $TARBALL $DIR/generic/linux.tar.bz2 cd $DIR/generic 1>/dev/null /usr/bin/time -f "TAR -xjf @ $i-$j: %e real,%U user,%S sys" $DEBUG tar -xjf linux.tar.bz2 -C tarball/ 2> $RESULTS/generic-$i-$j.txt $DEBUG sync 1>/dev/null /usr/bin/time -f "FIND . @ $i-$j: %e real,%U user,%S sys" $DEBUG find tarball 1>/dev/null 2>> $RESULTS/generic-$i-$j.txt $DEBUG sync 1>/dev/null /usr/bin/time -f "CP @ $i-$j: %e real,%U user,%S sys" $DEBUG cp -a tarball tarball_copy 1>/dev/null 2>> $RESULTS/generic-$i-$j.txt $DEBUG sync 1>/dev/null /usr/bin/time -f "RM -rf @ $i-$j: %e real,%U user,%S sys" $DEBUG rm -rf tarball 1>/dev/null 2>> $RESULTS/generic-$i-$j.txt $DEBUG sync 1>/dev/null /usr/bin/time -f "DD "$SIZE"MB to disk @ $i-$j: %e real,%U user,%S sys" $DEBUG \ dd if=/dev/zero of=test.img bs=1M count="$SIZE" 1>/dev/null 2>> $RESULTS/generic-$i-$j.txt $DEBUG sync 1>/dev/null /usr/bin/time -f "DD "$SIZE"MB from disk @ $i-$j: %e real,%U user,%S sys" $DEBUG \ dd if=test.img of=/dev/null bs=1M count="$SIZE" 1>/dev/null 2>> $RESULTS/generic-$i-$j.txt $DEBUG sync 1>/dev/null cd $HOME && $DEBUG rm -rf $DIR/generic } # what to do after the benchmark b_post () { $DEBUG sync 1>/dev/null $DEBUG sleep 5s 1>/dev/null $DEBUG umount $DIR echo "" } # routines to setup loop-aes s_crypto_pre () { #if [ ! -b $LOOP ]; then $DEBUG dmesg -n1 $DEBUG rmmod loop_blowfish loop_serpent loop_twofish loop 2>/dev/null $DEBUG modprobe loop lo_prealloc="$PREALLOC" # 125 is the default for module in `echo loop_blowfish loop_serpent loop_twofish`; do $DEBUG modprobe $module done $DEBUG dmesg -n7 #fi # setup password and keyfile echo "Pd1eXapMJk0XAJnNSIzE" > $PWFILE # head -c 2925 /dev/urandom | uuencode -m - | head -n 66 | tail -n 65 | gpg -q --passphrase-file $PWFILE --symmetric -a > $KEYFILE head -c 2925 /dev/urandom | uuencode -m - | head -n 66 | tail -n 65 | gpg -q --passphrase-fd 3 --symmetric -a > $KEYFILE 3<$PWFILE } # attach loop-device s_crypto () { $DEBUG losetup -p 3 -e $j -K $KEYFILE $LOOP $DEV 3<$PWFILE } # detach loop-device s_crypto_post () { $DEBUG losetup -d $LOOP 2>/dev/null } ######################### END FUNCTIONS #################################### ######################### BEGIN PROGRAM #################################### # full path required, because we want to publish the program later on if [ ! "`echo "$0" | grep ^\/`" ]; then echo "Please specify the full path to "$0"!" exit 1 fi ########### # lo_prealloc is not a variable for now as it does not matter that much. # be careful when you re-enable the tuneable, because $1 is used for "-F" too. # lo_prealloc, for further infos read ch9 of: # http://loop-aes.sourceforge.net/loop-AES.README # #if [ -z "$1" ]; then # echo "Please specify the lo_prealloc parameter for loop.ko, e.g. $0 250" # exit 1 #else # PREALLOC="$1" PREALLOC="125" # <-- 125 pages is the default #fi ########### # don't reuse old (key)files, symlink attacks are out there, dude! if [ -f $KEYFILE -o -f $PWFILE ]; then echo "$KEYFILE and/or $PWFILE still exist, please delete them!" exit 1 fi # do you really...? if [ "$1" = "-F" -o "$2" = "-F" ]; then echo "Execution forced with -F!" else echo -n "This procedure will delete everything on $DEV, continue? (Yes|No) " && read "a" if [ ! "$a" = "Yes" ]; then echo "Aborted on your request" exit 1 fi fi # more sanity checks... /sbin/losetup -a > /dev/null 2>&1 || (echo "Please install loop-aes-utils" && exit 1) if [ ! -x "`which uuencode 2>/dev/null`" -o ! -x "`which tiobench 2>/dev/null`" -o ! -x "`which bonnie++ 2>/dev/null`" ]; then echo "One or more of the following packages are missing:" echo " - sharutils" echo " - tiobench" echo " - bonnie++" exit 1 fi # check if DEV or LOOP is mounted if [ -n "`mount | grep $DEV`" -o -n "`mount | grep $LOOP`" ]; then echo "" && echo "" echo "Something went wrong!" echo "$DEV or $LOOP is mounted, please fix this before running this script again." echo "" exit 1 else echo "Beginning tests..." fi # create $DIR $DEBUG mkdir -pm 0755 $DIR 1>/dev/null $DEBUG mkdir -pm 0755 $RESULTS/old 1>/dev/null $DEBUG rm -rf $RESULTS/old/* 1>/dev/null $DEBUG mv $RESULTS/* $RESULTS/old >/dev/null 2>&1 # gather some information about the system we're running on prior any benchmarks echo "**** DMESG ****" > $RESULTS/dmesg && dmesg >> $RESULTS/dmesg echo "" >> $RESULTS/dmesg echo "###########################################################" >> $RESULTS/dmesg echo "**** LSMOD ****" >> $RESULTS/dmesg && lsmod >> $RESULTS/dmesg echo "**** PREALLOC *" >> $RESULTS/dmesg && echo "PREALLOC: $PREALLOC" >> $RESULTS/dmesg echo "" >> $RESULTS/dmesg echo "###########################################################" >> $RESULTS/dmesg echo "**** CPU ****" >> $RESULTS/dmesg && cat /proc/cpuinfo >> $RESULTS/dmesg echo "" >> $RESULTS/dmesg echo "###########################################################" >> $RESULTS/dmesg echo "**** memory: `free -tm`" >> $RESULTS/dmesg $DEBUG cp /proc/config* $RESULTS/ # the test routine will be processed like this: # - create fs # - no crypto -> run benchmarks # - crypto -> run benchmarks # - create next fs # - ... # setup loop-aes (only done once) if [ -n "$ALG" ]; then s_crypto_pre else echo "loop-aes is NOT used!" fi # create every fs for i in $FS; do echo "##################### $i #####################" m_$i $DEV # run every benchmark (no crypto) for j in $BM; do echo "##################### $i / $j " b_pre $DEV STATUS="$?" # if something goes wrong, STATUS will (probably) know... # execute benchmark only, if mounting was successful if [ "`grep $DIR /proc/mounts`" -o "$DEBUG" -a "$STATUS" = 0 ]; then b_$j else echo "Something went wrong prior benchmarking $i-$j" fi # clean up b_post done # attach loop-devices, make/mount filesystems for j in $ALG; do s_crypto_post # detach loop-device (just to be sure) s_crypto $j m_$i $LOOP # run every benchmark (loop-aes) for k in $BM; do echo "" echo "##################### $i / $k - $j " b_pre $LOOP # execute benchmark only, if mounting was successful if [ "`grep $DIR /proc/mounts`" -o "$DEBUG" ]; then b_$k else echo "Something went wrong upon benchmarking $i-$j-$k" fi # clean up b_post done s_crypto_post done echo "" done # info echo "**** e2fsprogs: `fsck.ext2 -V 2>&1 | head -n1`" >> $RESULTS/info echo "**** jfsutils: `fsck.jfs -V | head -n1`" >> $RESULTS/info echo "**** xfsprogs: `xfs_repair -V`" >> $RESULTS/info echo "**** reiserfsprogs: `fsck.reiserfs -V 2>&1 | head -n1`" >> $RESULTS/info echo "**** reiser4progs: `/sbin/fsck.reiser4 -V 2>&1 | head -n1`" >> $RESULTS/info echo "**** mount: `mount -V`" >> $RESULTS/info echo "**** bonnie: `bonnie++ 2>&1 | grep -i version`" >> $RESULTS/info echo "**** tiobench: `tiotest -h | grep ^tiotest`" >> $RESULTS/info echo "**** iozone:`iozone -v | grep Version`" >> $RESULTS/info # results cd $RESULTS $DEBUG mkdir -p public 1>/dev/null for i in generic-*-*; do echo && echo "##### $i" && cat "$i"|grep -v records; done > public/generic.txt for i in tiobench-*-*.txt; do grep "Sequential Reads" -A5 $i; done >> public/tiobench.txt && echo "#############" >> public/tiobench.txt for i in tiobench-*-*.txt; do grep "Random Reads" -A5 $i; done >> public/tiobench.txt && echo "#############" >> public/tiobench.txt for i in tiobench-*-*.txt; do grep "Sequential Writes" -A5 $i; done >> public/tiobench.txt && echo "#############" >> public/tiobench.txt for i in tiobench-*-*.txt; do grep "Random Writes" -B1 -A5 $i; done >> public/tiobench.txt cat bonnie-* | bon_csv2html > public/bonnie.html $DEBUG mkdir public/raw $DEBUG mv *.txt *.csv public/raw $DEBUG mv config.gz dmesg info public/ $DEBUG cp "$0" public/bench.sh.txt # clean up $DEBUG rm -f $PWFILE $KEYFILE $DEBUG losetup -d $LOOP > /dev/null 2>&1 ######################### BEGIN PROGRAM #################################### ######################### APPENDIX ######################################### # # Some notes about the -p option of "losetup", as pointed out by # Jari Ruusu : # # > Wrong! -p option reads password from _open_ file descriptor 26, where # > 0 is stdin, 1 is stdout, 2 is stderr, and so on. Pointing -p option to # > unopen fd is equivalent to empty password. # > # > Maybe you intended to do something like this: # > # > losetup -k 128 -p 3 -e serpent /dev/loop6 /dev/sdb2 3