2 # FS QA Test No. btrfs/055
4 # Regression test for the btrfs ioctl clone operation when the source range
5 # contains hole(s) and the FS has the NO_HOLES feature enabled (file holes
6 # don't need file extent items in the btree to represent them).
8 # This issue is fixed by the following linux kernel btrfs patch:
10 # Btrfs: fix clone to deal with holes when NO_HOLES feature is enabled
12 #-----------------------------------------------------------------------
13 # Copyright (c) 2014 Filipe Manana. All Rights Reserved.
15 # This program is free software; you can redistribute it and/or
16 # modify it under the terms of the GNU General Public License as
17 # published by the Free Software Foundation.
19 # This program is distributed in the hope that it would be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write the Free Software Foundation,
26 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #-----------------------------------------------------------------------
31 seqres=$RESULT_DIR/$seq
32 echo "QA output created by $seq"
35 status=1 # failure is the default!
36 trap "_cleanup; exit \$status" 0 1 2 3 15
43 # get standard environment, filters and checks
47 # real QA test starts here
52 _require_btrfs_fs_feature "no_holes"
53 _require_btrfs_mkfs_feature "no-holes"
58 test_btrfs_clone_with_holes()
60 _scratch_mkfs "$1" >/dev/null 2>&1
63 # Create a file with 4 extents and 1 hole, all with a size of 8Kb each.
64 # The hole is in the range [16384, 24576[.
65 $XFS_IO_PROG -s -f -c "pwrite -S 0x01 -b 8192 0 8192" \
66 -c "pwrite -S 0x02 -b 8192 8192 8192" \
67 -c "pwrite -S 0x04 -b 8192 24576 8192" \
68 -c "pwrite -S 0x05 -b 8192 32768 8192" \
69 $SCRATCH_MNT/foo | _filter_xfs_io
71 # Clone destination file, 1 extent of 96kb.
72 $XFS_IO_PROG -s -f -c "pwrite -S 0xff -b 98304 0 98304" \
73 $SCRATCH_MNT/bar | _filter_xfs_io
75 # Clone 2nd extent, 8Kb hole and 3rd extent of foo into bar.
76 $CLONER_PROG -s 8192 -d 0 -l 24576 $SCRATCH_MNT/foo $SCRATCH_MNT/bar
78 # Verify both extents and the hole were cloned.
79 echo "1) Check both extents and the hole were cloned"
80 od -t x1 $SCRATCH_MNT/bar
82 # Cloning range starts at the middle of an hole.
83 $CLONER_PROG -s 20480 -d 32768 -l 12288 $SCRATCH_MNT/foo \
86 # Verify that half of the hole and the following 8Kb extent were cloned.
87 echo "2) Check half hole and one 8Kb extent were cloned"
88 od -t x1 $SCRATCH_MNT/bar
90 # Cloning range ends at the middle of an hole.
91 $CLONER_PROG -s 0 -d 65536 -l 20480 $SCRATCH_MNT/foo $SCRATCH_MNT/bar
93 # Verify that 2 extents of 8kb and a 4kb hole were cloned.
94 echo "3) Check that 2 extents of 8kb eacg and a 4kb hole were cloned"
95 od -t x1 $SCRATCH_MNT/bar
97 # Create a 24Kb hole at the end of the source file (foo).
98 $XFS_IO_PROG -c "truncate 65536" $SCRATCH_MNT/foo
101 # Now clone a range that overlaps that hole at the end of the foo file.
102 # It should clone the last 4Kb of the extent at offset 32768 and the
103 # first 8kb of the 24kb hole at the end of foo.
104 $CLONER_PROG -s 36864 -d 86016 -l 12288 $SCRATCH_MNT/foo \
107 # Verify that the second half of the 8Kb extent at offset 32768 of foo
108 # and the first 8Kb of the 24kb hole of foo were cloned into bar.
109 echo "4) Check that 4kb of 1 extent and 8Kb of an hole were cloned"
110 od -t x1 $SCRATCH_MNT/bar
112 # Clone the same range as before, but clone it into a different offset
113 # of the target (bar) such that it increases the size of the target
115 $CLONER_PROG -s 36864 -d 94208 -l 12288 $SCRATCH_MNT/foo \
118 # Verify that the second half of the 8Kb extent at offset 32768 of foo
119 # and the first 8Kb of the 24kb hole of foo were cloned into bar at
120 # bar's offset 94208 and that bar's size increased by 8Kb.
121 echo "5) Check that 4kb of 1 extent and 8Kb of an hole were cloned and file size increased"
122 od -t x1 $SCRATCH_MNT/bar
124 # Create a new completely sparse file (no extents, it's a big hole).
125 $XFS_IO_PROG -f -c "truncate 100000" $SCRATCH_MNT/qwerty
128 # Test cloning a range from the sparse file to the bar file without
129 # increasing bar's size.
130 $CLONER_PROG -s 4096 -d 0 -l 8192 $SCRATCH_MNT/qwerty $SCRATCH_MNT/bar
132 # First 8Kb of bar should now be zeroes.
133 echo "6) Check that 8kb of the hole were cloned"
134 od -t x1 $SCRATCH_MNT/bar
136 # Test cloning a range from the sparse file to the end of the bar file.
137 # The bar file currently has a size of 106496 bytes.
138 $CLONER_PROG -s 0 -d 106496 -l 32768 $SCRATCH_MNT/qwerty \
141 # Verify bar's size increased to 106496 + 32768 bytes (136Kb), and its
142 # last 32768 bytes are all zeroes.
143 echo "7) Check that 32kb of the hole were cloned and the file size increased"
144 od -t x1 $SCRATCH_MNT/bar
146 # Verify that there are no consistency errors.
150 # Regardless of the NO_HOLES feature being enabled or not, the test results
151 # should be exactly the same for both cases.
153 echo "Testing without the NO_HOLES feature"
154 # As of btrfs-progs 3.14.x, the no-holes feature isn't enabled by default.
155 # But explicitly disable it at mkfs time as it might be enabled by default
156 # in future versions.
157 test_btrfs_clone_with_holes "-O ^no-holes"
161 echo "Testing with the NO_HOLES feature enabled"
162 test_btrfs_clone_with_holes "-O no-holes"