diff options
author | Pádraig Brady <P@draigBrady.com> | 2011-02-11 08:55:22 +0000 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2011-04-01 15:04:18 +0100 |
commit | bfdb6b585b6842362977b8c10fe7858fb96a1dd0 (patch) | |
tree | 0279e6e1674d34072ba8e7bf94ba929f332e54e4 /tests/cp | |
parent | b56b53bd70b1f8fa2b5a95d4569bb72a2419b5cd (diff) | |
download | coreutils-bfdb6b585b6842362977b8c10fe7858fb96a1dd0.tar.xz |
copy: process empty extents more efficiently
* src/copy.c (extent_copy): Treat an allocated but empty extent
much like a hole. I.E. don't read data we know is going to be NUL.
Also we convert the empty extent to a hole only when SPARSE_ALWAYS
so that the source and dest have the same allocation. This will
be improved soon, when we use fallocate() to do the allocation.
* tests/cp/fiemap-empty: A new test for efficiency and correctness
of copying empty extents.
* tests/Makefile.am: Reference the new test.
* NEWS: Mention the change in behavior.
Diffstat (limited to 'tests/cp')
-rwxr-xr-x | tests/cp/fiemap-empty | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/tests/cp/fiemap-empty b/tests/cp/fiemap-empty new file mode 100755 index 000000000..f1ed71c71 --- /dev/null +++ b/tests/cp/fiemap-empty @@ -0,0 +1,89 @@ +#!/bin/sh +# Test cp reads unwritten extents efficiently + +# Copyright (C) 2011 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +. "${srcdir=.}/init.sh"; path_prepend_ ../src +print_ver_ cp + +touch fiemap_chk +fiemap_capable_ fiemap_chk || + skip_test_ 'this file system lacks FIEMAP support' +rm fiemap_chk + +# TODO: rather than requiring `fallocate`, possible add +# this functionality to truncate --alloc +fallocate --help >/dev/null || skip_test_ 'The fallocate utility is required' +fallocate -l 1 -n falloc.test || + skip_test_ 'this file system lacks FALLOCATE support' +rm falloc.test + +fallocate -l 600000000 space.test || + skip_test_ 'this test needs at least 600MB free space' + +# Disable this test on old BTRFS (e.g. Fedora 14) +# which reports ordinary extents for unwritten ones. +filefrag space.test || skip_test_ 'the `filefrag` utility is missing' +filefrag -v space.test | grep -F 'unwritten' > /dev/null || + skip_test_ 'this file system does not report empty extents as "unwritten"' + +rm space.test + +# Ensure we read a large empty file quickly +fallocate -l 300000000 empty.big || framework_failure +timeout 3 cp --sparse=always empty.big cp.test || fail=1 +test $(stat -c %s empty.big) = $(stat -c %s cp.test) || fail=1 +rm empty.big cp.test + +# Ensure we handle extents beyond file size correctly. +# Note until we support fallocate, we will not maintain +# the file allocation. Ammend this test when fallocate is supported +fallocate -l 10000000 -n unwritten.withdata || framework_failure +dd count=10 if=/dev/urandom conv=notrunc iflag=fullblock of=unwritten.withdata +cp unwritten.withdata cp.test || fail=1 +test $(stat -c %s unwritten.withdata) = $(stat -c %s cp.test) || fail=1 +cmp unwritten.withdata cp.test || fail=1 +rm unwritten.withdata cp.test + +# The following to generate unaccounted extents followed by a hole, is not +# supported by ext4 at least. The ftruncate discards all extents not +# accounted for in the size. +# fallocate -l 10000000 -n unacc.withholes +# dd count=10 if=/dev/urandom conv=notrunc iflag=fullblock of=unacc.withholes +# truncate -s20000000 unacc.withholes + +# Ensure we handle a hole after empty extents correctly. +# Since all extents are accounted for in the size, +# we can maintain the allocation independently from +# fallocate() support. +fallocate -l 10000000 empty.withholes +truncate -s 20000000 empty.withholes +sectors_per_block=$(expr $(stat -c %o .) / 512) +cp empty.withholes cp.test || fail=1 +test $(stat -c %s empty.withholes) = $(stat -c %s cp.test) || fail=1 +# These are usually equal but can vary by an IO block due to alignment +alloc_diff=$(expr $(stat -c %b empty.withholes) - $(stat -c %b cp.test)) +alloc_diff=$(echo $alloc_diff | tr -d -- -) # abs() +test $alloc_diff -le $sectors_per_block || fail=1 +# Again with SPARSE_ALWAYS +cp --sparse=always empty.withholes cp.test || fail=1 +test $(stat -c %s empty.withholes) = $(stat -c %s cp.test) || fail=1 +# cp.test should take 0 space, but allowing for some systems +# that store default extended attributes in data blocks +test $(stat -c %b cp.test) -le $sectors_per_block || fail=1 +rm empty.withholes cp.test + +Exit $fail |