Fiemap: synchronize the file before invoking the ioctl
authorArtem Bityutskiy <artem.bityutskiy@intel.com>
Tue, 17 Sep 2013 11:57:35 +0000 (14:57 +0300)
committerArtem Bityutskiy <artem.bityutskiy@intel.com>
Wed, 18 Sep 2013 06:51:25 +0000 (09:51 +0300)
Early FIEMAP implementations had many bugs related to cached dirty data. And
this is why it is safer to synchronize the file before invoking FIEMAP for it.
Let's start using the 'FIEMAP_FLAG_SYNC' FIEMAP ioctl flag which does exactly
that.

Change-Id: I1698b88ed3978ffa632502ba72ad345ec8708ce0
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@intel.com>
TODO
bmaptools/Fiemap.py

diff --git a/TODO b/TODO
index c1d33edb472e05934cdce9736f296ed02cdd9394..b1925bf488eb1b0084de62888c1409f4e9fac4ef 100644 (file)
--- a/TODO
+++ b/TODO
@@ -3,11 +3,10 @@ Current TODO list, any help with these is appreciated.
 3. In setup.py, fetch the version from 'bmaptool' file.
 4. Teach the 'make_a_release.sh' script to update the version and the
    changelog.
-5. Fsync before creating the bmap file (probably use FIEMAP_FLAG_SYNC flag)
 6. Write in the man page, docs, and may be --help that it is very important
    that the image is not changed while we create the bmep file, and after we
    have created it too.
 7. Verify that unmapped areas have all zeroes to guarantee integrity.
 8. Update the man pages
 9. Teach bmaptool to update the alternate GPT partition
-10. Document GPG singatures support and supported hash function types.
+10. Document GPG singatures support and supported hash function types
index 9413358f494a991ac6e663962c5a3de88eb2d2e3..b5f7c2cf73b417f9d35ff71b013d4f963eff8352 100644 (file)
@@ -39,6 +39,9 @@ _FIEMAP_EXTENT_FORMAT = "=QQQQQLLLL"
 _FIEMAP_EXTENT_SIZE = struct.calcsize(_FIEMAP_EXTENT_FORMAT)
 # The FIEMAP ioctl number
 _FIEMAP_IOCTL = 0xC020660B
+# This FIEMAP ioctl flag which instructs the kernel to sync the file before
+# reading the block map
+_FIEMAP_FLAG_SYNC = 0x00000001
 
 # Minimum buffer which is required for 'class Fiemap' to operate
 MIN_BUFFER_SIZE = _FIEMAP_SIZE + _FIEMAP_EXTENT_SIZE
@@ -68,6 +71,9 @@ class Fiemap:
         fiemap_extent' elements which will be used when invoking the FIEMAP
         ioctl. The larger is the buffer, the less times the FIEMAP ioctl will
         be invoked.
+
+        This class synchronizes the image file every time it invokes the FIEMAP
+        ioctl in order to work-around early FIEMAP implementation kernel bugs.
         """
 
         self._f_image_needs_close = False
@@ -148,9 +154,13 @@ class Fiemap:
             raise Error("bad block number %d, should be within [0, %d]"
                         % (block, self.blocks_cnt))
 
-        # Initialize the 'struct fiemap' part of the buffer
+        # Initialize the 'struct fiemap' part of the buffer. We use the
+        # '_FIEMAP_FLAG_SYNC' flag in order to make sure the file is
+        # synchronized. The reason for this is that early FIEMAP
+        # implementations had many bugs related to cached dirty data, and
+        # synchronizing the file is a necessary work-around.
         struct.pack_into(_FIEMAP_FORMAT, self._buf, 0, block * self.block_size,
-                         count * self.block_size, 0, 0,
+                         count * self.block_size, _FIEMAP_FLAG_SYNC, 0,
                          self._fiemap_extent_cnt, 0)
 
         try: