generic/563: use a loop device to avoid partition incompatibility
[xfstests-dev.git] / tests / btrfs / 088
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved.
4 #
5 # FS QA Test No. btrfs/088
6 #
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).
10 #
11 # This issue was fixed by the following linux kernel patch:
12 #
13 #    Btrfs: fix fs corruption on transaction abort if device supports discard
14 #    (commit 678886bdc6378c1cbd5072da2c5a3035000214e3)
15 #
16 seq=`basename $0`
17 seqres=$RESULT_DIR/$seq
18 echo "QA output created by $seq"
19
20 tmp=/tmp/$$
21 status=1        # failure is the default!
22 trap "_cleanup; exit \$status" 0 1 2 3 15
23
24 _cleanup()
25 {
26         rm -f $tmp.*
27 }
28
29 # get standard environment, filters and checks
30 . ./common/rc
31 . ./common/filter
32
33 # real QA test starts here
34 _supported_fs btrfs
35 _require_scratch
36 _require_fail_make_request
37
38 SYSFS_BDEV=`_sysfs_dev $SCRATCH_DEV`
39
40 enable_io_failure()
41 {
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
46 }
47
48 disable_io_failure()
49 {
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
53 }
54
55 rm -f $seqres.full
56
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.
59 _disable_dmesg_check
60
61 _scratch_mkfs >>$seqres.full 2>&1
62 _scratch_mount "-o discard"
63 _require_batched_discard $SCRATCH_MNT
64
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
67 sync
68
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
71 # transaction.
72 touch $SCRATCH_MNT/bar
73
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
77
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).
88 enable_io_failure
89
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).
92 sync
93 disable_io_failure
94
95 touch $SCRATCH_MNT/abc >>$seqres.full 2>&1 && \
96         echo "Transaction was not aborted, filesystem is not in readonly mode"
97
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
103
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.
106 _scratch_cycle_mount
107
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
110 # did not fsync foo.
111 echo "File foo content after transaction abort + remount:"
112 od -t x1 $SCRATCH_MNT/foo
113
114 status=0
115 exit