summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2011-03-07 08:34:35 +0000
committerPádraig Brady <P@draigBrady.com>2011-03-11 00:50:10 +0000
commit3ed0384c4171def286f5a9fbad4d89da7b0775aa (patch)
tree24197938d4e675982d1e1a79679307922ab6f154
parent194c1e89a41cab90e871bf120ccf37ce4ab4dc9c (diff)
downloadcoreutils-3ed0384c4171def286f5a9fbad4d89da7b0775aa.tar.xz
copy: merge similar extents before processing
* src/extent-scan.c (extent_scan_read): Merge adjacent extents that vary only in size, so that we may process them more efficiently. This will be especially useful when we introduce fallocate() so that we don't reproduce fragmentation in the destination.
-rw-r--r--src/extent-scan.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/src/extent-scan.c b/src/extent-scan.c
index 1ba59dbfd..b9520b7fa 100644
--- a/src/extent-scan.c
+++ b/src/extent-scan.c
@@ -85,24 +85,41 @@ extent_scan_read (struct extent_scan *scan)
scan->ei_count = fiemap->fm_mapped_extents;
scan->ext_info = xnmalloc (scan->ei_count, sizeof (struct extent_info));
- unsigned int i;
+ unsigned int i, si = 0;
+ struct extent_info *last_ei IF_LINT ( = scan->ext_info);
+
for (i = 0; i < scan->ei_count; i++)
{
assert (fm_extents[i].fe_logical <= OFF_T_MAX);
- scan->ext_info[i].ext_logical = fm_extents[i].fe_logical;
- scan->ext_info[i].ext_length = fm_extents[i].fe_length;
- scan->ext_info[i].ext_flags = fm_extents[i].fe_flags;
+ if (si && last_ei->ext_flags ==
+ (fm_extents[i].fe_flags & ~FIEMAP_EXTENT_LAST)
+ && (last_ei->ext_logical + last_ei->ext_length
+ == fm_extents[i].fe_logical))
+ {
+ /* Merge previous with last. */
+ last_ei->ext_length += fm_extents[i].fe_length;
+ /* Copy flags in case different. */
+ last_ei->ext_flags = fm_extents[i].fe_flags;
+ }
+ else
+ {
+ last_ei = scan->ext_info + si;
+ last_ei->ext_logical = fm_extents[i].fe_logical;
+ last_ei->ext_length = fm_extents[i].fe_length;
+ last_ei->ext_flags = fm_extents[i].fe_flags;
+ si++;
+ }
}
- i--;
- if (scan->ext_info[i].ext_flags & FIEMAP_EXTENT_LAST)
- {
- scan->hit_final_extent = true;
- return true;
- }
+ /* We don't bother reallocating. We should though if we change
+ to looping through all extents, within this function. */
+ scan->ei_count = si;
- scan->scan_start = fm_extents[i].fe_logical + fm_extents[i].fe_length;
+ if (last_ei->ext_flags & FIEMAP_EXTENT_LAST)
+ scan->hit_final_extent = true;
+ else
+ scan->scan_start = last_ei->ext_logical + last_ei->ext_length;
return true;
}