[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
merge-all.am
Description: Text document
- Re: auto merging extents,
Pádraig Brady <=