Make CAM return and GEOM DISK pass through new GEOM::lunid attribute.
SPC-4 specification states that serial number may be property of device, but not a specific logical unit. People reported about FC storages using serial number in that way, making it unusable for purposes of LUN multipath detection. SPC-4 states that designators associated with logical unit from the VPD page 83h "Device Identification" should be used for that purpose. Report first of them in the new attribute in such preference order: NAA, EUI-64, T10 and SCSI name string. While there, make GEOM DISK properly report GEOM::ident in XML output also using d_getattr() method, if available. This fixes serial numbers reporting for SCSI disks in `geom disk list` output and confxml. Discussed with: gibbs, ken Sponsored by: iXsystems, Inc. MFC after: 2 weeks
This commit is contained in:
parent
62fed16cb9
commit
ccba710262
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=251654
@ -1096,8 +1096,9 @@ xpt_announce_quirks(struct cam_periph *periph, int quirks, char *bit_string)
|
||||
int
|
||||
xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret = -1, l;
|
||||
struct ccb_dev_advinfo cdai;
|
||||
struct scsi_vpd_id_descriptor *idd;
|
||||
|
||||
mtx_assert(path->bus->sim->mtx, MA_OWNED);
|
||||
|
||||
@ -1110,7 +1111,10 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
|
||||
cdai.buftype = CDAI_TYPE_SERIAL_NUM;
|
||||
else if (!strcmp(attr, "GEOM::physpath"))
|
||||
cdai.buftype = CDAI_TYPE_PHYS_PATH;
|
||||
else
|
||||
else if (!strcmp(attr, "GEOM::lunid")) {
|
||||
cdai.buftype = CDAI_TYPE_SCSI_DEVID;
|
||||
cdai.bufsiz = CAM_SCSI_DEVID_MAXLEN;
|
||||
} else
|
||||
goto out;
|
||||
|
||||
cdai.buf = malloc(cdai.bufsiz, M_CAMXPT, M_NOWAIT|M_ZERO);
|
||||
@ -1123,9 +1127,42 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
|
||||
cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
|
||||
if (cdai.provsiz == 0)
|
||||
goto out;
|
||||
if (cdai.buftype == CDAI_TYPE_SCSI_DEVID) {
|
||||
idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
|
||||
cdai.provsiz, scsi_devid_is_lun_naa);
|
||||
if (idd == NULL)
|
||||
idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
|
||||
cdai.provsiz, scsi_devid_is_lun_eui64);
|
||||
if (idd == NULL)
|
||||
idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
|
||||
cdai.provsiz, scsi_devid_is_lun_t10);
|
||||
if (idd == NULL)
|
||||
idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
|
||||
cdai.provsiz, scsi_devid_is_lun_name);
|
||||
if (idd == NULL)
|
||||
goto out;
|
||||
ret = 0;
|
||||
if ((idd->proto_codeset & SVPD_ID_CODESET_MASK) == SVPD_ID_CODESET_ASCII ||
|
||||
(idd->proto_codeset & SVPD_ID_CODESET_MASK) == SVPD_ID_CODESET_UTF8) {
|
||||
l = strnlen(idd->identifier, idd->length);
|
||||
if (l < len) {
|
||||
bcopy(idd->identifier, buf, l);
|
||||
buf[l] = 0;
|
||||
} else
|
||||
ret = EFAULT;
|
||||
} else {
|
||||
if (idd->length * 2 < len) {
|
||||
for (l = 0; l < idd->length; l++)
|
||||
sprintf(buf + l * 2, "%02x",
|
||||
idd->identifier[l]);
|
||||
} else
|
||||
ret = EFAULT;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
if (strlcpy(buf, cdai.buf, len) >= len)
|
||||
ret = EFAULT;
|
||||
}
|
||||
|
||||
out:
|
||||
if (cdai.buf != NULL)
|
||||
|
@ -5173,7 +5173,59 @@ scsi_devid_is_sas_target(uint8_t *bufp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
int
|
||||
scsi_devid_is_lun_eui64(uint8_t *bufp)
|
||||
{
|
||||
struct scsi_vpd_id_descriptor *descr;
|
||||
|
||||
descr = (struct scsi_vpd_id_descriptor *)bufp;
|
||||
if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN)
|
||||
return 0;
|
||||
if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_EUI64)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
scsi_devid_is_lun_naa(uint8_t *bufp)
|
||||
{
|
||||
struct scsi_vpd_id_descriptor *descr;
|
||||
|
||||
descr = (struct scsi_vpd_id_descriptor *)bufp;
|
||||
if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN)
|
||||
return 0;
|
||||
if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_NAA)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
scsi_devid_is_lun_t10(uint8_t *bufp)
|
||||
{
|
||||
struct scsi_vpd_id_descriptor *descr;
|
||||
|
||||
descr = (struct scsi_vpd_id_descriptor *)bufp;
|
||||
if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN)
|
||||
return 0;
|
||||
if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_T10)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
scsi_devid_is_lun_name(uint8_t *bufp)
|
||||
{
|
||||
struct scsi_vpd_id_descriptor *descr;
|
||||
|
||||
descr = (struct scsi_vpd_id_descriptor *)bufp;
|
||||
if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN)
|
||||
return 0;
|
||||
if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_SCSI_NAME)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct scsi_vpd_id_descriptor *
|
||||
scsi_get_devid(struct scsi_vpd_device_id *id, uint32_t page_len,
|
||||
scsi_devid_checkfn_t ck_fn)
|
||||
{
|
||||
@ -5194,7 +5246,7 @@ scsi_get_devid(struct scsi_vpd_device_id *id, uint32_t page_len,
|
||||
+ desc->length)) {
|
||||
|
||||
if (ck_fn == NULL || ck_fn((uint8_t *)desc) != 0)
|
||||
return (desc->identifier);
|
||||
return (desc);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
|
@ -1292,6 +1292,7 @@ struct scsi_vpd_id_descriptor
|
||||
#define SVPD_ID_PROTO_SHIFT 4
|
||||
#define SVPD_ID_CODESET_BINARY 0x01
|
||||
#define SVPD_ID_CODESET_ASCII 0x02
|
||||
#define SVPD_ID_CODESET_UTF8 0x03
|
||||
#define SVPD_ID_CODESET_MASK 0x0f
|
||||
u_int8_t id_type;
|
||||
#define SVPD_ID_PIV 0x80
|
||||
@ -2316,7 +2317,12 @@ u_int scsi_calc_syncparam(u_int period);
|
||||
typedef int (*scsi_devid_checkfn_t)(uint8_t *);
|
||||
int scsi_devid_is_naa_ieee_reg(uint8_t *bufp);
|
||||
int scsi_devid_is_sas_target(uint8_t *bufp);
|
||||
uint8_t * scsi_get_devid(struct scsi_vpd_device_id *id, uint32_t len,
|
||||
int scsi_devid_is_lun_eui64(uint8_t *bufp);
|
||||
int scsi_devid_is_lun_naa(uint8_t *bufp);
|
||||
int scsi_devid_is_lun_name(uint8_t *bufp);
|
||||
int scsi_devid_is_lun_t10(uint8_t *bufp);
|
||||
struct scsi_vpd_id_descriptor *
|
||||
scsi_get_devid(struct scsi_vpd_device_id *id, uint32_t len,
|
||||
scsi_devid_checkfn_t ck_fn);
|
||||
|
||||
void scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
|
@ -1056,7 +1056,8 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
|
||||
ses_setphyspath_callback_args_t args;
|
||||
int i, ret;
|
||||
struct sbuf sb;
|
||||
uint8_t *devid, *elmaddr;
|
||||
struct scsi_vpd_id_descriptor *idd;
|
||||
uint8_t *devid;
|
||||
ses_element_t *elmpriv;
|
||||
const char *c;
|
||||
|
||||
@ -1084,9 +1085,9 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
|
||||
if (cdai.ccb_h.status != CAM_REQ_CMP)
|
||||
goto out;
|
||||
|
||||
elmaddr = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
|
||||
idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
|
||||
cdai.provsiz, scsi_devid_is_naa_ieee_reg);
|
||||
if (elmaddr == NULL)
|
||||
if (idd == NULL)
|
||||
goto out;
|
||||
|
||||
if (sbuf_new(&sb, NULL, 128, SBUF_AUTOEXTEND) == NULL) {
|
||||
@ -1095,7 +1096,7 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
|
||||
}
|
||||
/* Next, generate the physical path string */
|
||||
sbuf_printf(&sb, "id1,enc@n%jx/type@%x/slot@%x",
|
||||
scsi_8btou64(elmaddr), iter->type_index,
|
||||
scsi_8btou64(idd->identifier), iter->type_index,
|
||||
iter->type_element_index);
|
||||
/* Append the element descriptor if one exists */
|
||||
elmpriv = elm->elm_private;
|
||||
|
@ -427,8 +427,11 @@ g_disk_start(struct bio *bp)
|
||||
static void
|
||||
g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp)
|
||||
{
|
||||
struct bio *bp;
|
||||
struct disk *dp;
|
||||
struct g_disk_softc *sc;
|
||||
char *buf;
|
||||
int res = 0;
|
||||
|
||||
sc = gp->softc;
|
||||
if (sc == NULL || (dp = sc->dp) == NULL)
|
||||
@ -443,7 +446,27 @@ g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g
|
||||
indent, dp->d_fwheads);
|
||||
sbuf_printf(sb, "%s<fwsectors>%u</fwsectors>\n",
|
||||
indent, dp->d_fwsectors);
|
||||
sbuf_printf(sb, "%s<ident>%s</ident>\n", indent, dp->d_ident);
|
||||
if (dp->d_getattr != NULL) {
|
||||
buf = g_malloc(DISK_IDENT_SIZE, M_WAITOK);
|
||||
bp = g_alloc_bio();
|
||||
bp->bio_disk = dp;
|
||||
bp->bio_attribute = "GEOM::ident";
|
||||
bp->bio_length = DISK_IDENT_SIZE;
|
||||
bp->bio_data = buf;
|
||||
res = dp->d_getattr(bp);
|
||||
sbuf_printf(sb, "%s<ident>%s</ident>\n", indent,
|
||||
res == 0 ? buf: dp->d_ident);
|
||||
bp->bio_attribute = "GEOM::lunid";
|
||||
bp->bio_length = DISK_IDENT_SIZE;
|
||||
bp->bio_data = buf;
|
||||
if (dp->d_getattr(bp) == 0)
|
||||
sbuf_printf(sb, "%s<lunid>%s</lunid>\n",
|
||||
indent, buf);
|
||||
g_destroy_bio(bp);
|
||||
g_free(buf);
|
||||
} else
|
||||
sbuf_printf(sb, "%s<ident>%s</ident>\n", indent,
|
||||
dp->d_ident);
|
||||
sbuf_printf(sb, "%s<descr>%s</descr>\n", indent, dp->d_descr);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user