Add a fallback to the device mapper logic. We've seen systems in the field

that are apparently misconfigured by the manufacturer and cause the mapping
logic to fail.  The fallback allows drive numbers to be assigned based on the
PHY number that they're attached to.  Add sysctls and tunables to overrid
this new behavior, but they should be considered only necessary for debugging.

Reviewed by:	 imp, smh
Obtained from:	Netflix
MFC after:	3 days
Sponsored by:	D8403
This commit is contained in:
Scott Long 2016-11-02 15:13:25 +00:00
parent 5ffb56f057
commit 4ab1cdc5ad
6 changed files with 72 additions and 14 deletions

View File

@ -1376,6 +1376,7 @@ mpr_get_tunables(struct mpr_softc *sc)
sc->max_io_pages = MPR_MAXIO_PAGES;
sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD;
sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
sc->use_phynum = 1;
/*
* Grab the global variables.
@ -1387,6 +1388,7 @@ mpr_get_tunables(struct mpr_softc *sc)
TUNABLE_INT_FETCH("hw.mpr.max_io_pages", &sc->max_io_pages);
TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu);
TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time);
TUNABLE_INT_FETCH("hw.mpr.use_phy_num", &sc->use_phynum);
/* Grab the unit-instance variables */
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level",
@ -1421,6 +1423,10 @@ mpr_get_tunables(struct mpr_softc *sc)
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.spinup_wait_time",
device_get_unit(sc->mpr_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time);
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.use_phy_num",
device_get_unit(sc->mpr_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->use_phynum);
}
static void
@ -1510,6 +1516,10 @@ mpr_setup_sysctl(struct mpr_softc *sc)
OID_AUTO, "spinup_wait_time", CTLFLAG_RD,
&sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for "
"spinup after SATA ID error");
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "use_phy_num", CTLFLAG_RD, &sc->use_phynum, 0,
"Use the phy number for enumeration");
}
int

View File

@ -757,14 +757,25 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
}
}
/*
* use_phynum:
* 1 - use the PhyNum field as a fallback to the mapping logic
* 0 - never use the PhyNum field
* -1 - only use the PhyNum field
*/
id = MPR_MAP_BAD_ID;
if (sc->use_phynum != -1)
id = mpr_mapping_get_sas_id(sc, sas_address, handle);
if (id == MPR_MAP_BAD_ID) {
printf("failure at %s:%d/%s()! Could not get ID for device "
"with handle 0x%04x\n", __FILE__, __LINE__, __func__,
handle);
if ((sc->use_phynum == 0)
|| ((id = config_page.PhyNum) > sassc->maxtargets)) {
mpr_dprint(sc, MPR_INFO, "failure at %s:%d/%s()! "
"Could not get ID for device with handle 0x%04x\n",
__FILE__, __LINE__, __func__, handle);
error = ENXIO;
goto out;
}
}
if (mprsas_check_id(sassc, id) != 0) {
device_printf(sc->mpr_dev, "Excluding target id %d\n", id);
@ -772,9 +783,16 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
goto out;
}
targ = &sassc->targets[id];
if (targ->handle != 0x0) {
mpr_dprint(sc, MPR_MAPPING, "Attempting to reuse target id "
"%d handle 0x%04x\n", id, targ->handle);
error = ENXIO;
goto out;
}
mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n",
sas_address);
targ = &sassc->targets[id];
targ->devinfo = device_info;
targ->devname = le32toh(config_page.DeviceName.High);
targ->devname = (targ->devname << 32) |

View File

@ -271,6 +271,7 @@ struct mpr_softc {
uint16_t chain_seg_size;
u_int enable_ssu;
int spinup_wait_time;
int use_phynum;
uint64_t chain_alloc_fail;
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;

View File

@ -1353,6 +1353,7 @@ mps_get_tunables(struct mps_softc *sc)
sc->max_io_pages = MPS_MAXIO_PAGES;
sc->enable_ssu = MPS_SSU_ENABLE_SSD_DISABLE_HDD;
sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
sc->use_phynum = 1;
/*
* Grab the global variables.
@ -1364,6 +1365,7 @@ mps_get_tunables(struct mps_softc *sc)
TUNABLE_INT_FETCH("hw.mps.max_io_pages", &sc->max_io_pages);
TUNABLE_INT_FETCH("hw.mps.enable_ssu", &sc->enable_ssu);
TUNABLE_INT_FETCH("hw.mps.spinup_wait_time", &sc->spinup_wait_time);
TUNABLE_INT_FETCH("hw.mps.use_phy_num", &sc->use_phynum);
/* Grab the unit-instance variables */
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.debug_level",
@ -1398,6 +1400,10 @@ mps_get_tunables(struct mps_softc *sc)
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.spinup_wait_time",
device_get_unit(sc->mps_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time);
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.use_phy_num",
device_get_unit(sc->mps_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->use_phynum);
}
static void
@ -1495,6 +1501,10 @@ mps_setup_sysctl(struct mps_softc *sc)
SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "encl_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
mps_mapping_encl_dump, "A", "Enclosure Table Dump");
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "use_phy_num", CTLFLAG_RD, &sc->use_phynum, 0,
"Use the phy number for enumeration");
}
int

View File

@ -669,14 +669,25 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
}
}
/*
* use_phynum:
* 1 - use the PhyNum field as a fallback to the mapping logic
* 0 - never use the PhyNum field
* -1 - only use the PhyNum field
*/
id = MPS_MAP_BAD_ID;
if (sc->use_phynum != -1)
id = mps_mapping_get_sas_id(sc, sas_address, handle);
if (id == MPS_MAP_BAD_ID) {
printf("failure at %s:%d/%s()! Could not get ID for device "
"with handle 0x%04x\n", __FILE__, __LINE__, __func__,
handle);
if ((sc->use_phynum == 0)
|| ((id = config_page.PhyNum) > sassc->maxtargets)) {
mps_dprint(sc, MPS_INFO, "failure at %s:%d/%s()! "
"Could not get ID for device with handle 0x%04x\n",
__FILE__, __LINE__, __func__, handle);
error = ENXIO;
goto out;
}
}
if (mpssas_check_id(sassc, id) != 0) {
device_printf(sc->mps_dev, "Excluding target id %d\n", id);
@ -684,9 +695,16 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
goto out;
}
targ = &sassc->targets[id];
if (targ->handle != 0x0) {
mps_dprint(sc, MPS_MAPPING, "Attempting to reuse target id "
"%d handle 0x%04x\n", id, targ->handle);
error = ENXIO;
goto out;
}
mps_dprint(sc, MPS_MAPPING, "SAS Address from SAS device page0 = %jx\n",
sas_address);
targ = &sassc->targets[id];
targ->devinfo = device_info;
targ->devname = le32toh(config_page.DeviceName.High);
targ->devname = (targ->devname << 32) |

View File

@ -285,6 +285,7 @@ struct mps_softc {
int chain_free_lowwater;
u_int enable_ssu;
int spinup_wait_time;
int use_phynum;
uint64_t chain_alloc_fail;
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;