From 73576ea71e1aae3f74fb844f5dec13d2ef2d0560 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Thu, 14 Jun 2018 14:30:53 +0800 Subject: [PATCH] btrfs: test if btrfs will corrupt nodatasum compressed extent when replacing device This is a long existing bug (from 2012) but exposed by a reporter recently, that when compressed extent without data csum get written to device-replace target device, the written data is in fact uncompressed data other than the original compressed data. And since btrfs still consider the data is compressed and will try to read it as compressed, it can cause read error. This is fixed by kernel commit ac0b4145d662 ("btrfs: scrub: Don't use inode pages for device replace") Reported-by: James Harvey Reviewed-by: Nikolay Borisov Signed-off-by: Qu Wenruo Signed-off-by: Eryu Guan --- tests/btrfs/167 | 76 +++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/167.out | 2 ++ tests/btrfs/group | 1 + 3 files changed, 79 insertions(+) create mode 100755 tests/btrfs/167 create mode 100644 tests/btrfs/167.out diff --git a/tests/btrfs/167 b/tests/btrfs/167 new file mode 100755 index 00000000..3b66dff2 --- /dev/null +++ b/tests/btrfs/167 @@ -0,0 +1,76 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2018 SUSE Linux Products GmbH. All Rights Reserved. +# +# FS QA Test 167 +# +# Test if btrfs will corrupt compressed data extent without data csum +# by replacing it with uncompressed data, when doing device replace. +# +# This could be fixed by the following kernel commit: +# ac0b4145d662 ("btrfs: scrub: Don't use inode pages for device replace") +# +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + rm -f $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter + +# remove previous $seqres.full before test +rm -f $seqres.full + +# real QA test starts here + +# Modify as appropriate. +_supported_fs btrfs +_supported_os Linux +_require_scratch_dev_pool 2 +_require_scratch_dev_pool_equal_size + +_scratch_dev_pool_get 1 +_spare_dev_get +_scratch_pool_mkfs >> $seqres.full 2>&1 + +# Create nodatasum inode +_scratch_mount "-o nodatasum" +touch $SCRATCH_MNT/nodatasum_file +_scratch_remount "datasum,compress" +_pwrite_byte 0xcd 0 128K $SCRATCH_MNT/nodatasum_file > /dev/null + +# Write the compressed data back to disk +sync + +# Replace the device +_run_btrfs_util_prog replace start -Bf 1 $SPARE_DEV $SCRATCH_MNT + +# Unmount to drop all cache so next read will read from disk +_scratch_unmount +_mount $SPARE_DEV $SCRATCH_MNT + +# Now the EXTENT_DATA item still marks the extent as compressed, +# but the on-disk data is uncompressed, thus reading it as compressed +# will definitely cause EIO. +cat $SCRATCH_MNT/nodatasum_file > /dev/null + +_scratch_unmount +_spare_dev_put +_scratch_dev_pool_put + +echo "Silence is golden" + +# success, all done +status=0 +exit diff --git a/tests/btrfs/167.out b/tests/btrfs/167.out new file mode 100644 index 00000000..a668597d --- /dev/null +++ b/tests/btrfs/167.out @@ -0,0 +1,2 @@ +QA output created by 167 +Silence is golden diff --git a/tests/btrfs/group b/tests/btrfs/group index e68aa1b7..5cff3bd6 100644 --- a/tests/btrfs/group +++ b/tests/btrfs/group @@ -169,3 +169,4 @@ 164 auto quick volume 165 auto quick subvol 166 auto quick qgroup +167 auto quick replace volume -- 2.30.2