diff mbox

[ndctl,v2,6/6] ndctl/test: add a new unit test for BTT error clearing

Message ID 20171013001004.14963-7-vishal.l.verma@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Verma, Vishal L Oct. 13, 2017, 12:10 a.m. UTC
The new error injection command allows us to inject errors that persist
through changing the mode of a BTT namespace to 'raw' and back. This
allows us to test error clearing with a BTT by adding a selective error
block to the raw namespace, enabling the BTT, and then clearing it via a
write.

Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 test/Makefile.am   |   3 +-
 test/btt-errors.sh | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 151 insertions(+), 1 deletion(-)
 create mode 100755 test/btt-errors.sh

Comments

Dan Williams Oct. 13, 2017, 11:12 p.m. UTC | #1
On Thu, Oct 12, 2017 at 5:10 PM, Vishal Verma <vishal.l.verma@intel.com> wrote:
> The new error injection command allows us to inject errors that persist
> through changing the mode of a BTT namespace to 'raw' and back. This
> allows us to test error clearing with a BTT by adding a selective error
> block to the raw namespace, enabling the BTT, and then clearing it via a
> write.
>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>

Nice to see this. As for the BTT details I'm going to trust you as the
BTT maintainer, but if any of those are wrong we can handle it later
with incremental fixes.
diff mbox

Patch

diff --git a/test/Makefile.am b/test/Makefile.am
index 8cec451..881fcea 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -14,7 +14,8 @@  TESTS =\
 	btt-check.sh \
 	label-compat.sh \
 	blk-exhaust.sh \
-	inject-error.sh
+	inject-error.sh \
+	btt-errors.sh
 
 check_PROGRAMS =\
 	libndctl \
diff --git a/test/btt-errors.sh b/test/btt-errors.sh
new file mode 100755
index 0000000..aec0b9d
--- /dev/null
+++ b/test/btt-errors.sh
@@ -0,0 +1,149 @@ 
+#!/bin/bash -x
+
+# Copyright(c) 2015-2017 Intel Corporation. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License 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.
+
+NDCTL="../ndctl/ndctl"
+BUS="nfit_test.0"
+MNT=test_btt_mnt
+FILE=image
+json2var="s/[{}\",]//g; s/:/=/g"
+blockdev=""
+rc=77
+
+err() {
+	rc=1
+	echo "test/btt-errors: failed at line $1"
+
+	rm -f $FILE
+	rm -f $MNT/$FILE
+	if [ -n "$blockdev" ]; then
+		umount "/dev/$blockdev"
+	else
+		rc=77
+	fi
+	rmdir $MNT
+	exit $rc
+}
+
+check_min_kver()
+{
+	local ver="$1"
+	: "${KVER:=$(uname -r)}"
+
+	[ -n "$ver" ] || return 1
+	[[ "$ver" == "$(echo -e "$ver\n$KVER" | sort -V | head -1)" ]]
+}
+
+force_raw()
+{
+	raw="$1"
+	if grep -q "$MNT" /proc/mounts; then umount $MNT; fi
+	ndctl disable-namespace "$dev"
+	echo "$raw" > "/sys/bus/nd/devices/$dev/force_raw"
+	ndctl enable-namespace "$dev"
+	echo "Set $dev to raw mode: $raw"
+	if [[ "$raw" == "1" ]]; then
+		raw_bdev=${blockdev%s}
+		test -b "/dev/$raw_bdev"
+	else
+		raw_bdev=""
+	fi
+}
+
+check_min_kver "4.14" || { echo "kernel $KVER may lack BTT error handling"; exit $rc; }
+
+set -e
+mkdir -p $MNT
+trap 'err $LINENO' ERR
+
+# setup (reset nfit_test dimms)
+modprobe nfit_test
+$NDCTL disable-region -b "$BUS" all
+$NDCTL zero-labels -b "$BUS" all
+$NDCTL enable-region -b "$BUS" all
+
+rc=1
+
+# create a btt namespace and clear errors (if any)
+dev="x"
+json=$($NDCTL create-namespace -b "$BUS" -t pmem -m sector)
+eval "$(echo "$json" | sed -e "$json2var")"
+[ $dev = "x" ] && echo "fail: $LINENO" && exit 1
+
+force_raw 1
+if read -r sector len < "/sys/block/$raw_bdev/badblocks"; then
+	dd of=/dev/$raw_bdev if=/dev/zero oflag=direct bs=512 seek="$sector" count="$len"
+fi
+force_raw 0
+
+mkfs.ext4 "/dev/$blockdev" -b 4096
+mount -o nodelalloc "/dev/$blockdev" $MNT
+
+# prepare an image file with random data
+dd if=/dev/urandom of=$FILE bs=4096 count=1
+test -s $FILE
+
+# copy it to the file system
+cp $FILE $MNT/$FILE
+
+# Get the start sector for the file
+start_sect=$(filefrag -v -b512 $MNT/$FILE | grep -E "^[ ]+[0-9]+.*" | head -1 | awk '{ print $4 }' | cut -d. -f1)
+start_4k=$((start_sect/8))
+test -n "$start_sect"
+echo "start sector of the file is: $start_sect (512B) or $start_4k (4096B)"
+
+# figure out the btt offset
+
+force_raw 1
+
+# calculate start of the map
+map=$(hexdump -s 96 -n 4 "/dev/$raw_bdev" | head -1 | cut -d' ' -f2-)
+map=$(tr -d ' ' <<< "0x${map#* }${map%% *}")
+printf "btt map starts at: %x\n" "$map"
+
+# calculate map entry byte offset for the file's block
+map_idx=$((map + (4 * start_4k)))
+printf "btt map entry location for sector %x: %x\n" "$start_4k" "$map_idx"
+
+# read the map entry
+map_ent=$(hexdump -s $map_idx -n 4 "/dev/$raw_bdev" | head -1 | cut -d' ' -f2-)
+map_ent=$(tr -d ' ' <<< "0x${map_ent#* }${map_ent%% *}")
+map_ent=$((map_ent & 0x3fffffff))
+printf "btt map entry: 0x%x\n" "$map_ent"
+
+# calculate the data offset
+dataoff=$(((map_ent * 4096) + 4096))
+printf "dataoff: 0x%x\n" "$dataoff"
+
+bb_inj=$((dataoff/512))
+
+# inject badblocks for one page at the start of the file
+$NDCTL inject-error --block="$bb_inj" --count=8 $dev
+
+force_raw 0
+mount -o nodelalloc "/dev/$blockdev" $MNT
+
+# make sure reading the first block of the file fails as expected
+: The following 'dd' is expected to hit an I/O Error
+dd if=$MNT/$FILE of=/dev/null iflag=direct bs=4096 count=1 && err $LINENO || true
+
+# write via btt to clear the error
+dd if=/dev/zero of=$MNT/$FILE oflag=direct bs=4096 count=1
+
+# read again and that should succeed
+dd if=$MNT/$FILE of=/dev/null iflag=direct bs=4096 count=1
+
+# done, exit
+$NDCTL disable-region -b "$BUS" all
+$NDCTL zero-labels -b "$BUS" all
+$NDCTL enable-region -b "$BUS" all
+exit 0