2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (C) 2020 SUSE Linux Products GmbH. All Rights Reserved.
7 # Test several scenarios of cloning operations where the source range includes
8 # inline extents. They used to not be supported on btrfs because their
9 # implementation was not straightforward, and therefore these operations used
10 # to fail with errno EOPNOTSUPP on older kernels.
12 # Support for this was added by a patch with the following subject:
14 # "Btrfs: implement full reflink support for inline extents"
17 seqres=$RESULT_DIR/$seq
18 echo "QA output created by $seq"
20 status=1 # failure is the default!
21 trap "_cleanup; exit \$status" 0 1 2 3 15
29 # get standard environment, filters and checks
34 # remove previous $seqres.full before test
37 # real QA test starts here
39 _require_scratch_reflink
40 _require_xfs_io_command "falloc" "-k"
41 _require_command "$CHATTR_PROG" chattr
42 _require_btrfs_fs_feature "no_holes"
43 _require_btrfs_mkfs_feature "no-holes"
47 rm -f $SCRATCH_MNT/foo* $SCRATCH_MNT/bar*
49 # File foo1 has an inline extent encoding 4K of data followed by a regular
50 # extent. It has a file size of 128K.
51 echo "Creating file foo1"
52 touch $SCRATCH_MNT/foo1
53 $CHATTR_PROG +c $SCRATCH_MNT/foo1 > /dev/null 2>&1
54 $XFS_IO_PROG -c "pwrite -S 0xab 0 4K" \
56 -c "pwrite -S 0xab 4K 124K" \
57 $SCRATCH_MNT/foo1 | _filter_xfs_io
59 # File bar1 has a single 128K extent, and a file size of 128K.
60 echo "Creating file bar1"
61 $XFS_IO_PROG -f -c "pwrite -S 0xcd 0 128K" $SCRATCH_MNT/bar1 | _filter_xfs_io
63 echo "Cloning foo1 into the end of bar1"
64 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo1 0 128K 128K" $SCRATCH_MNT/bar1 \
67 echo "File bar1 digest = $(_md5_checksum $SCRATCH_MNT/bar1)"
69 # File foo2 has an inline extent with 1000 bytes of data and it's followed
70 # by a regular extent of 60K. It has a file size of 64K.
71 echo "Creating file foo2"
72 $XFS_IO_PROG -f -c "pwrite -S 0xab 0 1000" \
75 -c "pwrite -S 0xab 4K 60K" \
76 $SCRATCH_MNT/foo2 | _filter_xfs_io
78 # File bar2 has a regular extent of 64K and a file size of 64K too.
79 echo "Creating file bar2"
80 $XFS_IO_PROG -f -c "pwrite -S 0xcd 0 64K" $SCRATCH_MNT/bar2 | _filter_xfs_io
82 echo "Cloning foo2 into the end of bar2"
83 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo2 0 64K 64K" $SCRATCH_MNT/bar2 \
86 echo "File bar2 digest = $(_md5_checksum $SCRATCH_MNT/bar2)"
88 # File bar3 has a regular extent of 128K and a file size of 128K too.
89 echo "Creating file bar3"
90 $XFS_IO_PROG -f -c "pwrite -S 0xcd 0 128K" $SCRATCH_MNT/bar3 \
93 echo "Cloning foo2 into the middle of bar3"
94 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo2 0 64K 64K" $SCRATCH_MNT/bar3 \
97 echo "File bar3 digest = $(_md5_checksum $SCRATCH_MNT/bar3)"
99 # File bar4 has a 64K hole at offset 0 followed by a 64K regular extent, and
100 # a file size of 128K.
101 echo "Creating file bar4"
102 $XFS_IO_PROG -f -c "pwrite -S 0xcd 64K 64K" $SCRATCH_MNT/bar4 | _filter_xfs_io
104 echo "Cloning foo1 into bar4"
105 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo1 0 0 128K" $SCRATCH_MNT/bar4 \
108 echo "File bar4 digest = $(_md5_checksum $SCRATCH_MNT/bar4)"
110 # File bar5 has a 1Mb prealloc extent at file offset 0 and a file size of 0.
111 echo "Creating file bar5"
112 $XFS_IO_PROG -f -c "falloc -k 0 1M" $SCRATCH_MNT/bar5
114 echo "Cloning foo1 into bar5"
115 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo1 0 0 128K" $SCRATCH_MNT/bar5 \
118 echo "File bar5 digest = $(_md5_checksum $SCRATCH_MNT/bar5)"
120 # File bar6 has an inline extent encoding 500 bytes of data followed by a
121 # prealloc extent of 1Mb at file offset 4K. The file size is 500 bytes.
122 echo "Creating file bar6"
123 $XFS_IO_PROG -f -c "pwrite -S 0xef 0 500" \
124 -c "falloc -k 4K 1M" \
125 $SCRATCH_MNT/bar6 | _filter_xfs_io
127 echo "Cloning foo1 into bar6"
128 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo1 0 0 128K" $SCRATCH_MNT/bar6 \
131 echo "File bar6 digest = $(_md5_checksum $SCRATCH_MNT/bar6)"
133 # File foo3 a single inline extent of 500 bytes.
134 echo "Creating file foo3"
135 $XFS_IO_PROG -f -c "pwrite -S 0xbf 0 500" $SCRATCH_MNT/foo3 | _filter_xfs_io
137 # File bar7 is an empty file, has no extents.
138 touch $SCRATCH_MNT/bar7
140 echo "Cloning foo3 into bar7"
141 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo3" $SCRATCH_MNT/bar7 | _filter_xfs_io
143 echo "File bar7 digest = $(_md5_checksum $SCRATCH_MNT/bar7)"
145 # Unmount and mount again the filesystem. We want to verify the reflink
146 # operations were durably persisted.
149 echo "File digests after mounting again the filesystem:"
150 echo "File bar1 digest = $(_md5_checksum $SCRATCH_MNT/bar1)"
151 echo "File bar2 digest = $(_md5_checksum $SCRATCH_MNT/bar2)"
152 echo "File bar3 digest = $(_md5_checksum $SCRATCH_MNT/bar3)"
153 echo "File bar4 digest = $(_md5_checksum $SCRATCH_MNT/bar4)"
154 echo "File bar5 digest = $(_md5_checksum $SCRATCH_MNT/bar5)"
155 echo "File bar6 digest = $(_md5_checksum $SCRATCH_MNT/bar6)"
156 echo "File bar7 digest = $(_md5_checksum $SCRATCH_MNT/bar7)"
159 _scratch_mkfs "-O ^no-holes" >>$seqres.full 2>&1
163 echo "Testing with defaults"
168 echo "Testing with -o compress"
170 _scratch_cycle_mount "compress"
174 echo "Testing with -o nodatacow"
176 _scratch_cycle_mount "nodatacow"
180 echo "Testing with -O no-holes"
183 _scratch_mkfs "-O no-holes" >>$seqres.full 2>&1