From 7ecf84e7958cd901b5190073afb6204f1d9c73e7 Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Fri, 8 Dec 2017 19:03:42 +0800 Subject: [PATCH 1/3] MegaRAID plugin: Fix cache information query. * MegaRAID always enable read cache. Old code treat that as read ahead cache which is not what we defined in API document. * Fix the write cache set function to handle 'Cache I/O'. * Inform user via volume_read_cache_policy_update(): read cache is always enabled, if they are looking for read ahead cache setting, they should use storcli/perccli. Signed-off-by: Gris Ge --- plugin/megaraid/megaraid.py | 77 ++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/plugin/megaraid/megaraid.py b/plugin/megaraid/megaraid.py index 8982ff9a..25b900da 100644 --- a/plugin/megaraid/megaraid.py +++ b/plugin/megaraid/megaraid.py @@ -1067,9 +1067,6 @@ def volume_cache_info(self, volume, flags=Client.FLAG_RSVD): sys_all_output = self._storcli_exec( ["/%s" % vd_path.split('/')[1], "show", "all"]) - write_cache_status = Volume.WRITE_CACHE_STATUS_WRITE_THROUGH - read_cache_status = Volume.READ_CACHE_STATUS_DISABLED - ram_size = _mega_size_to_lsm( sys_all_output['HwCfg'].get('On Board Memory Size', '0 KB')) if ram_size > 0: @@ -1081,36 +1078,42 @@ def volume_cache_info(self, volume, flags=Client.FLAG_RSVD): flag_battery_ok = True lsi_cache_setting = vd_basic_info['Cache'] - if lsi_cache_setting[0] == 'R': - read_cache_policy = Volume.READ_CACHE_POLICY_ENABLED - if flag_has_ram: - read_cache_status = Volume.READ_CACHE_STATUS_ENABLED - elif lsi_cache_setting[0:2] == 'NR': - read_cache_policy = Volume.READ_CACHE_POLICY_DISABLED - else: - raise LsmError( - ErrorNumber.PLUGIN_BUG, - "Unknown read cache %s for volume %s" % - (lsi_cache_setting, vd_path)) + # According to MegaRAID document, read I/O is always cached for direct + # I/O and cache I/O. + read_cache_policy = Volume.READ_CACHE_POLICY_ENABLED + write_cache_status = Volume.WRITE_CACHE_STATUS_WRITE_THROUGH + read_cache_status = Volume.READ_CACHE_STATUS_DISABLED - if 'AWB' in lsi_cache_setting: + if lsi_cache_setting.endswith('D'): + # Direct I/O + if 'AWB' in lsi_cache_setting: + write_cache_policy = Volume.WRITE_CACHE_POLICY_WRITE_BACK + elif 'WB' in lsi_cache_setting: + write_cache_policy = Volume.WRITE_CACHE_POLICY_AUTO + elif 'WT' in lsi_cache_setting: + write_cache_policy = Volume.WRITE_CACHE_POLICY_WRITE_THROUGH + else: + raise LsmError( + ErrorNumber.PLUGIN_BUG, + "Unknown write cache %s for volume %s" % + (lsi_cache_setting, vd_path)) + elif lsi_cache_setting.endswith('C'): + # cache I/O always caches write and read and ignore changes. write_cache_policy = Volume.WRITE_CACHE_POLICY_WRITE_BACK - if flag_has_ram: - write_cache_status = Volume.WRITE_CACHE_STATUS_WRITE_BACK - elif 'WB' in lsi_cache_setting: - # This mode means enable write cache when battery or CacheVault - # is healthy. - write_cache_policy = Volume.WRITE_CACHE_POLICY_AUTO - if flag_has_ram and flag_battery_ok: - write_cache_status = Volume.WRITE_CACHE_STATUS_WRITE_BACK - elif 'WT' in lsi_cache_setting: - write_cache_policy = Volume.WRITE_CACHE_POLICY_WRITE_THROUGH else: raise LsmError( ErrorNumber.PLUGIN_BUG, - "Unknown write cache %s for volume %s" % + "Unknown I/O type %s for volume %s" % (lsi_cache_setting, vd_path)) + if flag_has_ram: + read_cache_status = Volume.READ_CACHE_STATUS_ENABLED + if write_cache_policy == Volume.WRITE_CACHE_POLICY_WRITE_BACK: + write_cache_status = Volume.WRITE_CACHE_STATUS_WRITE_BACK + elif write_cache_policy == Volume.WRITE_CACHE_POLICY_AUTO: + if flag_battery_ok: + write_cache_status = Volume.WRITE_CACHE_STATUS_WRITE_BACK + # TODO(Gris Ge): When 'Block SSD Write Disk Cache Change' of # 'Supported Adapter Operations' is 'Yes' lsi_disk_cache_setting = vd_prop_info['Disk Cache Policy'] @@ -1162,12 +1165,27 @@ def volume_write_cache_policy_update(self, volume, wcp, """ Depending on "storcli /c0/vX set wrcache=" command. """ - cmd = [_vd_path_of_lsm_vol(volume), "set"] + vd_path = _vd_path_of_lsm_vol(volume) + # Check whether we are working on cache I/O which ignore write cache + # setting and always cache write. + vol_show_output = self._storcli_exec([vd_path, "show", "all"]) + vd_basic_info = vol_show_output[vd_path][0] + lsi_cache_setting = vd_basic_info['Cache'] + if lsi_cache_setting.endswith('C'): + flag_cache_io = True + else: + flag_cache_io = False + + cmd = [vd_path, "set"] if wcp == Volume.WRITE_CACHE_POLICY_WRITE_BACK: cmd.append("wrcache=awb") elif wcp == Volume.WRITE_CACHE_POLICY_AUTO: + if flag_cache_io: + self._storcli_exec([vd_path, "set", "iopolicy=Direct"]) cmd.append("wrcache=wb") elif wcp == Volume.WRITE_CACHE_POLICY_WRITE_THROUGH: + if flag_cache_io: + self._storcli_exec([vd_path, "set", "iopolicy=Direct"]) cmd.append("wrcache=wt") else: raise LsmError(ErrorNumber.PLUGIN_BUG, @@ -1181,8 +1199,9 @@ def volume_read_cache_policy_update(self, volume, rcp, storcli always enable read cache and no way to change it """ raise LsmError(ErrorNumber.NO_SUPPORT, - "LSI MegaRAID always enable read cache and refused to " - "change that.") + "MegaRAID always enable read cache and refused to " + "change that. You can change read ahead cache " + "setting via storcli/perccli") @_handle_errors def volume_delete(self, volume, flags=Client.FLAG_RSVD): From 9502647282e4ccb18aa41933cb8471c61240fa36 Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Fri, 8 Dec 2017 19:04:45 +0800 Subject: [PATCH 2/3] MegaRAID plugin: PEP8 clean up Signed-off-by: Gris Ge --- plugin/megaraid/megaraid.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugin/megaraid/megaraid.py b/plugin/megaraid/megaraid.py index 25b900da..c317c11d 100644 --- a/plugin/megaraid/megaraid.py +++ b/plugin/megaraid/megaraid.py @@ -85,6 +85,7 @@ def _disk_type_of(disk_show_basic_dict): return Disk.TYPE_UNKNOWN + _DISK_STATE_MAP = { 'Onln': Disk.STATUS_OK, 'Offln': Disk.STATUS_ERROR, @@ -409,7 +410,7 @@ def plugin_info(self, flags=Client.FLAG_RSVD): @_handle_errors def time_out_set(self, ms, flags=Client.FLAG_RSVD): - self._tmo_ms = ms # TODO(Gris Ge): Not implemented yet. + self._tmo_ms = ms # TODO(Gris Ge): Not implemented yet. @_handle_errors def time_out_get(self, flags=Client.FLAG_RSVD): @@ -874,7 +875,8 @@ def _vcr_cap_get(self, mega_sys_path): supported_strip_sizes = list( min_strip_size * (2 ** i) for i in range( - 0, int(math.log(int_div(max_strip_size, min_strip_size), 2) + 1))) + 0, int(math.log(int_div(max_strip_size, min_strip_size), 2) + + 1))) # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # The math above is to generate a list like: From 0dd64bd71093cf480317251628f66bd4b99ca2a1 Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Fri, 8 Dec 2017 19:05:16 +0800 Subject: [PATCH 3/3] MegaRAID plugin: Be consistent on vd_path extraction. * Always use _vd_path_of_lsm_vol() to extract private data to vd_path. Signed-off-by: Gris Ge --- plugin/megaraid/megaraid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/megaraid/megaraid.py b/plugin/megaraid/megaraid.py index c317c11d..13c05b52 100644 --- a/plugin/megaraid/megaraid.py +++ b/plugin/megaraid/megaraid.py @@ -760,7 +760,7 @@ def volume_raid_info(self, volume, flags=Client.FLAG_RSVD): ErrorNumber.INVALID_ARGUMENT, "Ilegal input volume argument: missing plugin_data property") - vd_path = volume.plugin_data + vd_path = _vd_path_of_lsm_vol(volume) vol_show_output = self._storcli_exec([vd_path, "show", "all"]) vd_basic_info = vol_show_output[vd_path][0] vd_id = int(vd_basic_info['DG/VD'].split('/')[-1])