The SINGLE_DEV btrfs feature allows to mount the same filesystem multiple times, at the same time. This is the fstests counter-part, which checks both mkfs/btrfstune (by mounting the FS twice), and also unsupported scenarios, like device replace / remove. Suggested-by: Josef Bacik <josef@xxxxxxxxxxxxxx> Signed-off-by: Guilherme G. Piccoli <gpiccoli@xxxxxxxxxx> --- Hi folks, this test was a suggestion by Josef for the SINGLE_DEV feature we're trying to introduce in the kernel [0]. Some design decisions: (a) The number 300 was selected since seems we already skipped 298 in the code base, given that the test btrfs/298 is being worked upstream. (b) About mounting twice the same filesystem - how to accomplish that in a proper fashion? I went with the naive / trivial approach, just created temporary directories on top of $SCRATCH_MNT, but I'm not sure if that is the way to go. Is it guaranteed that $SCRATCH_MNT is writable prior to any mount command? (c) The way to be sure we have two different devices holding the same image was using SCRATCH_DEV_POOL and dd'ing the first device to the 2nd one - is there any better alternative than this one? Suggestions / reviews much appreciated! Cheers, Guilherme [0] https://lore.kernel.org/linux-btrfs/20230803154453.1488248-1-gpiccoli@xxxxxxxxxx/ tests/btrfs/300 | 107 ++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/300.out | 5 +++ 2 files changed, 112 insertions(+) create mode 100755 tests/btrfs/300 create mode 100644 tests/btrfs/300.out diff --git a/tests/btrfs/300 b/tests/btrfs/300 new file mode 100755 index 000000000000..120e790906ea --- /dev/null +++ b/tests/btrfs/300 @@ -0,0 +1,107 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2023 Guilherme G. Piccoli (Igalia S.L.). All Rights Reserved. +# +# FS QA Test 300 +# +# Test for the btrfs single-dev feature - both mkfs and btrfstune are +# validated, as well as explicitly unsupported commands, like device +# removal / replacement. +# +. ./common/preamble +_begin_fstest auto mkfs quick +. ./common/filter +_supported_fs btrfs + +_require_btrfs_mkfs_feature single-dev +_require_btrfs_fs_feature single_dev + +_require_scratch_dev_pool 2 +_scratch_dev_pool_get 2 + +_require_command "$BTRFS_TUNE_PROG" btrfstune +_require_command "$WIPEFS_PROG" wipefs + +# Used random hash to avoid name collision. +DIR_a="563b01de1f_a" +DIR_b="563b01de1f_b" + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* + rm -rf $SCRATCH_MNT/$DIR_a + rm -rf $SCRATCH_MNT/$DIR_b +} + +# Helper to mount a btrfs fs +# Arg 1: device +# Arg 2: mount point +mount_btrfs() +{ + $MOUNT_PROG -t btrfs $1 $2 + [ $? -ne 0 ] && _fail "mounting $1 on $2 failed" +} + +mkdir $SCRATCH_MNT/$DIR_a +mkdir $SCRATCH_MNT/$DIR_b + +DEV1=$(echo $SCRATCH_DEV_POOL | $AWK_PROG '{ print $1 }') +DEV2=$(echo $SCRATCH_DEV_POOL | $AWK_PROG '{ print $2 }') + + +# Part 1 +# First test involves a mkfs with single-dev feature enabled. +# If it succeeds and mounting that FS *twice* also succeeds, +# we're good and continue. +$WIPEFS_PROG -a $DEV1 >> $seqres.full 2>&1 +$WIPEFS_PROG -a $DEV2 >> $seqres.full 2>&1 + +$MKFS_BTRFS_PROG -O single-dev $DEV1 >>$seqres.full 2>&1 +dd if=$DEV1 of=$DEV2 bs=64M conv=fsync >> $seqres.full 2>&1 + +mount_btrfs $DEV1 $SCRATCH_MNT/$DIR_a +mount_btrfs $DEV2 $SCRATCH_MNT/$DIR_b + +$UMOUNT_PROG $SCRATCH_MNT/$DIR_b +$UMOUNT_PROG $SCRATCH_MNT/$DIR_a + + +# Part 2 +# Second test is similar to the first with the difference we +# run mkfs with no single-dev mention, and make use of btrfstune +# to set such feature. +$WIPEFS_PROG -a $DEV1 >> $seqres.full 2>&1 +$WIPEFS_PROG -a $DEV2 >> $seqres.full 2>&1 + +$MKFS_BTRFS_PROG $DEV1 >>$seqres.full 2>&1 +$BTRFS_TUNE_PROG --convert-to-single-device $DEV1 +dd if=$DEV1 of=$DEV2 bs=64M conv=fsync >> $seqres.full 2>&1 + +mount_btrfs $DEV1 $SCRATCH_MNT/$DIR_a +mount_btrfs $DEV2 $SCRATCH_MNT/$DIR_b + +$UMOUNT_PROG $SCRATCH_MNT/$DIR_b +$UMOUNT_PROG $SCRATCH_MNT/$DIR_a + + +# Part 3 +# Final part attempts to run some single-dev unsupported commands, +# like device replace/remove - it they fail, test succeeds! +mount_btrfs $DEV1 $SCRATCH_MNT + +$BTRFS_UTIL_PROG device replace start $DEV1 $DEV1 $SCRATCH_MNT 2>&1 \ + | _filter_scratch + +$BTRFS_UTIL_PROG device remove $DEV1 $SCRATCH_MNT 2>&1 \ + | sed -e "s,\B$DEV1,DEV1,g" + +$UMOUNT_PROG $SCRATCH_MNT +_scratch_dev_pool_put 2 + +# success, all done +status=0 +echo "Finished" + +exit diff --git a/tests/btrfs/300.out b/tests/btrfs/300.out new file mode 100644 index 000000000000..5f13cfb228fb --- /dev/null +++ b/tests/btrfs/300.out @@ -0,0 +1,5 @@ +QA output created by 300 +ERROR: ioctl(DEV_REPLACE_STATUS) failed on "SCRATCH_MNT": Invalid argument + +ERROR: error removing device 'DEV1': Invalid argument +Finished -- 2.41.0