]> www.infradead.org Git - users/hch/xfstests-dev.git/commitdiff
btrfs: add a helpers for read repair testing
authorChristoph Hellwig <hch@lst.de>
Fri, 27 May 2022 08:19:06 +0000 (10:19 +0200)
committerZorro Lang <zlang@kernel.org>
Sat, 28 May 2022 07:10:11 +0000 (15:10 +0800)
Add a few helpers to consolidate code for btrfs read repair testing:

 - _btrfs_get_first_logical() gets the btrfs logical address for the
   first extent in a file
 - _btrfs_get_device_path and _btrfs_get_physical use the
   btrfs-map-logical tool to find the device path and physical address
   for btrfs logical address for a specific mirror
 - _btrfs_direct_read_on_mirror and _btrfs_buffered_read_on_mirror
   read the data from a specific mirror

These will be used to consolidate the read repair tests and avoid
duplication for new tests.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Zorro Lang <zlang@kernel.org>
common/btrfs
common/config

index ac597ca465a1c3d39240b7e330284c42b7471c47..c7058918cecd81845727eda0359d2cfd3f927545 100644 (file)
@@ -505,3 +505,78 @@ _btrfs_metadump()
        $BTRFS_IMAGE_PROG "$device" "$dumpfile"
        [ -n "$DUMP_COMPRESSOR" ] && $DUMP_COMPRESSOR -f "$dumpfile" &> /dev/null
 }
+
+# Return the btrfs logical address for the first block in a file
+_btrfs_get_first_logical()
+{
+       local file=$1
+       _require_command "$FILEFRAG_PROG" filefrag
+
+       ${FILEFRAG_PROG} -v $file >> $seqres.full
+       ${FILEFRAG_PROG} -v $file | _filter_filefrag | cut -d '#' -f 1
+}
+
+# Find the device path for a btrfs logical offset
+_btrfs_get_device_path()
+{
+       local logical=$1
+       local stripe=$2
+
+       _require_command "$BTRFS_MAP_LOGICAL_PROG" btrfs-map-logical
+
+       $BTRFS_MAP_LOGICAL_PROG -l $logical $SCRATCH_DEV | \
+               $AWK_PROG "(\$1 ~ /mirror/ && \$2 ~ /$stripe/) { print \$8 }"
+}
+
+
+# Find the device physical sector for a btrfs logical offset
+_btrfs_get_physical()
+{
+       local logical=$1
+       local stripe=$2
+
+       _require_command "$BTRFS_MAP_LOGICAL_PROG" btrfs-map-logical
+
+       $BTRFS_MAP_LOGICAL_PROG -b -l $logical $SCRATCH_DEV >> $seqres.full 2>&1
+       $BTRFS_MAP_LOGICAL_PROG -l $logical $SCRATCH_DEV | \
+               $AWK_PROG "(\$1 ~ /mirror/ && \$2 ~ /$stripe/) { print \$6 }"
+}
+
+# Read from a specific stripe to test read recovery that corrupted a specific
+# stripe.  Btrfs uses the PID to select the mirror, so keep reading until the
+# xfs_io process that performed the read was executed with a PID that ends up
+# on the intended mirror.
+_btrfs_direct_read_on_mirror()
+{
+       local mirror=$1
+       local nr_mirrors=$2
+       local file=$3
+       local offset=$4
+       local size=$5
+
+       while [[ -z $( (( BASHPID % nr_mirrors == mirror )) &&
+               exec $XFS_IO_PROG -d \
+                       -c "pread -b $size $offset $size" $file) ]]; do
+               :
+       done
+}
+
+# Read from a specific stripe to test read recovery that corrupted a specific
+# stripe.  Btrfs uses the PID to select the mirror, so keep reading until the
+# xfs_io process that performed the read was executed with a PID that ends up
+# on the intended mirror.
+_btrfs_buffered_read_on_mirror()
+{
+       local mirror=$1
+       local nr_mirrors=$2
+       local file=$3
+       local offset=$4
+       local size=$5
+
+       echo 3 > /proc/sys/vm/drop_caches
+       while [[ -z $( (( BASHPID % nr_mirrors == mirror )) &&
+               exec $XFS_IO_PROG \
+                       -c "pread -b $size $offset $size" $file) ]]; do
+               :
+       done
+}
index 558f148bec6ae582d9a199579d211ebc8280ba71..de3aba15b146ffa3ef34ec7ddb5f032f60f41870 100644 (file)
@@ -228,6 +228,7 @@ export E2IMAGE_PROG="$(type -P e2image)"
 export BLKZONE_PROG="$(type -P blkzone)"
 export GZIP_PROG="$(type -P gzip)"
 export BTRFS_IMAGE_PROG="$(type -P btrfs-image)"
+export BTRFS_MAP_LOGICAL_PROG=$(type -P btrfs-map-logical)
 
 # use 'udevadm settle' or 'udevsettle' to wait for lv to be settled.
 # newer systems have udevadm command but older systems like RHEL5 don't.