]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
ensure zeros are written out when clearing volumes
authorPádraig Brady <pbrady@redhat.com>
Wed, 16 Jan 2013 16:23:48 +0000 (16:23 +0000)
committerPádraig Brady <pbrady@redhat.com>
Mon, 21 Jan 2013 12:16:23 +0000 (12:16 +0000)
Note O_DIRECT is _not_ used when copying from /dev/zero
and there are issues with enabling that (see 444cd542).
Therefore we arrange to have dd issue an fdatasync()
to ensure the data is persisted, lest it be discarded
from the write cache when the device is unprovisioned.

* cinder/volume/drivers/lvm.py (_copy_volume): Add 'conv=fdatasync'
to the dd option list if O_DIRECT isn't used when clearing
(which it won't as descrived above).

Fixes bug: 1100363
Change-Id: I76789557754ebaeb6d52bb34548a2ef17808fbf6

cinder/volume/drivers/lvm.py

index b1b217d73d04c6c9640527c4094f4ae8557b1766..b3bde19b8f85520ab2b7afa2be8e7615c4920ab0 100644 (file)
@@ -85,21 +85,27 @@ class LVMVolumeDriver(driver.VolumeDriver):
 
         self._try_execute(*cmd, run_as_root=True)
 
-    def _copy_volume(self, srcstr, deststr, size_in_g):
+    def _copy_volume(self, srcstr, deststr, size_in_g, clearing=False):
         # Use O_DIRECT to avoid thrashing the system buffer cache
-        direct_flags = ('iflag=direct', 'oflag=direct')
+        extra_flags = ['iflag=direct', 'oflag=direct']
 
         # Check whether O_DIRECT is supported
         try:
             self._execute('dd', 'count=0', 'if=%s' % srcstr, 'of=%s' % deststr,
-                          *direct_flags, run_as_root=True)
+                          *extra_flags, run_as_root=True)
         except exception.ProcessExecutionError:
-            direct_flags = ()
+            extra_flags = []
+
+        # If the volume is being unprovisioned then
+        # request the data is persisted before returning,
+        # so that it's not discarded from the cache.
+        if clearing and not extra_flags:
+            extra_flags.append('conv=fdatasync')
 
         # Perform the copy
         self._execute('dd', 'if=%s' % srcstr, 'of=%s' % deststr,
                       'count=%d' % (size_in_g * 1024), 'bs=1M',
-                      *direct_flags, run_as_root=True)
+                      *extra_flags, run_as_root=True)
 
     def _volume_not_present(self, volume_name):
         path_name = '%s/%s' % (FLAGS.volume_group, volume_name)
@@ -184,7 +190,8 @@ class LVMVolumeDriver(driver.VolumeDriver):
 
         if FLAGS.volume_clear == 'zero':
             if size_in_m == 0:
-                return self._copy_volume('/dev/zero', vol_path, size_in_g)
+                return self._copy_volume('/dev/zero', vol_path, size_in_g,
+                                         clearing=True)
             else:
                 clear_cmd = ['shred', '-n0', '-z', '-s%dMiB' % size_in_m]
         elif FLAGS.volume_clear == 'shred':