Skip to content

Commit

Permalink
block-device test added
Browse files Browse the repository at this point in the history
Test a partition on a block device.

Check that files can be written and read reliably, measure the timings
for read and write, and run the bonnie++ block device test on the
device.

Signed-off-by: Ryan Harkin <[email protected]>
  • Loading branch information
Ryan Harkin authored and mwasilew committed Apr 16, 2020
1 parent ed043b7 commit 018d4b9
Show file tree
Hide file tree
Showing 2 changed files with 300 additions and 0 deletions.
261 changes: 261 additions & 0 deletions automated/linux/block-device/block-device.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2019 Linaro Ltd.

# shellcheck disable=SC1091
. ../../lib/sh-test-lib
OUTPUT="$(pwd)/output"
RESULT_FILE="${OUTPUT}/result.txt"

PARTDEV=""
PARTNAME=""
DEVICE=""
DEVNAME=""

SKIP_INSTALL="false"
FORMAT_DEVICE="false"

MOUNT_DIR=$(mktemp -d "/tmp/block-device.XXXXX")
TMPFILE=$(mktemp "/tmp/10M.XXXXX")
RESULT=pass

usage() {
echo "\
Usage: $0
[-d </dev/sdXN>]
[-f <true|false>]
[-s <true|false>]
-d </dev/sdXN>
This is the block device to be tested, eg. /dev/sda1.
It should be a partition, not a raw block device
-f <true|false>
This will erase the device and create a new partition table
with a single ext4 partition on it.
-s <true|false>
Tell the test to skip installation of dependencies, or not
This test will perform tests on a block device.
"
}

while getopts "d:f:s:h" opts; do
case "$opts" in
d) PARTDEV="${OPTARG}";
PARTNAME=$(basename -- "${PARTDEV}");
DEVICE=${PARTDEV/%[[:digit:]]/}
DEVNAME=$(basename -- "${DEVICE}")
;;
f) FORMAT_DEVICE="${OPTARG,,}" ;;
s) SKIP_INSTALL="${OPTARG,,}" ;;
h|*) usage ; exit 1 ;;
esac
done

install() {
if [ "${SKIP_INSTALL}" = "true" ]; then
info_msg "Skip installing dependencies"
else
# install dependencies
dist=
dist_name
case "${dist}" in
debian|ubuntu)
pkgs="bonnie++"
install_deps "${pkgs}" "${SKIP_INSTALL}"
;;
fedora|centos)
pkgs="bonnie++"
install_deps "${pkgs}" "${SKIP_INSTALL}"
;;
# When we don't have a package manager
# Assume dependencies pre-installed
*)
echo "Unsupported distro: ${dist}! Package installation skipped!"
;;
esac
fi
}

block_device_exists () {
local device=$1

if [[ -b ${device} ]]; then
echo true
else
echo false
fi
}

wait_for_device () {
local device=$1
local retries=20

echo -n "Waiting for ${device}: "
for ((i=0;i<retries;++i)); do
local exists
exists=$(block_device_exists "${device}")
if [[ "${exists}" == "true" ]]; then
echo "done"
echo "block-device-${DEVNAME}-present pass" | tee -a "${RESULT_FILE}"
sleep 0.5 # allow the device some time to settle after being plugged in
return
fi
echo -n "."
sleep 0.5
done
echo "failed"
echo "block-device-preset-${DEVNAME} fail" | tee -a "${RESULT_FILE}"
exit 1
}

device_mounted() {
local dev
dev="$1"
if grep -qs "${dev}" /proc/mounts; then
echo "1"
else
echo "0"
fi
}

format_device() {
if [ "${RESULT}" != "fail" ] && [ "${FORMAT_DEVICE}" = "true" ] ; then
local mounted
mounted=$(device_mounted "${PARTDEV}")
if [ "${mounted}" = "1" ]; then
RESULT=fail
echo "block-device-${DEVNAME}-not-mounted ${RESULT}" | tee -a "${RESULT_FILE}"
return
fi
echo "block-device-${DEVNAME}-not-mounted ${RESULT}" | tee -a "${RESULT_FILE}"

if [ "${RESULT}" = "pass" ]; then
echo "Erase device ${DEVICE}"
if ! dd if=/dev/zero of="${DEVICE}" bs=512 count=2048; then
RESULT=fail
fi
fi
echo "block-device-${DEVNAME}-erase ${RESULT}" | tee -a "${RESULT_FILE}"

if [ "${RESULT}" = "pass" ]; then
echo "Create partition table on ${DEVICE}"
echo 'type=83' | sfdisk --force "${DEVICE}" || RESULT=fail
fi
echo "block-device-${DEVNAME}-partition ${RESULT}" | tee -a "${RESULT_FILE}"

if [ "${RESULT}" = "pass" ]; then
PARTDEV="${DEVICE}1"
echo "Format ${PARTDEV} as ext4"
mkfs.ext4 -F "${PARTDEV}" || RESULT=fail
fi
echo "block-device-${PARTNAME}-format ${RESULT}" | tee -a "${RESULT_FILE}"
else
echo "block-device-${PARTNAME}-format skip" | tee -a "${RESULT_FILE}"
fi
}

