Messages in this thread | | | From | Junichi Nomura <> | Subject | Test program: check if fsync() can detect I/O error (2/2) | Date | Tue, 15 Sep 2015 09:52:18 +0000 |
| |
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
| |