]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
avoid the buffer cache when copying volumes
authorPádraig Brady <pbrady@redhat.com>
Fri, 13 Jul 2012 17:22:17 +0000 (18:22 +0100)
committerPádraig Brady <pbrady@redhat.com>
Thu, 6 Sep 2012 19:37:41 +0000 (20:37 +0100)
The dd process when clearing volumes, was seen to starve
the system when writing to an iSCSI SAN connected over GigE.

So use O_DIRECT within the dd process so that the system
buffer cache is not impacted, which is generally the
best thing to do when streaming large amounts of data.

Also one could drop the I/O priority of the dd process
by prepending "ionice -c3". That would change the priority
from "normal" (best effort) to "idle", which means zeroing
will only proceed when there is no other I/O on the system.
It was thought best to leave scheduling decisions to the
system however, rather than specifying them explicitly.

Fixes bug: 937694
Change-Id: Ic842d7b83209c41d8ff05075990ed12e6f86283a

cinder/volume/driver.py

index 8c667aeb5561dd1cbd955acf1b5bfaca640feb90..5c7ab46fcbbebb67f84a66966807ff4c95ee96fc 100644 (file)
@@ -119,9 +119,20 @@ class VolumeDriver(object):
                           volume_name, FLAGS.volume_group, run_as_root=True)
 
     def _copy_volume(self, srcstr, deststr, size_in_g):
+        # Use O_DIRECT to avoid thrashing the system buffer cache
+        direct_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)
+        except exception.ProcessExecutionError:
+            direct_flags = ()
+
+        # Perform the copy
         self._execute('dd', 'if=%s' % srcstr, 'of=%s' % deststr,
                       'count=%d' % (size_in_g * 1024), 'bs=1M',
-                      run_as_root=True)
+                      *direct_flags, run_as_root=True)
 
     def _volume_not_present(self, volume_name):
         path_name = '%s/%s' % (FLAGS.volume_group, volume_name)