lkml.org 
[lkml]   [2015]   [Sep]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
From
SubjectTest program: check if fsync() can detect I/O error (2/2)
Date
On 09/15/15 17:39, Jun'ichi Nomura wrote:
>> However if admins run a command such as sync or fsfreeze along side,
>> fsync/fdatasync may return success even if writeback has failed.
>> That could lead to data corruption.
>
> For reproducing the problem, compile the attached C program (iogen.c)
> and run with 'runtest.sh' script in the next mail:
> # gcc -o iogen iogen.c
> # bash ./runtest.sh

-- cut here --
#!/bin/bash

# preparation for hwpoison injection
export KERNEL_SRC=/lib/modules/$(uname -r)/build
[ -d "$KERNEL_SRC" ] || exit 1 # no kernel source given
make vm -C $KERNEL_SRC/tools || exit 1 # tools/vm failed to build
pagetypes=$KERNEL_SRC/tools/vm/page-types
[ -x $pagetypes ] || exit 1
modprobe hwpoison-inject

# -------------------------------------------------------------------
fstype=ext4

# file name of loopback image
loopfile=test.img
imgsize=16M
lodev=/dev/loop0

# filesystem to use
mkfs=mkfs.$fstype

# device-mapper map name
testmap=testmap

# file name to store device-mapper table data
mapok=testmap.ok
maperr=testmap.err

# mount point and file name used for testing
testdir=/mnt/test
testfile=$testdir/x

# test file size
filesize=16384

# -------------------------------------------------------------------
# Set up
#

endtest() {
sleep 3
umount $testdir
dmsetup remove $testmap
losetup -d $lodev
exit
}

# Create loopback device for testing
dd if=/dev/zero of=$loopfile bs=$imgsize count=1
losetup $lodev $loopfile || endtest
if [ ! -b $lodev ]; then
endtest
fi


# Layer DM device for error injection
echo "0 $(blockdev --getsz $lodev) linear $lodev 0" | dmsetup create $testmap
dmsetup table $testmap > $mapok || endtest
if [ ! -b /dev/mapper/$testmap ]; then
endtest
fi

# Mount and create target file
mkdir -p $testdir
$mkfs /dev/mapper/$testmap
mount /dev/mapper/$testmap $testdir || endtest
dd if=/dev/zero of=$testfile bs=$filesize count=1 oflag=direct || endtest

# Find physical location of the target file
find_location() {
# pick up physical block number of file offset 0
filefrag -v $1 | \
awk '$1 == "0" {print $3} $1 == "0:" {print $4}' | \
sed 's/\.//g'
}
filefrag -v $testfile
block=$(find_location $testfile)
if [ -z "$block" ]; then
endtest
fi
blocksize=$(stat -c %s -f $testfile)
secsize=512
sector=$((block * blocksize / secsize + 1))

# Create error mapping: inject error at $sector
next=$((sector + 1))
total=$(blockdev --getsz $lodev)
remainder=$((total - next))
cat <<EOF > $maperr
0 $sector linear $lodev 0
$sector 1 error
$next $remainder linear $lodev $next
EOF

map_replace() {
cat $1 | dmsetup load $testmap
dmsetup suspend --nolockfs $testmap
dmsetup resume $testmap
}

inject_memory_error() {
local pfn=0x$($pagetypes -f $testfile -Nl | grep ^1$'\t' | cut -f2)
[ "$pfn" = 0x ] && return 1 # target pfn not found
$pagetypes -a $pfn -X -N
}

# -------------------------------------------------------------------
# Test
#

msg() {
echo $* > /dev/kmsg
echo $*
}

injector_ioerr_nop() {
# start
read x
msg "TEST: $fstype / ioerr / (no admin action)"

# inject
read x
msg "(admin): Injecting I/O error"
map_replace $maperr
msg "(admin): Do nothing"

# remove
read x
map_replace $mapok

# end
read x
umount /dev/mapper/$testmap || endtest
mount /dev/mapper/$testmap $testdir || endtest
}

injector_ioerr_synccmd() {
# start
read x
msg "TEST: $fstype / ioerr / sync-command"

# inject
read x
msg "(admin): Injecting I/O error"
map_replace $maperr
msg "(admin): Calling sync(2)"
sync

# remove
read x
map_replace $mapok

# end
read x
umount /dev/mapper/$testmap || endtest
mount /dev/mapper/$testmap $testdir || endtest
}

injector_hwpoison_synccmd() {
# start
read x
msg "TEST: $fstype / memory-error / sync-command"

# inject
read x
msg "(admin): Injecting memory error"
inject_memory_error
msg "(admin): Calling sync(2)"
sync

# remove
read x

# end
read x
umount /dev/mapper/$testmap || endtest
mount /dev/mapper/$testmap $testdir || endtest
}

msg '============'
./iogen $testfile $filesize | injector_ioerr_nop
msg '============'
./iogen $testfile $filesize | injector_ioerr_synccmd
msg '============'
./iogen $testfile $filesize | injector_hwpoison_synccmd

# -------------------------------------------------------------------
# Clean up
#
endtest


\
 
 \ /
  Last update: 2015-09-15 12:21    [W:1.935 / U:0.440 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site