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 # real QA test starts here
36 _require_scratch_reflink
37 _require_xfs_io_command "falloc" "-k"
38 _require_command "$CHATTR_PROG" chattr
39 _require_btrfs_fs_feature "no_holes"
40 _require_btrfs_mkfs_feature "no-holes"
44 rm -f $SCRATCH_MNT/foo* $SCRATCH_MNT/bar*
46 # File foo1 has an inline extent encoding 4K of data followed by a regular
47 # extent. It has a file size of 128K.
48 echo "Creating file foo1"
49 touch $SCRATCH_MNT/foo1
50 $CHATTR_PROG +c $SCRATCH_MNT/foo1 > /dev/null 2>&1
51 $XFS_IO_PROG -c "pwrite -S 0xab 0 4K" \
53 -c "pwrite -S 0xab 4K 124K" \
54 $SCRATCH_MNT/foo1 | _filter_xfs_io
56 # File bar1 has a single 128K extent, and a file size of 128K.
57 echo "Creating file bar1"
58 $XFS_IO_PROG -f -c "pwrite -S 0xcd 0 128K" $SCRATCH_MNT/bar1 | _filter_xfs_io
60 echo "Cloning foo1 into the end of bar1"
61 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo1 0 128K 128K" $SCRATCH_MNT/bar1 \
64 echo "File bar1 digest = $(_md5_checksum $SCRATCH_MNT/bar1)"
66 # File foo2 has an inline extent with 1000 bytes of data and it's followed
67 # by a regular extent of 60K. It has a file size of 64K.
68 echo "Creating file foo2"
69 $XFS_IO_PROG -f -c "pwrite -S 0xab 0 1000" \
72 -c "pwrite -S 0xab 4K 60K" \
73 $SCRATCH_MNT/foo2 | _filter_xfs_io
75 # File bar2 has a regular extent of 64K and a file size of 64K too.
76 echo "Creating file bar2"
77 $XFS_IO_PROG -f -c "pwrite -S 0xcd 0 64K" $SCRATCH_MNT/bar2 | _filter_xfs_io
79 echo "Cloning foo2 into the end of bar2"
80 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo2 0 64K 64K" $SCRATCH_MNT/bar2 \
83 echo "File bar2 digest = $(_md5_checksum $SCRATCH_MNT/bar2)"
85 # File bar3 has a regular extent of 128K and a file size of 128K too.
86 echo "Creating file bar3"
87 $XFS_IO_PROG -f -c "pwrite -S 0xcd 0 128K" $SCRATCH_MNT/bar3 \
90 echo "Cloning foo2 into the middle of bar3"
91 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo2 0 64K 64K" $SCRATCH_MNT/bar3 \
94 echo "File bar3 digest = $(_md5_checksum $SCRATCH_MNT/bar3)"
96 # File bar4 has a 64K hole at offset 0 followed by a 64K regular extent, and
97 # a file size of 128K.
98 echo "Creating file bar4"
99 $XFS_IO_PROG -f -c "pwrite -S 0xcd 64K 64K" $SCRATCH_MNT/bar4 | _filter_xfs_io
101 echo "Cloning foo1 into bar4"
102 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo1 0 0 128K" $SCRATCH_MNT/bar4 \
105 echo "File bar4 digest = $(_md5_checksum $SCRATCH_MNT/bar4)"
107 # File bar5 has a 1Mb prealloc extent at file offset 0 and a file size of 0.
108 echo "Creating file bar5"
109 $XFS_IO_PROG -f -c "falloc -k 0 1M" $SCRATCH_MNT/bar5
111 echo "Cloning foo1 into bar5"
112 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo1 0 0 128K" $SCRATCH_MNT/bar5 \
115 echo "File bar5 digest = $(_md5_checksum $SCRATCH_MNT/bar5)"
117 # File bar6 has an inline extent encoding 500 bytes of data followed by a
118 # prealloc extent of 1Mb at file offset 4K. The file size is 500 bytes.
119 echo "Creating file bar6"
120 $XFS_IO_PROG -f -c "pwrite -S 0xef 0 500" \
121 -c "falloc -k 4K 1M" \
122 $SCRATCH_MNT/bar6 | _filter_xfs_io
124 echo "Cloning foo1 into bar6"
125 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo1 0 0 128K" $SCRATCH_MNT/bar6 \
128 echo "File bar6 digest = $(_md5_checksum $SCRATCH_MNT/bar6)"
130 # File foo3 a single inline extent of 500 bytes.
131 echo "Creating file foo3"
132 $XFS_IO_PROG -f -c "pwrite -S 0xbf 0 500" $SCRATCH_MNT/foo3 | _filter_xfs_io
134 # File bar7 is an empty file, has no extents.
135 touch $SCRATCH_MNT/bar7
137 echo "Cloning foo3 into bar7"
138 $XFS_IO_PROG -c "reflink $SCRATCH_MNT/foo3" $SCRATCH_MNT/bar7 | _filter_xfs_io
140 echo "File bar7 digest = $(_md5_checksum $SCRATCH_MNT/bar7)"
142 # Unmount and mount again the filesystem. We want to verify the reflink
143 # operations were durably persisted.
146 echo "File digests after mounting again the filesystem:"
147 echo "File bar1 digest = $(_md5_checksum $SCRATCH_MNT/bar1)"
148 echo "File bar2 digest = $(_md5_checksum $SCRATCH_MNT/bar2)"
149 echo "File bar3 digest = $(_md5_checksum $SCRATCH_MNT/bar3)"
150 echo "File bar4 digest = $(_md5_checksum $SCRATCH_MNT/bar4)"
151 echo "File bar5 digest = $(_md5_checksum $SCRATCH_MNT/bar5)"
152 echo "File bar6 digest = $(_md5_checksum $SCRATCH_MNT/bar6)"
153 echo "File bar7 digest = $(_md5_checksum $SCRATCH_MNT/bar7)"
156 _scratch_mkfs "-O ^no-holes" >>$seqres.full 2>&1
160 echo "Testing with defaults"
165 echo "Testing with -o compress"
167 _scratch_cycle_mount "compress"
171 echo "Testing with -o nodatacow"
173 _scratch_cycle_mount "nodatacow"
177 echo "Testing with -O no-holes"
180 _scratch_mkfs "-O no-holes" >>$seqres.full 2>&1