summaryrefslogtreecommitdiffstats
path: root/sys/cam/cam_xpt.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2013-06-12 13:36:20 +0000
committermav <mav@FreeBSD.org>2013-06-12 13:36:20 +0000
commitd745b9017bc6a38ecf70c8846a67ab8072fd64c4 (patch)
treed09e17bbf840c32b25e49d56a97f5305525efeeb /sys/cam/cam_xpt.c
parentceed11ef6c834cd21b2984cc4c55fe7917b0a083 (diff)
downloadFreeBSD-src-d745b9017bc6a38ecf70c8846a67ab8072fd64c4.zip
FreeBSD-src-d745b9017bc6a38ecf70c8846a67ab8072fd64c4.tar.gz
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
Diffstat (limited to 'sys/cam/cam_xpt.c')
-rw-r--r--sys/cam/cam_xpt.c47
1 files changed, 42 insertions, 5 deletions
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 5f1300f..a4c83b1 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -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;
- ret = 0;
- if (strlcpy(buf, cdai.buf, len) >= len)
- ret = EFAULT;
+ 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)
OpenPOWER on IntegriCloud