cam_periph: Add ability to wire units to a serial number
For scsi, ata and nvme, at least, we read a serial number from the device (if the device supports it, some scsi drives do not) and record it during the *_xpt probe device state machine before it posts the AC_FOUND_DEVICE async event. For mmc, no serial number is ever retrieved, so it's always NULL. Add the ability to match this serial number during device wiring. This mechanism is competely optional, and often times using a label and/or some other attribute of the device is easier. However, other times wiring a unit to a serial number simplifies management as most monitoring tools require the *daX device and having it stable from boot to boot helps with data continuity. It can be especially helpful for nvme where no other means exists to reliably tie a ndaX device to an underlying nvme drive and namespace. A similar mechanism exists in Linux to mange device unit numbers with udev. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D32683
This commit is contained in:
parent
710a519ebb
commit
577f9aa266
@ -69,7 +69,8 @@ static u_int camperiphnextunit(struct periph_driver *p_drv,
|
||||
lun_id_t lun);
|
||||
static u_int camperiphunit(struct periph_driver *p_drv,
|
||||
path_id_t pathid, target_id_t target,
|
||||
lun_id_t lun);
|
||||
lun_id_t lun,
|
||||
const char *sn);
|
||||
static void camperiphdone(struct cam_periph *periph,
|
||||
union ccb *done_ccb);
|
||||
static void camperiphfree(struct cam_periph *periph);
|
||||
@ -273,7 +274,8 @@ cam_periph_alloc(periph_ctor_t *periph_ctor,
|
||||
free(periph, M_CAMPERIPH);
|
||||
return (CAM_REQ_INVALID);
|
||||
}
|
||||
periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id);
|
||||
periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id,
|
||||
path->device->serial_num);
|
||||
cur_periph = TAILQ_FIRST(&(*p_drv)->units);
|
||||
while (cur_periph != NULL
|
||||
&& cur_periph->unit_number < periph->unit_number)
|
||||
@ -582,7 +584,8 @@ camperiphnextunit(struct periph_driver *p_drv, u_int newunit, int wired,
|
||||
|
||||
if (newunit != dunit)
|
||||
continue;
|
||||
if (resource_int_value(dname, dunit, "lun", &val) == 0 ||
|
||||
if (resource_string_value(dname, dunit, "sn", &strval) == 0 ||
|
||||
resource_int_value(dname, dunit, "lun", &val) == 0 ||
|
||||
resource_int_value(dname, dunit, "target", &val) == 0 ||
|
||||
resource_string_value(dname, dunit, "at", &strval) == 0)
|
||||
break;
|
||||
@ -595,7 +598,7 @@ camperiphnextunit(struct periph_driver *p_drv, u_int newunit, int wired,
|
||||
|
||||
static u_int
|
||||
camperiphunit(struct periph_driver *p_drv, path_id_t pathid,
|
||||
target_id_t target, lun_id_t lun)
|
||||
target_id_t target, lun_id_t lun, const char *sn)
|
||||
{
|
||||
u_int unit;
|
||||
int wired, i, val, dunit;
|
||||
@ -624,6 +627,11 @@ camperiphunit(struct periph_driver *p_drv, path_id_t pathid,
|
||||
continue;
|
||||
wired++;
|
||||
}
|
||||
if (resource_string_value(dname, dunit, "sn", &strval) == 0) {
|
||||
if (sn == NULL || strcmp(strval, sn) != 0)
|
||||
continue;
|
||||
wired++;
|
||||
}
|
||||
if (wired != 0) {
|
||||
unit = dunit;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user