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