two patches merged here
http://bugs.gentoo.org/353907
From f69876e558782eb770955aa0b1344a5a8262548b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?=
Date: Wed, 30 Mar 2011 22:50:05 +0100
Subject: [PATCH] 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
---
NEWS | 4 ++++
src/extent-scan.c | 34 +++++++++++++++++++++++++++++++++-
src/extent-scan.h | 3 +++
tests/cp/sparse-fiemap | 4 ++--
4 files changed, 42 insertions(+), 3 deletions(-)
From 1c3654cb1fb0d8f3c422c766028d0783a40f4a42 Mon Sep 17 00:00:00 2001
From: Jim Meyering
Date: Sat, 2 Apr 2011 19:59:30 +0200
Subject: [PATCH] copy: require fiemap sync also for 2.6.38 kernels
* src/extent-scan.c (extent_need_sync): Require sync also for 2.6.38.
Without this, part of the cp/fiemap-empty test would fail both on
F15-to-be (2.6.38.1-6.fc15.x86_64) and rawhide. For details, see
http://thread.gmane.org/gmane.comp.gnu.coreutils.bugs/22190
---
src/extent-scan.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/extent-scan.c b/src/extent-scan.c
index b9520b7..f10d8e0 100644
--- a/src/extent-scan.c
+++ b/src/extent-scan.c
@@ -20,15 +20,46 @@
#include
#include
#include
+#include
#include
#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.39.
+ 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 < 39)
+ 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;
diff --git a/src/extent-scan.h b/src/extent-scan.h
index 4724b25..8728515 100644
--- a/src/extent-scan.h
+++ b/src/extent-scan.h
@@ -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;