2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved.
5 # FS QA Test No. btrfs/088
7 # Test that btrfs' transaction abortion does not corrupt a filesystem mounted
8 # with -o discard nor allows a subsequent fstrim to corrupt the filesystem
9 # (regardless of being mounted with or without -o discard).
11 # This issue was fixed by the following linux kernel patch:
13 # Btrfs: fix fs corruption on transaction abort if device supports discard
14 # (commit 678886bdc6378c1cbd5072da2c5a3035000214e3)
17 seqres=$RESULT_DIR/$seq
18 echo "QA output created by $seq"
21 status=1 # failure is the default!
22 trap "_cleanup; exit \$status" 0 1 2 3 15
29 # get standard environment, filters and checks
33 # real QA test starts here
36 _require_fail_make_request
38 SYSFS_BDEV=`_sysfs_dev $SCRATCH_DEV`
42 echo 100 > $DEBUGFS_MNT/fail_make_request/probability
43 echo 1000 > $DEBUGFS_MNT/fail_make_request/times
44 echo 0 > $DEBUGFS_MNT/fail_make_request/verbose
45 echo 1 > $SYSFS_BDEV/make-it-fail
50 echo 0 > $SYSFS_BDEV/make-it-fail
51 echo 0 > $DEBUGFS_MNT/fail_make_request/probability
52 echo 0 > $DEBUGFS_MNT/fail_make_request/times
57 # We will abort a btrfs transaction later, which always produces a warning in
58 # dmesg. We do not want the test to fail because of this.
61 _scratch_mkfs >>$seqres.full 2>&1
62 _scratch_mount "-o discard"
63 _require_batched_discard $SCRATCH_MNT
65 # Create a file and call sync to commit our first transaction.
66 $XFS_IO_PROG -f -c "pwrite -S 0xaa 0 1M" $SCRATCH_MNT/foo | _filter_xfs_io
69 # Create some other file, which forces a COW operation of the fs root, adding
70 # the old root location to the pinned extents list, and opens a new btrfs
72 touch $SCRATCH_MNT/bar
74 # Write to the first file to verify later that the original data extent was not
75 # a victim of a discard operation.
76 $XFS_IO_PROG -c "pwrite -S 0xbb 512K 1M" $SCRATCH_MNT/foo | _filter_xfs_io
78 # Now make sure the next transaction commit will abort and turn the fs readonly,
79 # unmount the fs, mount it again and verify we can open file foo and read its
80 # content, which should be what it had when the first transaction was committed
81 # (first call to sync), since btrfs is a COW filesystem and foo was not fsynced.
82 # Btrfs used to issue a discard operation on the extents in the pinned extents
83 # list, resulting in corruption of metadata and data, and used too to return the
84 # pinned extents to the free space caches, allowing future fstrim operations to
85 # perform a discard operation against the pinned exents. This made the fs
86 # unmountable because the btree roots that the superblock points at were written
87 # in place (by the discard operations).
90 # This sync will trigger a commit of the current transaction, which will be
91 # aborted because IO will fail for metadata extents (btree nodes/leafs).
95 touch $SCRATCH_MNT/abc >>$seqres.full 2>&1 && \
96 echo "Transaction was not aborted, filesystem is not in readonly mode"
98 # This fstrim operation should not cause discard operations to be performed
99 # against extents that were COWed, otherwise the next mount will fail since
100 # the btree roots that the superblock points at have their physical areas
101 # on disk full of zeroes.
102 $FSTRIM_PROG $SCRATCH_MNT
104 # We expect to be able to mount the fs again and have available all metadata and
105 # data that got persisted in the first transaction.
108 # We now expect file's foo content to match what it had when the first
109 # transaction was committed because the second transaction was aborted and we
111 echo "File foo content after transaction abort + remount:"
112 od -t x1 $SCRATCH_MNT/foo