mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-04-20 18:56:39 +02:00
copy: with fiemap copy, only sync when needed
* src/extent-scan.h (struct extent_scan): Add the fm_flags member to pass to the fiemap scan. * src/extent-scan.c (extent_need_sync): A new function used to detect Linux kernels before 2.6.38. (extent_scan_init): Add FIEMAP_FLAG_SYNC when needed. * tests/cp/sparse-fiemap: Adjust comment. * NEWS: Mention the change in behavior. Indirectly suggested by Mike Frysinger
This commit is contained in:
4
NEWS
4
NEWS
@@ -28,6 +28,10 @@ GNU coreutils NEWS -*- outline -*-
|
||||
|
||||
** Changes in behavior
|
||||
|
||||
cp now avoids syncing files when possible, when doing a FIEMAP copy.
|
||||
The sync in only needed on Linux kernels before 2.6.38.
|
||||
[The sync was introduced in coreutils-8.10]
|
||||
|
||||
df now aligns columns consistently, and no longer wraps entries
|
||||
with longer device identifiers, over two lines.
|
||||
|
||||
|
||||
@@ -20,15 +20,46 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "extent-scan.h"
|
||||
#include "xstrtol.h"
|
||||
|
||||
#ifndef HAVE_FIEMAP
|
||||
# include "fiemap.h"
|
||||
#endif
|
||||
|
||||
/* Work around Linux kernel issues on BTRFS and EXT4 before 2.6.38.
|
||||
FIXME: remove in 2013, or whenever we're pretty confident
|
||||
that the offending, unpatched kernels are no longer in use. */
|
||||
static bool
|
||||
extent_need_sync (void)
|
||||
{
|
||||
static int need_sync = -1;
|
||||
|
||||
if (need_sync == -1)
|
||||
{
|
||||
struct utsname name;
|
||||
need_sync = 0; /* No workaround by default. */
|
||||
|
||||
#ifdef __linux__
|
||||
if (uname (&name) != -1 && strncmp (name.release, "2.6.", 4) == 0)
|
||||
{
|
||||
unsigned long val;
|
||||
if (xstrtoul (name.release + 4, NULL, 10, &val, NULL) == LONGINT_OK)
|
||||
{
|
||||
if (val < 38)
|
||||
need_sync = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return need_sync;
|
||||
}
|
||||
|
||||
/* Allocate space for struct extent_scan, initialize the entries if
|
||||
necessary and return it as the input argument of extent_scan_read(). */
|
||||
extern void
|
||||
@@ -39,6 +70,7 @@ extent_scan_init (int src_fd, struct extent_scan *scan)
|
||||
scan->scan_start = 0;
|
||||
scan->initial_scan_failed = false;
|
||||
scan->hit_final_extent = false;
|
||||
scan->fm_flags = extent_need_sync () ? FIEMAP_FLAG_SYNC : 0;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -62,7 +94,7 @@ extent_scan_read (struct extent_scan *scan)
|
||||
memset (&fiemap_buf, 0, sizeof fiemap_buf);
|
||||
|
||||
fiemap->fm_start = scan->scan_start;
|
||||
fiemap->fm_flags = FIEMAP_FLAG_SYNC;
|
||||
fiemap->fm_flags = scan->fm_flags;
|
||||
fiemap->fm_extent_count = count;
|
||||
fiemap->fm_length = FIEMAP_MAX_OFFSET - scan->scan_start;
|
||||
|
||||
|
||||
@@ -41,6 +41,9 @@ struct extent_scan
|
||||
/* Next scan start offset. */
|
||||
off_t scan_start;
|
||||
|
||||
/* Flags to use for scan. */
|
||||
uint32_t fm_flags;
|
||||
|
||||
/* How many extent info returned for a scan. */
|
||||
uint32_t ei_count;
|
||||
|
||||
|
||||
@@ -69,8 +69,8 @@ for i in $(seq 1 2 21); do
|
||||
-e 'for (1..'$j') { sysseek (*F, $n, 1)' \
|
||||
-e '&& syswrite (*F, chr($_)x$n) or die "$!"}' > j1 || fail=1
|
||||
|
||||
# Note there is an implicit sync performed by cp to
|
||||
# work around bugs in EXT4 and BTRFS before Linux 2.6.38
|
||||
# Note there is an implicit sync performed by cp on Linux kernels
|
||||
# before 2.6.38 to work around bugs in EXT4 and BTRFS.
|
||||
# Note also the -s parameter to the filefrag commands below
|
||||
# for the same reasons.
|
||||
cp --sparse=always j1 j2 || fail=1
|
||||
|
||||
Reference in New Issue
Block a user