]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
copy: merge similar extents before processing
authorPádraig Brady <P@draigBrady.com>
Mon, 7 Mar 2011 08:34:35 +0000 (08:34 +0000)
committerPádraig Brady <P@draigBrady.com>
Fri, 11 Mar 2011 00:50:10 +0000 (00:50 +0000)
* 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.

src/extent-scan.c

index 1ba59dbfd040529198a4d6e2a3c104314364ac46..b9520b7fa895373d30bdaee70129bf0b7325306a 100644 (file)
@@ -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;
 }