mount_device () {
if [ "${RESULT}" == "pass" ] ; then
local mounted
mounted=$(device_mounted "${PARTDEV}")
if [ "${mounted}" = "1" ]; then
RESULT=skip
else
mkdir -p "${MOUNT_DIR}"
mount -t auto "${PARTDEV}" "${MOUNT_DIR}" || RESULT=fail
fi
echo "block-device-${PARTNAME}-mount ${RESULT}" | tee -a "${RESULT_FILE}"
fi
}

umount_device () {
umount "${MOUNT_DIR}" || RESULT=fail
echo "block-device-${PARTNAME}-umount ${RESULT}" | tee -a "${RESULT_FILE}"
}

copy_timing_test () {
test_name=$1
infile=$2
outfile=$3

if [ "${RESULT}" == "pass" ] ; then
timings=$(mktemp "/tmp/block-device.timings.XXXXXXXXXXXX")
(dd if="${infile}" of="${outfile}" 2> "${timings}" && sync) || RESULT=fail
cat "${timings}"

if [ "${RESULT}" == "pass" ] ; then
local seconds
local mbps
seconds=$(tail -1 "${timings}" | awk '{print $8}')
mbps=$(tail -1 "${timings}" | awk '{print $10}')
echo "block-device-${PARTNAME}-${test_name}-timing ${RESULT} ${seconds} seconds" | tee -a "${RESULT_FILE}"
echo "block-device-${PARTNAME}-${test_name}-throughput ${RESULT} ${mbps} MB/s" | tee -a "${RESULT_FILE}"
fi
rm -f "${timings}"

echo "block-device-${PARTNAME}-${test_name}-cp ${RESULT}" | tee -a "${RESULT_FILE}"
fi
if [ "${RESULT}" == "pass" ] ; then
cmp "${infile}" "${outfile}" || RESULT=fail
echo "block-device-${PARTNAME}-${test_name}-cmp ${RESULT}" | tee -a "${RESULT_FILE}"
fi
}

write_timing () {
if [ "${RESULT}" == "pass" ] ; then
echo "Writing 10MB file to ${PARTDEV}"
dd if=/dev/urandom of="${TMPFILE}" bs=1024 count=10240 || RESULT=fail
echo "block-device-${PARTNAME}-create-10M-file ${RESULT}" | tee -a "${RESULT_FILE}"
fi
if [ "${RESULT}" == "pass" ] ; then
# shellcheck disable=SC2086
copy_timing_test "write" "${TMPFILE}" "${MOUNT_DIR}/$(basename -- ${TMPFILE})" || RESULT=fail
fi
rm -f "${TMPFILE}"
}

read_timing () {
if [ "${RESULT}" == "pass" ] ; then
echo "Reading 10MB file to ${PARTDEV}"
# shellcheck disable=SC2086
copy_timing_test "read" "${MOUNT_DIR}/$(basename -- ${TMPFILE})" "${TMPFILE}" || RESULT=fail
rm -f "${TMPFILE}"
fi
}

bonnie_test () {
if [ "${RESULT}" == "pass" ] ; then
BONNIE_LOG=$(mktemp "/tmp/bonnie.XXXXX")
bonnie\+\+ -u root -d "${MOUNT_DIR}" | tee -a "${BONNIE_LOG}" || RESULT=fail
echo "block-device-${PARTNAME}-bonnie++ ${RESULT}" | tee -a "${RESULT_FILE}"
fi
}

################################################################################
# Run the test actions
################################################################################
echo "Test Parameters"
echo "---------------"
echo "PARTDEV: ${PARTDEV}"
echo "PARTNAME: ${PARTNAME}"
echo "DEVICE: ${DEVICE}"
echo "RESULT_FILE: ${RESULT_FILE}"
echo ""
echo "MOUNT_DIR: ${MOUNT_DIR}"
echo "TMPFILE: ${TMPFILE}"
echo ""

install
create_out_dir "${OUTPUT}"
wait_for_device "${DEVICE}"
format_device
mount_device
write_timing
read_timing
bonnie_test
umount_device

# Cleanup temporary files
rm -f "${TMPFILE}"
rm -rf "${MOUNT_DIR}"
39 changes: 39 additions & 0 deletions automated/linux/block-device/block-device.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2019 Schneider Electric
metadata:
format: Lava-Test Test Definition 1.0
name: block-device
description: "Test a partition on a block device.
Check that files can be written and read reliably, measure the timings
for read and write, and run the bonnie++ block device test on the
device."

maintainer:
- [email protected]
os:
- debian
- ubuntu
- fedora
- centos
- openembedded
scope:
- blkdev
- bonnie++
- performance
- functional

devices:
- rzn1d
- soca9

params:
DEVICE: "/dev/sdXN"
FORMAT_DEVICE: "False"
SKIP_INSTALL: "False"

run:
steps:
- cd ./automated/linux/block-device
- ./block-device.sh -s "${SKIP_INSTALL}" -d "${DEVICE}" -f "${FORMAT_DEVICE}"
- ../../utils/send-to-lava.sh ./output/result.txt

0 comments on commit 018d4b9

Please sign in to comment.