reflink: test CoW with blocksize < pagesize
[xfstests-dev.git] / common / reflink
1 ##/bin/bash
2 # Routines for reflinking, deduping, and comparing parts of files.
3 #-----------------------------------------------------------------------
4 #  Copyright (c) 2015 Oracle.  All Rights Reserved.
5 #  This program is free software; you can redistribute it and/or modify
6 #  it under the terms of the GNU General Public License as published by
7 #  the Free Software Foundation; either version 2 of the License, or
8 #  (at your option) any later version.
9 #
10 #  This program is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #  GNU General Public License for more details.
14 #
15 #  You should have received a copy of the GNU General Public License
16 #  along with this program; if not, write to the Free Software
17 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 #  USA
19 #
20 #  Contact information: Oracle Corporation, 500 Oracle Parkway,
21 #  Redwood Shores, CA 94065, USA, or: http://www.oracle.com/
22 #-----------------------------------------------------------------------
23
24 # Check that cp has a reflink argument
25 _require_cp_reflink()
26 {
27        cp --help | grep -q reflink || \
28                _notrun "This test requires a cp with --reflink support."
29 }
30
31 # Given 2 files, verify that they have the same mapping but different
32 # inodes - i.e. an undisturbed reflink
33 # Silent if so, make noise if not
34 _verify_reflink()
35 {
36        # not a hard link or symlink?
37        cmp -s  <(stat -c '%i' $1) <(stat -c '%i' $2) \
38                && echo "$1 and $2 are not reflinks: same inode number"
39
40        # same mapping?
41        diff -u <($XFS_IO_PROG -c "fiemap" $1 | grep -v $1) \
42                <($XFS_IO_PROG -c "fiemap" $2 | grep -v $2) \
43                || echo "$1 and $2 are not reflinks: different extents"
44 }
45
46 # New reflink/dedupe helpers
47
48 # this test requires the test fs support reflink...
49 _require_test_reflink()
50 {
51         _require_test
52         _require_xfs_io_command "reflink"
53
54         rm -rf "$TEST_DIR/file1" "$TEST_DIR/file2"
55         "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$TEST_DIR/file1" > /dev/null
56         "$XFS_IO_PROG" -f -c "reflink $TEST_DIR/file1 0 0 65536" "$TEST_DIR/file2" > /dev/null
57         if [ ! -s "$TEST_DIR/file2" ]; then
58                 rm -rf "$TEST_DIR/file1" "$TEST_DIR/file2"
59                 _notrun "Reflink not supported by test filesystem type: $FSTYP"
60         fi
61         rm -rf "$TEST_DIR/file1" "$TEST_DIR/file2"
62 }
63
64 # this test requires the scratch fs support reflink...
65 _require_scratch_reflink()
66 {
67         _require_scratch
68         _require_xfs_io_command "reflink"
69
70         _scratch_mkfs > /dev/null
71         _scratch_mount
72         "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$SCRATCH_MNT/file1" > /dev/null
73         "$XFS_IO_PROG" -f -c "reflink $SCRATCH_MNT/file1 0 0 65536" "$SCRATCH_MNT/file2" > /dev/null
74         if [ ! -s "$SCRATCH_MNT/file2" ]; then
75                 _scratch_unmount
76                 _notrun "Reflink not supported by scratch filesystem type: $FSTYP"
77         fi
78         _scratch_unmount
79 }
80
81 # this test requires the test fs support dedupe...
82 _require_test_dedupe()
83 {
84         _require_test
85         _require_xfs_io_command "dedupe"
86
87         rm -rf "$TEST_DIR/file1" "$TEST_DIR/file2"
88         "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$TEST_DIR/file1" > /dev/null
89         "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$TEST_DIR/file2" > /dev/null
90         testio="$("$XFS_IO_PROG" -f -c "dedupe $TEST_DIR/file1 0 0 65536" "$TEST_DIR/file2" 2>&1)"
91         echo $testio | grep -q "Operation not supported" && \
92                 _notrun "Dedupe not supported by test filesystem type: $FSTYP"
93         echo $testio | grep -q "Inappropriate ioctl for device" && \
94                 _notrun "Dedupe not supported by test filesystem type: $FSTYP"
95         rm -rf "$TEST_DIR/file1" "$TEST_DIR/file2"
96 }
97
98 # this test requires the scratch fs support dedupe...
99 _require_scratch_dedupe()
100 {
101         _require_scratch
102         _require_xfs_io_command "dedupe"
103
104         _scratch_mkfs > /dev/null
105         _scratch_mount
106         "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$SCRATCH_MNT/file1" > /dev/null
107         "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$SCRATCH_MNT/file2" > /dev/null
108         testio="$("$XFS_IO_PROG" -f -c "dedupe $TEST_DIR/file1 0 0 65536" "$TEST_DIR/file2" 2>&1)"
109         echo $testio | grep -q "Operation not supported" && \
110                 _notrun "Dedupe not supported by test filesystem type: $FSTYP"
111         echo $testio | grep -q "Inappropriate ioctl for device" && \
112                 _notrun "Dedupe not supported by test filesystem type: $FSTYP"
113         _scratch_unmount
114 }
115
116 # Prints a range of a file as a hex dump
117 _read_range() {
118         file="$1"
119         offset="$2"
120         len="$3"
121         xfs_io_args="$4"
122
123         $XFS_IO_PROG $xfs_io_args -f -c "pread -q -v $offset $len" "$file" | cut -d ' ' -f '3-18'
124 }
125
126 # Compare ranges of two files
127 _compare_range() {
128         file1="$1"
129         offset1="$2"
130         file2="$3"
131         offset2="$4"
132         len="$5"
133
134         cmp -s <(_read_range "$file1" "$offset1" "$len") \
135                <(_read_range "$file2" "$offset2" "$len")
136 }
137
138 # Prints the md5 checksum of a hexdump of a part of a given file
139 _md5_range_checksum() {
140         file="$1"
141         offset="$2"
142         len="$3"
143
144         md5sum <(_read_range "$file" "$offset" "$len") | cut -d ' ' -f 1
145 }
146
147 # Reflink some file1 into file2 via cp
148 _cp_reflink() {
149         file1="$1"
150         file2="$2"
151
152         cp --reflink=always "$file1" "$file2"
153 }
154
155 # Reflink some file1 into file2
156 _reflink() {
157         file1="$1"
158         file2="$2"
159
160         "$XFS_IO_PROG" -f -c "reflink $file1" "$file2"
161 }
162
163 # Reflink some part of file1 into another part of file2
164 _reflink_range() {
165         file1="$1"
166         offset1="$2"
167         file2="$3"
168         offset2="$4"
169         len="$5"
170         xfs_io_args="$6"
171
172         "$XFS_IO_PROG" $xfs_io_args -f -c "reflink $file1 $offset1 $offset2 $len" "$file2"
173 }
174
175 # Dedupe some part of file1 into another part of file2
176 _dedupe_range() {
177         file1="$1"
178         offset1="$2"
179         file2="$3"
180         offset2="$4"
181         len="$5"
182         xfs_io_args="$6"
183
184         "$XFS_IO_PROG" $xfs_io_args -f -c "dedupe $file1 $offset1 $offset2 $len" "$file2"
185 }
186
187 # Create fs of certain blocksize on scratch device
188 # _scratch_mkfs_blocksized blocksize
189 _scratch_mkfs_blocksized()
190 {
191     blocksize=$1
192
193     re='^[0-9]+$'
194     if ! [[ $blocksize =~ $re ]] ; then
195         _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
196     fi
197
198     case $FSTYP in
199     xfs)
200         # don't override MKFS_OPTIONS that set a block size.
201         echo $MKFS_OPTIONS |egrep -q "b?size="
202         if [ $? -eq 0 ]; then
203                 _scratch_mkfs_xfs
204         else
205                 _scratch_mkfs_xfs -b size=$blocksize
206         fi
207         ;;
208     ext2|ext3|ext4|ocfs2)
209         ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV
210         ;;
211     *)
212         _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_blocksized"
213         ;;
214     esac
215 }