coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: auto merging extents


From: Pádraig Brady
Subject: Re: auto merging extents
Date: Tue, 05 Apr 2011 11:33:10 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.8) Gecko/20100227 Thunderbird/3.0.3

This improves upon 
http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=3ed0384c
by handling mergeable extents that span fiemap scan boundaries.

The diff, ignoring whitespace changes, is below.
The full patch is attached.

cheers,
Pádraig.

diff --git a/src/extent-scan.c b/src/extent-scan.c
index c0a5de6..1a84bd4 100644
--- a/src/extent-scan.c
+++ b/src/extent-scan.c
@@ -67,6 +67,7 @@ extent_scan_init (int src_fd, struct extent_scan *scan)
 {
   scan->fd = src_fd;
   scan->ei_count = 0;
+  scan->ext_info = NULL;
   scan->scan_start = 0;
   scan->initial_scan_failed = false;
   scan->hit_final_extent = false;
@@ -82,10 +83,15 @@ extent_scan_init (int src_fd, struct extent_scan *scan)
 extern bool
 extent_scan_read (struct extent_scan *scan)
 {
+  unsigned int si = 0;
+  struct extent_info *last_ei IF_LINT ( = scan->ext_info);
+
+  while (true)
+    {
   union { struct fiemap f; char c[4096]; } fiemap_buf;
   struct fiemap *fiemap = &fiemap_buf.f;
   struct fiemap_extent *fm_extents = &fiemap->fm_extents[0];
-  enum { count = (sizeof fiemap_buf - sizeof *fiemap) / sizeof *fm_extents };
+      enum { count = (sizeof fiemap_buf - sizeof *fiemap)/sizeof *fm_extents };
   verify (count != 0);

   /* This is required at least to initialize fiemap->fm_start,
@@ -107,22 +113,23 @@ extent_scan_read (struct extent_scan *scan)
       return false;
     }

-  /* If 0 extents are returned, then more get_extent_table() are not needed.  
*/
+      /* If 0 extents are returned, then no more scans are needed.  */
   if (fiemap->fm_mapped_extents == 0)
     {
       scan->hit_final_extent = true;
-      return false;
+          return scan->scan_start != 0;
     }

-  scan->ei_count = fiemap->fm_mapped_extents;
-  scan->ext_info = xnmalloc (scan->ei_count, sizeof (struct extent_info));
+      assert (scan->ei_count <= SIZE_MAX - fiemap->fm_mapped_extents);
+      scan->ei_count += fiemap->fm_mapped_extents;
+      scan->ext_info = xnrealloc (scan->ext_info, scan->ei_count,
+                                  sizeof (struct extent_info));

-  unsigned int i, si = 0;
-  struct extent_info *last_ei IF_LINT ( = scan->ext_info);
-
-  for (i = 0; i < scan->ei_count; i++)
+      unsigned int i = 0;
+      for (i = 0; i < fiemap->fm_mapped_extents; i++)
     {
-      assert (fm_extents[i].fe_logical <= OFF_T_MAX - fm_extents[i].fe_length);
+          assert (fm_extents[i].fe_logical <=
+                  OFF_T_MAX - fm_extents[i].fe_length);

       if (si && last_ei->ext_flags ==
           (fm_extents[i].fe_flags & ~FIEMAP_EXTENT_LAST)
@@ -153,7 +160,7 @@ extent_scan_read (struct extent_scan *scan)
               new_logical = last_ei->ext_logical + last_ei->ext_length;
             }
           length_adjust = new_logical - fm_extents[i].fe_logical;
-          /* If an extent is contained within the previous one, just fail.  */
+              /* If an extent is contained within the previous one, fail.  */
           if (length_adjust < fm_extents[i].fe_length)
             {
               if (scan->scan_start == 0)
@@ -176,15 +183,26 @@ extent_scan_read (struct extent_scan *scan)
         }
     }

-  /* We don't bother reallocating.  We should though if we change
-     to looping through all extents, within this function.  */
-  scan->ei_count = si;
-
   if (last_ei->ext_flags & FIEMAP_EXTENT_LAST)
     scan->hit_final_extent = true;
+
+      /* If we have enough extents, discard the last as it might
+         be merged with one from the next scan.  */
+      if (si > count && !scan->hit_final_extent)
+        last_ei = scan->ext_info + --si;
+
+      /* We don't bother reallocating any trailing slots.  */
+      scan->ei_count = si;
+
+      if (scan->hit_final_extent)
+        break;
   else
     scan->scan_start = last_ei->ext_logical + last_ei->ext_length;

+      if (si >= count)
+        break;
+    }
+
   return true;
 }
 #else

Attachment: merge-all.am
Description: Text document


reply via email to

[Prev in Thread] Current Thread [Next in Thread]