From 1d909844ab6cb5320c1c8e7b9d9c7764e2b7a820 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 3 Nov 2017 15:07:36 +0000 Subject: [PATCH] Fix mpr(4) panics caused by bad drive mapping tables sys/dev/mpr/mpr_mapping.c If _mapping_process_dpm_pg0 detects inconsistencies in the drive mapping table (stored in the HBA's NVRAM), abort reading it and continue to boot as if the mapping table were blank. I observed such inconsistencies in several HBAs after upgrading firmware from 14.0.0.0 to 15.0.0.0. Reviewed by: slm MFC after: 3 weeks Sponsored by: Spectra Logic Corp Differential Revision: https://reviews.freebsd.org/D12901 --- sys/dev/mpr/mpr_mapping.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/sys/dev/mpr/mpr_mapping.c b/sys/dev/mpr/mpr_mapping.c index 8154bfd6c916..6d90c79efca8 100644 --- a/sys/dev/mpr/mpr_mapping.c +++ b/sys/dev/mpr/mpr_mapping.c @@ -2207,7 +2207,7 @@ mpr_mapping_free_memory(struct mpr_softc *sc) free(sc->dpm_pg0, M_MPR); } -static void +static bool _mapping_process_dpm_pg0(struct mpr_softc *sc) { u8 missing_cnt, enc_idx; @@ -2336,7 +2336,7 @@ _mapping_process_dpm_pg0(struct mpr_softc *sc) "%s: Conflict in mapping table for " " enclosure %d\n", __func__, enc_idx); - break; + goto fail; } physical_id = dpm_entry->PhysicalIdentifier.High; @@ -2363,7 +2363,7 @@ _mapping_process_dpm_pg0(struct mpr_softc *sc) mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: " "Conflict in mapping table for device %d\n", __func__, map_idx); - break; + goto fail; } physical_id = dpm_entry->PhysicalIdentifier.High; mt_entry->physical_id = (physical_id << 32) | @@ -2375,6 +2375,18 @@ _mapping_process_dpm_pg0(struct mpr_softc *sc) mt_entry->device_info = MPR_DEV_RESERVED; } } /*close the loop for DPM table */ + return (true); + +fail: + for (entry_num = 0; entry_num < sc->max_dpm_entries; entry_num++) { + sc->dpm_entry_used[entry_num] = 0; + /* + * for IR firmware, it may be necessary to wipe out + * sc->mapping_table volumes tooi + */ + } + sc->num_enc_table_entries = 0; + return (false); } /* @@ -2614,9 +2626,11 @@ retry_read_dpm: } } - if (sc->is_dpm_enable) - _mapping_process_dpm_pg0(sc); - else { + if (sc->is_dpm_enable) { + if (!_mapping_process_dpm_pg0(sc)) + sc->is_dpm_enable = 0; + } + if (! sc->is_dpm_enable) { mpr_dprint(sc, MPR_MAPPING, "%s: DPM processing is disabled. " "Device mappings will not persist across reboots or " "resets.\n", __func__);