. "${srcdir=.}/init.sh"; path_prepend_ ../src
-if df -T -t btrfs -t xfs . ; then
+if df -T -t btrfs -t xfs -t ext4 -t ocfs2 . ; then
: # Current dir is on a partition with working extents. Good!
else
# It's not; we need to create one, hence we need root access.
cleanup_() { cd /; umount "$cwd/mnt"; }
skip=0
- # Create an XFS loopback file system
+ # Create an ext4 loopback file system
dd if=/dev/zero of=blob bs=32k count=1000 || skip=1
mkdir mnt
- mkfs -t xfs blob ||
- skip_test_ "failed to create XFS file system"
+ mkfs -t ext4 -F blob ||
+ skip_test_ "failed to create ext4 file system"
mount -oloop blob mnt || skip=1
cd mnt || skip=1
echo test > f || skip=1
test -s f || skip=1
test $skip = 1 &&
- skip_test_ "insufficient mount/XFS support"
+ skip_test_ "insufficient mount/ext4 support"
fi
# Create a 1TiB sparse file
$PERL -e 1 || skip_test_ 'skipping part of this test; you lack perl'
-for i in $(seq 20); do
+# Extract logical block number and length pairs from filefrag -v output.
+# The initial sed is to remove the "eof" from the normally-empty "flags" field.
+# That is required when that final extent has no number in the "expected" field.
+f()
+{
+ sed 's/ eof$//' $@ \
+ | awk '/^ *[0-9]/ {printf "%d %d ", $2 ,NF < 5 ? $NF : $5 } END {print ""}'
+}
+
+for i in $(seq 1 2 21); do
for j in 1 2 31 100; do
$PERL -e 'BEGIN { $n = '$i' * 1024; *F = *STDOUT }' \
-e 'for (1..'$j') { sysseek (*F, $n, 1)' \
- -e '&& syswrite (*F, "."x$n) or die "$!"}' > j1 || fail=1
-
+ -e '&& syswrite (*F, chr($_)x$n) or die "$!"}' > j1 || fail=1
+ # sync
cp --sparse=always j1 j2 || fail=1
+ # sync
+ # Technically we may need the 'sync' uses above, but
+ # uncommenting them makes this test take much longer.
+
cmp j1 j2 || fail=1
filefrag -v j1 | grep extent \
|| skip_test_ 'skipping part of this test; you lack filefrag'
# j: 6 extents found
# exclude the physical block numbers; they always differ
- filefrag -v j1 | awk '/^ / {print $1,$2}' > ff1 || fail=1
- filefrag -v j2 | awk '/^ / {print $1,$2}' > ff2 || fail=1
- compare ff1 ff2 || fail=1
+ filefrag -v j1 > ff1 || fail=1
+ filefrag -v j2 > ff2 || fail=1
+ { f ff1; f ff2; } \
+ | $PERL $abs_top_srcdir/tests/filefrag-extent-compare \
+ || { fail=1; break; }
done
+ test $fail = 1 && break
done
Exit $fail
--- /dev/null
+eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
+ & eval 'exec perl -wS "$0" $argv:q'
+ if 0;
+# Determine whether two files have the same extents by comparing
+# the logical block numbers and lengths from filefrag -v for each.
+
+# Invoke like this:
+# This helper function, f, extracts logical block number and lengths.
+# f() { awk '/^ *[0-9]/ {printf "%d %d ",$2,NF<5?$NF:$5} END {print ""}'; }
+# { filefrag -v j1 | f; filefrag -v j2 | f; } | ./filefrag-extent-compare
+
+use warnings;
+use strict;
+(my $ME = $0) =~ s|.*/||;
+
+my @line = <>;
+my $n_lines = @line;
+$n_lines == 2
+ or die "$ME: expected exactly two input lines; got $n_lines\n";
+
+my @A = split ' ', $line[0];
+my @B = split ' ', $line[1];
+@A % 2 || @B % 2
+ and die "$ME: unexpected input: odd number of numbers; expected even\n";
+
+my @a;
+my @b;
+foreach my $i (0..@A/2-1) { $a[$i] = { L_BLK => $A[2*$i], LEN => $A[2*$i+1] } };
+foreach my $i (0..@B/2-1) { $b[$i] = { L_BLK => $B[2*$i], LEN => $B[2*$i+1] } };
+
+my $i = 0;
+my $j = 0;
+while (1)
+ {
+ !defined $a[$i] && !defined $b[$j]
+ and exit 0;
+ defined $a[$i] && defined $b[$j]
+ or die "\@a and \@b have different lengths, even after adjustment\n";
+ ($a[$i]->{L_BLK} == $b[$j]->{L_BLK}
+ && $a[$i]->{LEN} == $b[$j]->{LEN})
+ and next;
+ ($a[$i]->{LEN} < $b[$j]->{LEN}
+ && exists $a[$i+1] && $a[$i]->{LEN} + $a[$i+1]->{LEN} == $b[$j]->{LEN})
+ and ++$i, next;
+ exists $b[$j+1] && $a[$i]->{LEN} == $b[$i]->{LEN} + $b[$i+1]->{LEN}
+ and ++$j, next;
+ die "differing extent:\n"
+ . " [$i]=$a[$i]->{L_BLK} $a[$i]->{LEN}\n"
+ . " [$j]=$b[$j]->{L_BLK} $b[$j]->{LEN}\n"
+ }
+continue
+ {
+ ++$i;
+ ++$j;
+ }
+
+### Setup "GNU" style for perl-mode and cperl-mode.
+## Local Variables:
+## mode: perl
+## perl-indent-level: 2
+## perl-continued-statement-offset: 2
+## perl-continued-brace-offset: 0
+## perl-brace-offset: 0
+## perl-brace-imaginary-offset: 0
+## perl-label-offset: -2
+## perl-extra-newline-before-brace: t
+## perl-merge-trailing-else: nil
+## End: