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
37 _require_fail_make_request
39 SYSFS_BDEV=`_sysfs_dev $SCRATCH_DEV`
43 echo 100 > $DEBUGFS_MNT/fail_make_request/probability
44 echo 1000 > $DEBUGFS_MNT/fail_make_request/times
45 echo 0 > $DEBUGFS_MNT/fail_make_request/verbose
46 echo 1 > $SYSFS_BDEV/make-it-fail
51 echo 0 > $SYSFS_BDEV/make-it-fail
52 echo 0 > $DEBUGFS_MNT/fail_make_request/probability
53 echo 0 > $DEBUGFS_MNT/fail_make_request/times
58 # We will abort a btrfs transaction later, which always produces a warning in
59 # dmesg. We do not want the test to fail because of this.
62 _scratch_mkfs >>$seqres.full 2>&1
63 _scratch_mount "-o discard"
64 _require_batched_discard $SCRATCH_MNT
66 # Create a file and call sync to commit our first transaction.
67 $XFS_IO_PROG -f -c "pwrite -S 0xaa 0 1M" $SCRATCH_MNT/foo | _filter_xfs_io
70 # Create some other file, which forces a COW operation of the fs root, adding
71 # the old root location to the pinned extents list, and opens a new btrfs
73 touch $SCRATCH_MNT/bar
75 # Write to the first file to verify later that the original data extent was not
76 # a victim of a discard operation.
77 $XFS_IO_PROG -c "pwrite -S 0xbb 512K 1M" $SCRATCH_MNT/foo | _filter_xfs_io
79 # Now make sure the next transaction commit will abort and turn the fs readonly,
80 # unmount the fs, mount it again and verify we can open file foo and read its
81 # content, which should be what it had when the first transaction was committed
82 # (first call to sync), since btrfs is a COW filesystem and foo was not fsynced.
83 # Btrfs used to issue a discard operation on the extents in the pinned extents
84 # list, resulting in corruption of metadata and data, and used too to return the
85 # pinned extents to the free space caches, allowing future fstrim operations to
86 # perform a discard operation against the pinned exents. This made the fs
87 # unmountable because the btree roots that the superblock points at were written
88 # in place (by the discard operations).
91 # This sync will trigger a commit of the current transaction, which will be
92 # aborted because IO will fail for metadata extents (btree nodes/leafs).
96 touch $SCRATCH_MNT/abc >>$seqres.full 2>&1 && \
97 echo "Transaction was not aborted, filesystem is not in readonly mode"
99 # This fstrim operation should not cause discard operations to be performed
100 # against extents that were COWed, otherwise the next mount will fail since
101 # the btree roots that the superblock points at have their physical areas
102 # on disk full of zeroes.
103 $FSTRIM_PROG $SCRATCH_MNT
105 # We expect to be able to mount the fs again and have available all metadata and
106 # data that got persisted in the first transaction.
109 # We now expect file's foo content to match what it had when the first
110 # transaction was committed because the second transaction was aborted and we
112 echo "File foo content after transaction abort + remount:"
113 od -t x1 $SCRATCH_MNT/foo