test: improve the cp fiemap tests
[coreutils/ericb.git] / tests / cp / sparse-fiemap
blobfc27869e8a03bd129f6e6bd44de7d9702dac8262
1 #!/bin/sh
2 # Test cp --sparse=always through fiemap copy
4 # Copyright (C) 2010-2011 Free Software Foundation, Inc.
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 . "${srcdir=.}/init.sh"; path_prepend_ ../src
20 print_ver_ cp
22 # Note we don't check a file here as that could enable
23 # the test on ext3 where this test is seen to fail.
24 if fiemap_capable_ . ; then
25 : # Current dir is on a partition with working extents. Good!
26 else
27 # It's not; we need to create one, hence we need root access.
28 require_root_
30 cwd=$PWD
31 cleanup_() { cd /; umount "$cwd/mnt"; }
33 skip=0
34 # Create an ext4 loopback file system
35 dd if=/dev/zero of=blob bs=32k count=1000 || skip=1
36 mkdir mnt
37 mkfs -t ext4 -F blob ||
38 skip_test_ "failed to create ext4 file system"
39 mount -oloop blob mnt || skip=1
40 cd mnt || skip=1
41 echo test > f || skip=1
42 test -s f || skip=1
44 test $skip = 1 &&
45 skip_test_ "insufficient mount/ext4 support"
48 # =================================================
49 # Ensure that we exercise the FIEMAP-copying code enough
50 # to provoke at least two iterations of the do...while loop
51 # in which it calls ioctl (fd, FS_IOC_FIEMAP,...
52 # This also verifies that non-trivial extents are preserved.
54 $PERL -e 1 || skip_test_ 'skipping part of this test; you lack perl'
56 # Extract logical block number and length pairs from filefrag -v output.
57 # The initial sed is to remove the "eof" from the normally-empty "flags" field.
58 # Similarly, remove flags values like "unknown,delalloc,eof".
59 # That is required when that final extent has no number in the "expected" field.
60 f()
62 sed 's/ [a-z,][a-z,]*$//' $@ \
63 | awk '/^ *[0-9]/ {printf "%d %d ", $2 ,NF < 5 ? $NF : $5 } END {print ""}'
66 for i in $(seq 1 2 21); do
67 for j in 1 2 31 100; do
68 $PERL -e 'BEGIN { $n = '$i' * 1024; *F = *STDOUT }' \
69 -e 'for (1..'$j') { sysseek (*F, $n, 1)' \
70 -e '&& syswrite (*F, chr($_)x$n) or die "$!"}' > j1 || fail=1
72 # Note the explicit fdatasync is used here as
73 # it was seen that `filefrag -s` (FIEMAP_FLAG_SYNC) was
74 # ineffective on ext4 loopback on Linux 2.6.35.10-72.fc14.i686
75 dd if=/dev/null of=j1 conv=notrunc,fdatasync
76 cp --sparse=always j1 j2 || fail=1
77 dd if=/dev/null of=j2 conv=notrunc,fdatasync
79 cmp j1 j2 || fail=1
80 filefrag -v j1 | grep extent \
81 || skip_test_ 'skipping part of this test; you lack filefrag'
83 # Here is sample filefrag output:
84 # $ perl -e 'BEGIN{$n=16*1024; *F=*STDOUT}' \
85 # -e 'for (1..5) { sysseek(*F,$n,1)' \
86 # -e '&& syswrite *F,"."x$n or die "$!"}' > j
87 # $ filefrag -v j
88 # File system type is: ef53
89 # File size of j is 163840 (40 blocks, blocksize 4096)
90 # ext logical physical expected length flags
91 # 0 4 6258884 4
92 # 1 12 6258892 6258887 4
93 # 2 20 6258900 6258895 4
94 # 3 28 6258908 6258903 4
95 # 4 36 6258916 6258911 4 eof
96 # j: 6 extents found
98 # exclude the physical block numbers; they always differ
99 filefrag -v j1 > ff1 || fail=1
100 filefrag -v j2 > ff2 || fail=1
101 { f ff1; f ff2; } \
102 | $PERL $abs_top_srcdir/tests/filefrag-extent-compare \
103 || { fail=1; break; }
104 done
105 test $fail = 1 && break
106 done
108 Exit $fail