FC: Fix multipath wait issue with slow connections

With change[1], we added a mechanism to wait for multipath
device to be ready for I/O. see more info in [2].
Sometimes the connection to the storage array is slow and
the multipath device doesn't get discovered during the
os-brick operation.
This leads to failure while waiting for the multipath device
where we don't even have the multipath device populated yet
in /sys/block/<dev>/holders/dm-* resulting in the following
command executing and failing.

'multipath -C None'

This does indicate some issue with the connection but we
should not fail the operation here since we can still
complete it even with a single device discovered.

This is already handled in the iSCSI connector[3] with a check
for the sysfs dm name being populated or not.
This patch adds the same logic to FC where the dm name is
not populated but we don't want to fail the operation
because of slow connection.

Closes-Bug: #2097388

[1] https://review.opendev.org/c/openstack/os-brick/+/920516
[2] https://launchpad.net/bugs/2067949
[3] 5f5a8f7563/os_brick/initiator/connectors/iscsi.py (L788-L792)

Change-Id: Ie8860d05841cc3222871da55bdddd6b7f8135850
(cherry picked from commit 8ac46333d7)
(cherry picked from commit 557817b9b0)
(cherry picked from commit cc7e8ea978)
This commit is contained in:
Rajat Dhasmana
2025-02-05 02:07:14 +05:30
parent 1ebc6847d8
commit 62e099e445
3 changed files with 54 additions and 4 deletions

View File

@@ -290,8 +290,11 @@ class FibreChannelConnector(base.BaseLinuxConnector):
device = os.path.basename(self.device_name)
mpath = self._linuxscsi.find_sysfs_multipath_dm(
[device])
# Wait for multipath device to be ready for I/O
self._linuxscsi.wait_for_mpath_device(mpath)
if mpath:
# Sometimes the multipath device doesn't show up
# in time and we don't want to fail here.
# Wait for multipath device to be ready for I/O
self._linuxscsi.wait_for_mpath_device(mpath)
else:
device_path = self.host_device

View File

@@ -291,7 +291,6 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
connection_info['data'])
@mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device_path')
@mock.patch.object(linuxscsi.LinuxSCSI, 'wait_for_mpath_device')
def _test_connect_volume_multipath(self, get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
@@ -302,7 +301,6 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
find_mp_dev_mock,
access_mode,
should_wait_for_rw,
wait_mpath_device_mock,
find_mp_device_path_mock):
self.connector.use_multipath = True
get_fc_hbas_mock.side_effect = self.fake_get_fc_hbas
@@ -351,6 +349,49 @@ class FibreChannelConnectorTestCase(test_connector.ConnectorTestCase):
self.assertEqual(expected_commands, self.cmds)
return connection_info
@ddt.data(None, 'dm-18')
@mock.patch.object(linuxscsi.LinuxSCSI, 'wait_for_mpath_device')
@mock.patch.object(linuxscsi.LinuxSCSI, 'find_sysfs_multipath_dm')
@mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device')
@mock.patch.object(linuxscsi.LinuxSCSI, 'wait_for_rw')
@mock.patch.object(os.path, 'exists', return_value=True)
@mock.patch.object(os.path, 'realpath', return_value='/dev/sdb')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas')
@mock.patch.object(linuxfc.LinuxFibreChannel, 'get_fc_hbas_info')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_scsi_wwn')
@mock.patch.object(linuxscsi.LinuxSCSI, 'get_device_info')
@mock.patch.object(base.BaseLinuxConnector, 'check_valid_device')
def test_connect_volume_multipath_found_dm(self, sysfs_dm_name,
check_valid_device_mock,
get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
get_fc_hbas_mock,
realpath_mock,
exists_mock,
wait_for_rw_mock,
find_mp_dev_mock,
sysfs_multipath_dm_mock,
wait_mpath_device_mock):
check_valid_device_mock.return_value = True
sysfs_multipath_dm_mock.return_value = sysfs_dm_name
self._test_connect_volume_multipath(get_device_info_mock,
get_scsi_wwn_mock,
get_fc_hbas_info_mock,
get_fc_hbas_mock,
realpath_mock,
exists_mock,
wait_for_rw_mock,
find_mp_dev_mock,
'rw',
True)
sysfs_multipath_dm_mock.assert_called_once()
if sysfs_dm_name:
wait_mpath_device_mock.assert_called_once_with(sysfs_dm_name)
else:
wait_mpath_device_mock.assert_not_called()
@mock.patch.object(linuxscsi.LinuxSCSI, 'find_multipath_device')
@mock.patch.object(linuxscsi.LinuxSCSI, 'wait_for_rw')
@mock.patch.object(os.path, 'exists', return_value=True)

View File

@@ -0,0 +1,6 @@
---
fixes:
- |
`Bug #2097388 <https://bugs.launchpad.net/os-brick/+bug/2097388>`_:
Fibre Channel: Fixed issue while waiting for multipath device when
it is not populated in sysfs.