[bmap-tools] [PATCH 05/14] Filemap: introduce a FilemapSeek class

Artem Bityutskiy dedekind1 at gmail.com
Tue Jan 21 12:34:26 EST 2014


From: Artem Bityutskiy <artem.bityutskiy at intel.com>

This patch introduce a so far dummy FilemapSeek class which sill be an
alternative to FilemapFiemap. It also introduces the 'Filemap' function which
automatically selects which class will be used for getting block map. The
FIEMAP method is preferred as it is supposedly faster (at least for large
enough files).

This patch also converts all places where we creant an instance of 'Fiemap'
class to use the 'Filemap' function.

Change-Id: Ic0fcb060b5262e0314582ef3b6dc5f464e4c39a5
Signed-off-by: Artem Bityutskiy <artem.bityutskiy at intel.com>
---
 bmaptools/BmapCreate.py |  2 +-
 bmaptools/Filemap.py    | 61 ++++++++++++++++++++++++++++++++++++++++++-------
 tests/test_api_base.py  |  4 ++--
 tests/test_filemap.py   |  2 +-
 4 files changed, 57 insertions(+), 12 deletions(-)

diff --git a/bmaptools/BmapCreate.py b/bmaptools/BmapCreate.py
index e1447d4..e562a53 100644
--- a/bmaptools/BmapCreate.py
+++ b/bmaptools/BmapCreate.py
@@ -165,7 +165,7 @@ class BmapCreate:
             self._bmap_path = bmap
             self._open_bmap_file()
 
-        self.filemap = Filemap.Fiemap(self._f_image)
+        self.filemap = Filemap.filemap(self._f_image)
 
         self.image_size = self.filemap.image_size
         self.image_size_human = human_size(self.image_size)
diff --git a/bmaptools/Filemap.py b/bmaptools/Filemap.py
index 83d7412..76d2a5f 100644
--- a/bmaptools/Filemap.py
+++ b/bmaptools/Filemap.py
@@ -10,15 +10,14 @@
 # General Public License for more details.
 
 """
-This module implements python API for the FIEMAP ioctl. The FIEMAP ioctl
-allows to find holes and mapped areas in a file.
+This module implements python implements a way to get file block. Two methods
+are supported - the FIEMAP ioctl and the 'SEEK_HOLE / SEEK_DATA' features of
+the file seek syscall. The former is implemented by the 'FilemapFiemap' class,
+the latter is implemented by the 'FilemapSeek' class. Both classes provide the
+same API. The 'filemap' function automatically selects which class can be used
+and returns an instance of the class.
 """
 
-# Note, a lot of code in this module is not very readable, because it deals
-# with the rather complex FIEMAP ioctl. To understand the code, you need to
-# know the FIEMAP interface, which is documented in the
-# Documentation/filesystems/fiemap.txt file in the Linux kernel sources.
-
 # Disable the following pylint recommendations:
 #   * Too many instance attributes (R0902)
 # pylint: disable=R0902
@@ -141,6 +140,37 @@ class _FilemapBase:
 
         raise Error("the method is not implemented")
 
+class FilemapSeek(_FilemapBase):
+    """
+    This class uses the 'SEEK_HOLE' and 'SEEK_DATA' to find file block mapping.
+    """
+
+    def __init__(self, image):
+        """Refer the '_FilemapBase' class for the documentation."""
+
+        # Call the base class constructor first
+        _FilemapBase.__init__(self, image)
+
+    def block_is_mapped(self, block):
+        """Refer the '_FilemapBase' class for the documentation."""
+        raise Error("Not implemented")
+
+    def block_is_unmapped(self, block):
+        """Refer the '_FilemapBase' class for the documentation."""
+        raise Error("Not implemented")
+
+    def get_mapped_ranges(self, start, count):
+        """Refer the '_FilemapBase' class for the documentation."""
+        raise Error("Not implemented")
+
+    def get_unmapped_ranges(self, start, count):
+        """Refer the '_FilemapBase' class for the documentation."""
+        raise Error("Not implemented")
+
+# Below goes the FIEMAP ioctl implementation, which is not very readable
+# because it deals with the rather complex FIEMAP ioctl. To understand the
+# code, you need to know the FIEMAP interface, which is documented in the
+# "Documentation/filesystems/fiemap.txt" file in the Linux kernel sources.
 
 # Format string for 'struct fiemap'
 _FIEMAP_FORMAT = "=QQLLLL"
@@ -160,7 +190,7 @@ _FIEMAP_FLAG_SYNC = 0x00000001
 # FIEMAP ioctl will be invoked.
 _FIEMAP_BUFFER_SIZE = 256 * 1024
 
-class Fiemap(_FilemapBase):
+class FilemapFiemap(_FilemapBase):
     """
     This class provides API to the FIEMAP ioctl. Namely, it allows to iterate
     over all mapped blocks and over all holes.
@@ -321,3 +351,18 @@ class Fiemap(_FilemapBase):
 
         if hole_first < start + count:
             yield (hole_first, start + count - 1)
+
+def filemap(image):
+    """
+    Create and return an instance of a Filemap class - 'FilemapFiemap' or
+    'FilemapSeek', depending on what the system we run on supports. If the
+    FIEMAP ioctl is supported, an instance of the 'FilemapFiemap' class is
+    returned. Otherwise, if 'SEEK_HOLE' is supported an instance of the
+    'FilemapSeek' class is returned. If none of these are supported, the
+    function generates an 'Error' type exception.
+    """
+
+    try:
+        return FilemapFiemap(image)
+    except Error:
+        return FilemapSeek(image)
diff --git a/tests/test_api_base.py b/tests/test_api_base.py
index c073205..2a81f8d 100644
--- a/tests/test_api_base.py
+++ b/tests/test_api_base.py
@@ -51,8 +51,8 @@ def _compare_holes(file1, file2):
     The 'file1' and 'file2' arguments may be full file paths or file objects.
     """
 
-    filemap1 = Filemap.Fiemap(file1)
-    filemap2 = Filemap.Fiemap(file2)
+    filemap1 = Filemap.filemap(file1)
+    filemap2 = Filemap.filemap(file2)
 
     iterator1 = filemap1.get_unmapped_ranges(0, filemap1.blocks_cnt)
     iterator2 = filemap2.get_unmapped_ranges(0, filemap2.blocks_cnt)
diff --git a/tests/test_filemap.py b/tests/test_filemap.py
index 6919e53..a9d3cef 100644
--- a/tests/test_filemap.py
+++ b/tests/test_filemap.py
@@ -97,7 +97,7 @@ def _do_test(f_image, mapped, unmapped):
 
     # Make sure that 'Filemap' module's 'get_mapped_ranges()' returns the same
     # ranges as we have in the 'mapped' list.
-    filemap = Filemap.Fiemap(f_image)
+    filemap = Filemap.filemap(f_image)
 
     # Check both 'get_mapped_ranges()' and 'get_unmapped_ranges()' for the
     # entire file.
-- 
1.8.3.1




More information about the Bmap-tools mailing list