diff options
author | Pádraig Brady <P@draigBrady.com> | 2011-03-07 08:34:35 +0000 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2011-03-11 00:50:10 +0000 |
commit | 3ed0384c4171def286f5a9fbad4d89da7b0775aa (patch) | |
tree | 24197938d4e675982d1e1a79679307922ab6f154 /src | |
parent | 194c1e89a41cab90e871bf120ccf37ce4ab4dc9c (diff) | |
download | coreutils-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/extent-scan.c | 39 |
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; } |