summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <meyering@redhat.com>2011-04-20 11:21:09 +0200
committerJim Meyering <meyering@redhat.com>2011-04-20 18:48:48 +0200
commit18a474d755aa10d881243d9457d2c420c5e4ea77 (patch)
tree4df68a02135e49569c3287ca0e25b886d9ba9732 /src
parent846d826096fc8fb621d751f8b3db1da68a8bbd06 (diff)
downloadcoreutils-18a474d755aa10d881243d9457d2c420c5e4ea77.tar.xz
copy: use FIEMAP (extent_copy) only for apparently-sparse files,
to avoid the expense of extent_copy's unconditional use of FIEMAP_FLAG_SYNC. * src/copy.c (copy_reg): Do not attempt extent_copy on a file that appears to have no holes. * NEWS (Changes in behavior): Document this. At first I labeled this as a bug fix, but that would be inaccurate, considering there is no documentation of FIEMAP semantics, nor even consensus among kernel FS developers. Here's hoping SEEK_HOLE/SEEK_DATA support will soon make it into the linux kernel.
Diffstat (limited to 'src')
-rw-r--r--src/copy.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/src/copy.c b/src/copy.c
index 3db07b5b4..6edf52efc 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -993,6 +993,7 @@ copy_reg (char const *src_name, char const *dst_name,
/* Deal with sparse files. */
bool make_holes = false;
+ bool sparse_src = false;
if (S_ISREG (sb.st_mode))
{
@@ -1005,8 +1006,8 @@ copy_reg (char const *src_name, char const *dst_name,
blocks. If the file has fewer blocks than would normally be
needed for a file of its size, then at least one of the blocks in
the file is a hole. */
- if (x->sparse_mode == SPARSE_AUTO
- && is_probably_sparse (&src_open_sb))
+ sparse_src = is_probably_sparse (&src_open_sb);
+ if (x->sparse_mode == SPARSE_AUTO && sparse_src)
make_holes = true;
}
@@ -1038,21 +1039,25 @@ copy_reg (char const *src_name, char const *dst_name,
buf_alloc = xmalloc (buf_size + buf_alignment_slop);
buf = ptr_align (buf_alloc, buf_alignment);
- bool normal_copy_required;
- /* Perform an efficient extent-based copy, falling back to the
- standard copy only if the initial extent scan fails. If the
- '--sparse=never' option is specified, write all data but use
- any extents to read more efficiently. */
- if (extent_copy (source_desc, dest_desc, buf, buf_size,
- src_open_sb.st_size,
- S_ISREG (sb.st_mode) ? x->sparse_mode : SPARSE_NEVER,
- src_name, dst_name, &normal_copy_required))
- goto preserve_metadata;
-
- if (! normal_copy_required)
+ if (sparse_src)
{
- return_val = false;
- goto close_src_and_dst_desc;
+ bool normal_copy_required;
+
+ /* Perform an efficient extent-based copy, falling back to the
+ standard copy only if the initial extent scan fails. If the
+ '--sparse=never' option is specified, write all data but use
+ any extents to read more efficiently. */
+ if (extent_copy (source_desc, dest_desc, buf, buf_size,
+ src_open_sb.st_size,
+ S_ISREG (sb.st_mode) ? x->sparse_mode : SPARSE_NEVER,
+ src_name, dst_name, &normal_copy_required))
+ goto preserve_metadata;
+
+ if (! normal_copy_required)
+ {
+ return_val = false;
+ goto close_src_and_dst_desc;
+ }
}
off_t n_read;