This patch flushes IO for each SCSI device that
brick removes from the system. The patch also
flushes a multipath device prior to removing
each underlying LUN associated with the
multipath device. We were seeing kernel
IO errors in the syslog without calling flush
on the block device, during a detach for a
multipath FibreChannel copy image to volume
action.
Change-Id: I2fae3dccd4fcab22c8f59dcd297581ee9577b779
Closes-Bug:
1318950
mdev_info = self._linuxscsi.find_multipath_device(multipath_id)
devices = mdev_info['devices']
LOG.debug("devices to remove = %s" % devices)
+ self._linuxscsi.flush_multipath_device(multipath_id)
# There may have been more than 1 device mounted
# by the kernel for this volume. We have to remove
path = "/sys/block/%s/device/delete" % device.replace("/dev/", "")
if os.path.exists(path):
+ # flush any outstanding IO first
+ self.flush_device_io(device)
+
LOG.debug("Remove SCSI device(%s) with %s" % (device, path))
self.echo_scsi_command(path, "1")
self.remove_scsi_device(device['device'])
self.flush_multipath_device(mpath_dev['id'])
+ def flush_device_io(self, device):
+ """This is used to flush any remaining IO in the buffers."""
+ try:
+ LOG.debug("Flushing IO for device %s" % device)
+ self._execute('blockdev', '--flushbufs', device, run_as_root=True,
+ root_helper=self._root_helper)
+ except putils.ProcessExecutionError as exc:
+ msg = _("Failed to flush IO buffers prior to removing"
+ "device: (%(code)s)") % {'code': exc.exit_code}
+ LOG.warn(msg)
+
def flush_multipath_device(self, device):
try:
+ LOG.debug("Flush multipath device %s" % device)
self._execute('multipath', '-f', device, run_as_root=True,
root_helper=self._root_helper)
except putils.ProcessExecutionError as exc:
% (iqn, location)),
('iscsiadm -m node --rescan'),
('iscsiadm -m session --rescan'),
+ ('blockdev --flushbufs /dev/sdb'),
('tee -a /sys/block/sdb/device/delete'),
('iscsiadm -m node -T %s -p %s --op update'
' -n node.startup -v manual' % (iqn, location)),
def test_remove_scsi_device(self):
self.stubs.Set(os.path, "exists", lambda x: False)
- self.linuxscsi.remove_scsi_device("sdc")
+ self.linuxscsi.remove_scsi_device("/dev/sdc")
expected_commands = []
self.assertEqual(expected_commands, self.cmds)
self.stubs.Set(os.path, "exists", lambda x: True)
- self.linuxscsi.remove_scsi_device("sdc")
- expected_commands = [('tee -a /sys/block/sdc/device/delete')]
+ self.linuxscsi.remove_scsi_device("/dev/sdc")
+ expected_commands = [
+ ('blockdev --flushbufs /dev/sdc'),
+ ('tee -a /sys/block/sdc/device/delete')]
self.assertEqual(expected_commands, self.cmds)
def test_flush_multipath_device(self):
fake_find_multipath_device)
self.linuxscsi.remove_multipath_device('/dev/dm-3')
- expected_commands = [('tee -a /sys/block/sde/device/delete'),
- ('tee -a /sys/block/sdf/device/delete'),
- ('multipath -f 350002ac20398383d'), ]
+ expected_commands = [
+ ('blockdev --flushbufs /dev/sde'),
+ ('tee -a /sys/block/sde/device/delete'),
+ ('blockdev --flushbufs /dev/sdf'),
+ ('tee -a /sys/block/sdf/device/delete'),
+ ('multipath -f 350002ac20398383d'), ]
self.assertEqual(expected_commands, self.cmds)
def test_find_multipath_device_3par(self):