blob: d3e05b0d6d9f45206088d061f59d73f2901a7e69 [file] [log] [blame]
#!/bin/bash -x
# SPDX-License-Identifier: GPL-2.0
# Copyright(c) 2015-2017 Intel Corporation. All rights reserved.
DEV=""
NDCTL="../ndctl/ndctl"
BUS="-b nfit_test.0"
BUS1="-b nfit_test.1"
MNT=test_dax_mnt
FILE=image
json2var="s/[{}\",]//g; s/:/=/g"
rc=77
err() {
echo "test/dax-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)" ]]
}
check_min_kver "4.7" || { echo "kernel $KVER may lack dax error handling"; exit $rc; }
set -e
mkdir -p $MNT
trap 'err $LINENO' ERR
# setup (reset nfit_test dimms)
modprobe nfit_test
$NDCTL disable-region $BUS all
$NDCTL zero-labels $BUS all
$NDCTL enable-region $BUS all
rc=1
# create pmem
dev="x"
json=$($NDCTL create-namespace $BUS -t pmem -m raw)
eval $(echo $json | sed -e "$json2var")
[ $dev = "x" ] && echo "fail: $LINENO" && false
[ $mode != "raw" ] && echo "fail: $LINENO" && false
# inject errors in the middle of the namespace, verify that reading fails
err_sector="$(((size/512) / 2))"
err_count=8
$NDCTL inject-error --block="$err_sector" --count=$err_count $dev
read sector len < /sys/block/$blockdev/badblocks
[ $((sector * 2)) -ne $((size /512)) ] && echo "fail: $LINENO" && false
if dd if=/dev/$blockdev of=/dev/null iflag=direct bs=512 skip=$sector count=$len; then
echo "fail: $LINENO" && false
fi
# check that writing clears the errors
if ! dd of=/dev/$blockdev if=/dev/zero oflag=direct bs=512 seek=$sector count=$len; then
echo "fail: $LINENO" && false
fi
if read sector len < /sys/block/$blockdev/badblocks; then
# fail if reading badblocks returns data
echo "fail: $LINENO" && false
fi
#mkfs.xfs /dev/$blockdev -b size=4096 -f
mkfs.ext4 /dev/$blockdev -b 4096
mount /dev/$blockdev $MNT
# prepare an image file with random data
dd if=/dev/urandom of=$MNT/$FILE bs=4096 count=4 oflag=direct
# 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)
test -n "$start_sect"
echo "start sector of the file is $start_sect"
# inject badblocks for one page at the start of the file
echo $start_sect 8 > /sys/block/$blockdev/badblocks
# 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
# run the dax-errors test
test -x ./dax-errors
./dax-errors $MNT/$FILE
# TODO: disable this check till we have clear-on-write in the kernel
#if read sector len < /sys/block/$blockdev/badblocks; then
# # fail if reading badblocks returns data
# echo "fail: $LINENO" && false
#fi
# TODO Due to the above, we have to clear the existing badblock manually
read sector len < /sys/block/$blockdev/badblocks
if ! dd of=/dev/$blockdev if=/dev/zero oflag=direct bs=512 seek=$sector count=$len; then
echo "fail: $LINENO" && false
fi
# test that a hole punch to a dax file also clears errors
dd if=/dev/urandom of=$MNT/$FILE oflag=direct bs=4096 count=4
start_sect=$(filefrag -v -b512 $MNT/$FILE | grep -E "^[ ]+[0-9]+.*" | head -1 | awk '{ print $4 }' | cut -d. -f1)
test -n "$start_sect"
echo "holepunch test: start sector: $start_sect"
# inject a badblock at the second sector of the first page
echo $((start_sect + 1)) 1 > /sys/block/$blockdev/badblocks
# verify badblock by reading
: 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
# cleanup
rm -f $FILE
rm -f $MNT/$FILE
if [ -n "$blockdev" ]; then
umount /dev/$blockdev
fi
rmdir $MNT
$NDCTL disable-region $BUS all
$NDCTL disable-region $BUS1 all
modprobe -r nfit_test
exit 0