From f7a14619791716a90eaa881e07565d2f7fe719f6 Mon Sep 17 00:00:00 2001 From: Rod Smith Date: Fri, 15 Jul 2016 09:49:30 -0400 Subject: providers:checkbox: Added new disk_stress_ng test based on stress-ng --- bin/disk_stress_ng | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100755 bin/disk_stress_ng (limited to 'bin') diff --git a/bin/disk_stress_ng b/bin/disk_stress_ng new file mode 100755 index 0000000..73cd1ee --- /dev/null +++ b/bin/disk_stress_ng @@ -0,0 +1,238 @@ +#!/bin/bash + +# Script to disk stress tests using stress-ng +# +# Copyright (c) 2016 Canonical Ltd. +# +# Authors +# Rod Smith +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# The purpose of this script is to run disk stress tests using the +# stress-ng program. +# +# Usage: +# disk_stress_ng [ --disk-device ] +# [ --base-time ] +# [ --really-run ] +# +# Parameters: +# --disk-device -- This is the WHOLE-DISK device filename WITHOUT "/dev/" +# (e.g., sda). The script finds a filesystem on that +# device, mounts it if necessary, and runs the tests on +# that mounted filesystem. +# Test with iostat + +get_params() { + disk_device="/dev/sda" + base_time="60" + really_run="N" + while [ $# -gt 0 ] ; do + case $1 in + --disk-device) disk_device="/dev/$2" + shift + ;; + --base-time) base_time="$2" + shift + ;; + --really-run) really_run="Y" + ;; + *) echo "Usage: $0 [ --disk-device ] [ --base-time ]" + echo " [ --really-run ]" + exit 1 + ;; + esac + shift + done + disk_device=`echo $disk_device | sed "s/\/dev\/\/dev/\/dev/g"` + mounted_part="N" +} # get_params() + + +# Find the largest partition that holds a supported filesystem on $disk_device. +# Output: +# $largest_part -- Device filename of largest qualifying partition +# $largest_size -- Size of largest qualifying partition +# $largest_fs -- Filesystem (ext4, etc.) used on largest qualifying partition +# $unsupported_fs -- Empty or contains name of unsupported filesystem found on disk +find_largest_partition() { + largest_part="" + largest_size=0 + partitions=$(lsblk -b -l -n -o NAME,SIZE,TYPE,MOUNTPOINT $disk_device | grep part | tr -s " ") + unsupported_fs="" + for partition in $(echo "$partitions" | cut -d " " -f 1) ; do + part_size=$(echo "$partitions" | grep "$partition " | cut -d " " -f 2) + local blkid_info=$(blkid -s TYPE /dev/$partition | grep -E ext2\|ext3\|ext4\|xfs\|jfs\|btrfs) + if [ "$part_size" -gt "$largest_size" ] && [ -n "$blkid_info" ] ; then + largest_size=$part_size + largest_part="/dev/$partition" + largest_fs=$(blkid -s TYPE "/dev/$partition" | cut -d "=" -f 2) + fi + local blkid_info=$(blkid -s TYPE /dev/$partition | grep -E ntfs\|vfat\|hfs) + if [ -n "$blkid_info" ] ; then + # If there's an NTFS, HFS+, or FAT filesystem on the disk make note of it.... + unsupported_fs=$(blkid -s TYPE "/dev/$partition" | cut -d "=" -f 2) + fi + done +} # find_largest_partition() + +# Find the largest filesystem on $disk_device. If that partition is not +# already mounted, try to mount it. +# Output: +# $test_dir -- Directory in which tests will occur +# $mount_point -- Location where filesystem is mounted +# $mounted_part -- Sets to "Y" if script mounted partition +mount_filesystem() { + test_dir="/tmp/disk_stress_ng" + if [ -b $disk_device ] + then + echo "$disk_device is a block device" + + #Add a check for warnings + WARN=$(parted -s ${disk_device} print | grep "^Warning.*${disk}.*[Rr]ead-only" 2>&1) + if [[ $? == 0 ]] + then + echo "Warning found in parted output:" + echo $WARN + echo "Aborting Test" + exit 1 + fi + else + echo "$disk_device is not a block device! Aborting!" + exit 1 + fi + + find_largest_partition + + if [ -n "$largest_part" ] ; then + echo "Found largest partition: \"$largest_part\"" + mount_point=$(df | grep "$largest_part " | tr -s " " | cut -d " " -f 6) + if [ "$mount_point" == "" ] && [ "$really_run" == "Y" ] ; then + mount_point="/tmp/disk_stress_ng$disk_device" + echo "No partition is mounted from $disk_device; attempting to mount one...." + mkdir -p "$mount_point" + mount "$largest_part" "$mount_point" + mounted_part="Y" + fi + if [ "$mount_point" == "/" ] ; then + test_dir="/tmp/disk_stress_ng" + else + test_dir="$mount_point/tmp/disk_stress_ng" + fi + if [ "$really_run" == "Y" ] ; then + mkdir -p "$test_dir" + fi + echo "Test will use $largest_part, mounted at \"$mount_point\", using $largest_fs" + else + echo "There appears to be no partition with a suitable filesystem" + echo "on $disk_device; please create a suitable partition and re-run" + echo "this test." + if [ -n "unsupported_fs" ] ; then + echo "NOTE: A filesystem of type $unsupported_fs was found, but is not supported" + echo "by this test. A Linux-native filesystem (ext2/3/4fs, XFS, JFS, or Btrfs)" + echo "is required." + fi + exit 1 + fi +} # mount_filesystem() + + +# Run an individual stressor +# Input: +# $1 = stressor name (e.g., copyfile, dentry) +# $2 = run time +# Output: +# had_error -- sets to "1" if an error occurred +run_stressor() { + local runtime="$2" + # Multiply runtime by 5; will forcefully terminate if stress-ng + # fails to return in that time. + end_time=$((runtime*5)) + echo "Running stress-ng $1 stressor for $2 seconds...." + # Use "timeout" command to launch stress-ng, to catch it should it go into + # la-la land + timeout -s 9 $end_time stress-ng --aggressive --verify --timeout $runtime \ + --temp-path $test_dir --$1 0 + return_code="$?" + echo "return_code is $return_code" + if [ "$return_code" != "0" ] ; then + had_error=1 + echo "*****************************************************************" + if [ $return_code = "137" ] ; then + echo "** stress-ng disk test timed out and was forcefully terminated!" + else + echo "** Error $return_code reported on stressor $stressor!)" + fi + echo "*****************************************************************" + had_error=1 + result=$return_code + fi +} # run_stressor() + + +# +# Main program body.... +# + + +get_params "$@" +echo "disk_device is $disk_device" +mount_filesystem +echo "test_dir is $test_dir" + +had_error=0 + +# Tests Colin said to try but that aren't present as of standard stress-ng +# in Ubuntu 16.04: +# +# "chown" "copyfile" "ioprio" "locka" "lockofd" "madvise" "msync" "seal" +# +# TODO: Consider adding these tests for Ubuntu 18.04, or ealier with an +# updated stress-ng in the certification PPA.... + +disk_stressors=("aio" "aiol" "chdir" "chmod" "dentry" "dir" "fallocate" \ + "fiemap" "filename" "flock" "fstat" "hdd" "lease" "lockf" \ + "mknod" "readahead" "seek" "sync-file" "xattr") + +total_runtime=$((${#disk_stressors[@]}*$base_time)) + +echo "Estimated total run time is $total_runtime seconds" +echo "" + +if [ "$really_run" == "Y" ] ; then + for stressor in ${disk_stressors[@]}; do + run_stressor $stressor $base_time + done + if [ "$mounted_part" == "Y" ] ; then + umount $mount_point + fi +else + echo "To actually run tests, pass the --really-run option." + echo "Script is now terminating...." + exit 1 +fi + +# +# for stressor in ${vrt_stressors[@]}; do +# run_stressor $stressor $variable_time +# done + +echo "*******************************************************************" +if [ $had_error = "0" ] ; then + echo "** stress-ng disk test passed!" +else + echo "** stress-ng disk test failed; most recent error was $result" +fi +echo "*******************************************************************" +exit $result -- cgit v1.2.3 From 1e71c2b6d0b990edcda3fa210c2ab677c92915fd Mon Sep 17 00:00:00 2001 From: Rod Smith Date: Mon, 18 Jul 2016 13:39:37 -0400 Subject: Made changes to new disk_stress_ng script per Jeff's comments --- bin/disk_stress_ng | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) (limited to 'bin') diff --git a/bin/disk_stress_ng b/bin/disk_stress_ng index 73cd1ee..8445488 100755 --- a/bin/disk_stress_ng +++ b/bin/disk_stress_ng @@ -23,7 +23,7 @@ # stress-ng program. # # Usage: -# disk_stress_ng [ --disk-device ] +# disk_stress_ng [ ] # [ --base-time ] # [ --really-run ] # @@ -36,26 +36,29 @@ get_params() { disk_device="/dev/sda" - base_time="60" + short_device="sda" + base_time="240" really_run="N" while [ $# -gt 0 ] ; do case $1 in - --disk-device) disk_device="/dev/$2" - shift - ;; --base-time) base_time="$2" shift ;; --really-run) really_run="Y" ;; - *) echo "Usage: $0 [ --disk-device ] [ --base-time ]" - echo " [ --really-run ]" - exit 1 + *) disk_device="/dev/$1" + disk_device=`echo $disk_device | sed "s/\/dev\/\/dev/\/dev/g"` + short_device=$(echo $disk_device | sed "s/\/dev//g") + if [ ! -b $disk_device ] ; then + echo "Unknown block device \"$disk_device\"" + echo "Usage: $0 [ --base-time ] [ --really-run ]" + echo " [ device-file ]" + exit 1 + fi ;; esac shift done - disk_device=`echo $disk_device | sed "s/\/dev\/\/dev/\/dev/g"` mounted_part="N" } # get_params() @@ -93,6 +96,7 @@ find_largest_partition() { # $test_dir -- Directory in which tests will occur # $mount_point -- Location where filesystem is mounted # $mounted_part -- Sets to "Y" if script mounted partition +# $made_mountpoint -- Sets to "Y" if script created the mount point mount_filesystem() { test_dir="/tmp/disk_stress_ng" if [ -b $disk_device ] @@ -119,9 +123,13 @@ mount_filesystem() { echo "Found largest partition: \"$largest_part\"" mount_point=$(df | grep "$largest_part " | tr -s " " | cut -d " " -f 6) if [ "$mount_point" == "" ] && [ "$really_run" == "Y" ] ; then - mount_point="/tmp/disk_stress_ng$disk_device" + disk_device=$(echo $disk_device | sed "s/\/dev\/\/dev/\/dev/g") + mount_point="/mnt$short_device" echo "No partition is mounted from $disk_device; attempting to mount one...." - mkdir -p "$mount_point" + if [ ! -d $mount_point ] ; then + mkdir -p "$mount_point" + made_mountpoint="Y" + fi mount "$largest_part" "$mount_point" mounted_part="Y" fi @@ -130,9 +138,6 @@ mount_filesystem() { else test_dir="$mount_point/tmp/disk_stress_ng" fi - if [ "$really_run" == "Y" ] ; then - mkdir -p "$test_dir" - fi echo "Test will use $largest_part, mounted at \"$mount_point\", using $largest_fs" else echo "There appears to be no partition with a suitable filesystem" @@ -187,7 +192,6 @@ run_stressor() { get_params "$@" -echo "disk_device is $disk_device" mount_filesystem echo "test_dir is $test_dir" @@ -211,11 +215,16 @@ echo "Estimated total run time is $total_runtime seconds" echo "" if [ "$really_run" == "Y" ] ; then + mkdir -p "$test_dir" for stressor in ${disk_stressors[@]}; do run_stressor $stressor $base_time done + rm -rf "$test_dir" if [ "$mounted_part" == "Y" ] ; then - umount $mount_point + umount "$mount_point" + if [ "$made_mountpoint" == "Y" ] ; then + rmdir "$mount_point" + fi fi else echo "To actually run tests, pass the --really-run option." @@ -223,11 +232,6 @@ else exit 1 fi -# -# for stressor in ${vrt_stressors[@]}; do -# run_stressor $stressor $variable_time -# done - echo "*******************************************************************" if [ $had_error = "0" ] ; then echo "** stress-ng disk test passed!" -- cgit v1.2.3