All of lore.kernel.org
 help / color / mirror / Atom feed
From: Boris Burkov <boris@bur.io>
To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, fstests@vger.kernel.org
Subject: [PATCH] btrfs: add test for shifting devt
Date: Thu, 29 Feb 2024 10:36:41 -0800	[thread overview]
Message-ID: <27bad2e06121a6cd5cb34146e37b8e2dc46dec0c.1709231457.git.boris@bur.io> (raw)

---
 common/config       |   1 +
 common/rc           |   4 ++
 tests/btrfs/303     | 127 ++++++++++++++++++++++++++++++++++++++++++++
 tests/btrfs/303.out |   2 +
 4 files changed, 134 insertions(+)
 create mode 100755 tests/btrfs/303
 create mode 100644 tests/btrfs/303.out

diff --git a/common/config b/common/config
index a3b15b96f..43b517fda 100644
--- a/common/config
+++ b/common/config
@@ -235,6 +235,7 @@ 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)
+export PARTED_PROG="$(type -P parted)"
 
 # use 'udevadm settle' or 'udevsettle' to wait for lv to be settled.
 # newer systems have udevadm command but older systems like RHEL5 don't.
diff --git a/common/rc b/common/rc
index 30c44dddd..8e009aca9 100644
--- a/common/rc
+++ b/common/rc
@@ -5375,6 +5375,10 @@ _require_unshare() {
 		_notrun "unshare $*: command not found, should be in util-linux"
 }
 
+_require_parted() {
+	$PARTED_PROG --list &>/dev/null || _notrun "parted: command not found"
+}
+
 # Return a random file in a directory. A directory is *not* followed
 # recursively.
 _random_file() {
diff --git a/tests/btrfs/303 b/tests/btrfs/303
new file mode 100755
index 000000000..dece3eacc
--- /dev/null
+++ b/tests/btrfs/303
@@ -0,0 +1,127 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2024 Meta, Inc. All Rights Reserved.
+#
+# FS QA Test 303
+#
+# Test an edge case of multi device volume management in btrfs.
+# If a device changes devt between mounts of a multi device fs, we can trick
+# btrfs into mounting the same device twice fully (not as a bind mount). From
+# there, it is trivial to induce corruption.
+#
+. ./common/preamble
+_begin_fstest auto quick volume
+
+# Override the default cleanup function.
+# _cleanup()
+# {
+# 	cd /
+# 	rm -r -f $tmp.*
+# }
+
+# Import common functions.
+# . ./common/filter
+
+# real QA test starts here
+
+# Modify as appropriate.
+_supported_fs btrfs
+_require_test
+_require_parted
+
+#BARE_MOUNT_PROG=$here/src/bare-mount
+
+_cleanup() {
+	cd /
+	umount $MNT
+	umount $BIND
+	losetup -d $DEV0
+	losetup -d $DEV1
+	losetup -d $DEV2
+	rm $IMG0
+	rm $IMG1
+	rm $IMG2
+}
+
+do_mkpart() {
+	local dev=$1
+	$PARTED_PROG $dev 'mkpart mypart 1M 100%' --script
+}
+
+do_rmpart() {
+	local dev=$1
+	$PARTED_PROG $dev 'rm 1' --script
+}
+
+# Prepare 3 loop devices on the test device
+IMG0=$TEST_DIR/$$.img0
+IMG1=$TEST_DIR/$$.img1
+IMG2=$TEST_DIR/$$.img2
+truncate -s 1G $IMG0
+truncate -s 1G $IMG1
+truncate -s 1G $IMG2
+DEV0=$(losetup -f $IMG0 --show)
+DEV1=$(losetup -f $IMG1 --show)
+DEV2=$(losetup -f $IMG2 --show)
+D0P1=$DEV0"p1"
+D1P1=$DEV1"p1"
+MNT=$TEST_DIR/mnt
+BIND=$TEST_DIR/bind
+
+# Setup partition table with one partition on each device
+$PARTED_PROG $DEV0 'mktable gpt' --script
+$PARTED_PROG $DEV1 'mktable gpt' --script
+do_mkpart $DEV0
+do_mkpart $DEV1
+
+# mkfs with two devices to avoid clearing devices on close
+# single raid to allow removing DEV2
+$MKFS_BTRFS_PROG -f -msingle -dsingle $D0P1 $DEV2 &>/dev/null
+
+# Cycle mount the two device fs to populate both devices into the
+# stale device cache
+mkdir -p $MNT
+mount $D0P1 $MNT
+umount $MNT
+
+# Swap the partition dev_ts. This leaves the dev_t in the cache out of date.
+do_rmpart $DEV0
+do_rmpart $DEV1
+do_mkpart $DEV1
+do_mkpart $DEV0
+
+# Mount with mismatched dev_t!
+mount $D0P1 $MNT || _fail "failed to remount; don't proceed and do dangerous stuff on raw mount point"
+
+# Remove extra device to bring temp-fsid back in the fray
+$BTRFS_UTIL_PROG device remove $DEV2 $MNT
+
+# Create the should be bind mount
+mkdir -p $BIND
+mount $D0P1 $BIND
+mount_show=$($BTRFS_UTIL_PROG filesystem show $MNT)
+bind_show=$($BTRFS_UTIL_PROG filesystem show $BIND)
+# If they're different, we are in trouble.
+[ "$mount_show" = "$bind_show" ] || echo "$mount_show != $bind_show"
+
+# now prove it by corrupting it
+for i in $(seq 20); do
+	# TODO diff prog
+	dd if=/dev/urandom of=$MNT/foo.$i bs=50M count=1 &>/dev/null
+done
+for i in $(seq 20); do
+	# TODO diff prog
+	dd if=/dev/urandom of=$BIND/foo.$i bs=50M count=1 &>/dev/null
+done
+sync
+find $BIND -type f -delete
+sync
+$FSTRIM_PROG $BIND
+sleep 5
+echo 3 > /proc/sys/vm/drop_caches
+$BTRFS_UTIL_PROG scrub start -B $MNT >>$seqres.full 2>&1
+
+# success, all done
+echo "Silence is golden"
+status=0
+exit
diff --git a/tests/btrfs/303.out b/tests/btrfs/303.out
new file mode 100644
index 000000000..d48808e60
--- /dev/null
+++ b/tests/btrfs/303.out
@@ -0,0 +1,2 @@
+QA output created by 303
+Silence is golden
-- 
2.43.0


             reply	other threads:[~2024-02-29 18:35 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-29 18:36 Boris Burkov [this message]
2024-02-29 23:32 ` [PATCH] btrfs: add test for shifting devt Boris Burkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=27bad2e06121a6cd5cb34146e37b8e2dc46dec0c.1709231457.git.boris@bur.io \
    --to=boris@bur.io \
    --cc=fstests@vger.kernel.org \
    --cc=kernel-team@fb.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.