Print this page
NEX-7303 USN may contain garbage
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-3705 Need to update libses with LID/USN code from sesctld (lint fix)
NEX-3705 Need to update libses with LID/USN code from sesctld
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
*** 19,28 ****
--- 19,29 ----
* CDDL HEADER END
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/scsi/generic/commands.h>
#include <sys/scsi/impl/spc3_types.h>
*** 35,44 ****
--- 36,46 ----
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#include <scsi/libscsi.h>
+ #include <sys/byteorder.h>
#include "libscsi_impl.h"
int
libscsi_assert(const char *expr, const char *file, int line)
{
*** 296,306 ****
size_t len;
if ((ap = libscsi_action_alloc(hp, SPC3_CMD_INQUIRY,
LIBSCSI_AF_READ | LIBSCSI_AF_SILENT | LIBSCSI_AF_DIAGNOSE, &data,
offsetof(spc3_inquiry_data_t, id_vs_36[0]))) == NULL)
! return (-1);
cp = (spc3_inquiry_cdb_t *)libscsi_action_get_cdb(ap);
SCSI_WRITE16(&cp->ic_allocation_length,
offsetof(spc3_inquiry_data_t, id_vs_36[0]));
--- 298,308 ----
size_t len;
if ((ap = libscsi_action_alloc(hp, SPC3_CMD_INQUIRY,
LIBSCSI_AF_READ | LIBSCSI_AF_SILENT | LIBSCSI_AF_DIAGNOSE, &data,
offsetof(spc3_inquiry_data_t, id_vs_36[0]))) == NULL)
! return (libscsi_set_errno(hp, ESCSI_INQUIRY_FAILED));
cp = (spc3_inquiry_cdb_t *)libscsi_action_get_cdb(ap);
SCSI_WRITE16(&cp->ic_allocation_length,
offsetof(spc3_inquiry_data_t, id_vs_36[0]));
*** 322,337 ****
(tp->lst_product = libscsi_process_inquiry_string(hp,
data.id_product_id, sizeof (data.id_product_id))) == NULL ||
(tp->lst_revision = libscsi_process_inquiry_string(hp,
data.id_product_revision,
sizeof (data.id_product_revision))) == NULL) {
! return (-1);
}
return (0);
}
const char *
libscsi_vendor(libscsi_target_t *tp)
{
return (tp->lst_vendor);
}
--- 324,509 ----
(tp->lst_product = libscsi_process_inquiry_string(hp,
data.id_product_id, sizeof (data.id_product_id))) == NULL ||
(tp->lst_revision = libscsi_process_inquiry_string(hp,
data.id_product_revision,
sizeof (data.id_product_revision))) == NULL) {
! return (libscsi_set_errno(hp, ESCSI_INQUIRY_FAILED));
}
return (0);
}
+ /*
+ * A designation descriptor consists of the header followed by data.
+ * When given a pointer to the header to get to next descriptor we need to add
+ * to hdr pointer the number of data bytes plus size of the header itself.
+ */
+ #define NEXT_DESC(hdr, data_len, hdr_type) ((hdr_type *)((((uint8_t *)hdr) + \
+ data_len + sizeof (hdr_type))))
+
+ int
+ libscsi_get_inquiry_dev_id(libscsi_hdl_t *hp, libscsi_target_t *tp)
+ {
+ libscsi_action_t *ap;
+ spc3_inquiry_cdb_t *cp;
+ spc3_dev_id_vpd_page_impl_t data;
+ size_t len;
+ int des_bytes_left;
+ struct vpd_desc *cur_desc;
+ char lid[17];
+
+ if ((ap = libscsi_action_alloc(hp, SPC3_CMD_INQUIRY,
+ LIBSCSI_AF_READ | LIBSCSI_AF_SILENT | LIBSCSI_AF_DIAGNOSE, &data,
+ sizeof (spc3_dev_id_vpd_page_impl_t))) == NULL)
+ return (libscsi_set_errno(hp, ESCSI_NOMEM));
+
+ cp = (spc3_inquiry_cdb_t *)libscsi_action_get_cdb(ap);
+ cp->ic_evpd = 1; /* return vital product data for bellow page code */
+ cp->ic_page_code = DEV_ID_VPD_PAGE_CODE;
+ SCSI_WRITE16(&cp->ic_allocation_length,
+ sizeof (spc3_dev_id_vpd_page_impl_t));
+
+ if (libscsi_exec(ap, tp) != 0 ||
+ libscsi_action_get_status(ap) != 0) {
+ libscsi_action_free(ap);
+ return (libscsi_set_errno(hp, ESCSI_IO));
+ }
+
+ (void) libscsi_action_get_buffer(ap, NULL, NULL, &len);
+ libscsi_action_free(ap);
+
+ /* make sure we at least got the header */
+ if (len < offsetof(spc3_dev_id_vpd_page_impl_t, divpi_descrs[0]))
+ return (libscsi_set_errno(hp, ESCSI_BADLENGTH));
+
+ /* make sure we got the page we asked for */
+ if (data.divpi_hdr.page_code != DEV_ID_VPD_PAGE_CODE)
+ return (libscsi_set_errno(hp, ESCSI_IO));
+
+ /* check for page truncation */
+ len = ((data.divpi_hdr.page_len)[0] << 8 |
+ (data.divpi_hdr.page_len)[1]);
+ if (len > sizeof (data.divpi_descrs))
+ return (libscsi_set_errno(hp, ESCSI_BADLENGTH));
+
+ /* get the first descriptor */
+ cur_desc = (struct vpd_desc *)(data.divpi_descrs);
+ /* iterate over descriptors looking for the one we need */
+ des_bytes_left = len;
+ for (; des_bytes_left > sizeof (struct vpd_desc);
+ des_bytes_left -= (sizeof (struct vpd_desc) + cur_desc->len),
+ cur_desc = NEXT_DESC(cur_desc, cur_desc->len, struct vpd_desc)) {
+
+ /*
+ * Len for the NAA IEEE designators is 12 (aka 0x08).
+ * Designator type (id_type) 3 means a NAA formatted
+ * designator.
+ * Code set for the NAA IEEE designators is 1 (binary format).
+ * Association 0 means this designator is for a Logical Unit.
+ * Association 2 means this designator is for a SCSI device
+ * that contains the Logical Unit.
+ * With the ASSOCIATION field set to 0 or 2, device shall
+ * return the same descriptor when it is accessed through any
+ * other I_T nexus. See SPC4 7.8.6.1
+ */
+ if (cur_desc->len == 0x08 && cur_desc->id_type == 0x3 &&
+ cur_desc->code_set == 0x1 &&
+ (cur_desc->association == 0x0 ||
+ cur_desc->association == 0x2)) {
+ /* get to the data - skip the descriptor header */
+ cur_desc = (struct vpd_desc *)(((uint8_t *)cur_desc) +
+ sizeof (struct vpd_desc));
+
+ /*
+ * Bits 7-4 of the NAA formatted designator hold
+ * the designator type. We're only interested
+ * in designator type 0x5 - a 64bit value
+ * (including this type filed) that represents a
+ * NAA IEEE Registered designator that we use as
+ * the LID.
+ * See SPC4 "NAA designator format" section.
+ */
+ if (((*((uint8_t *)cur_desc)) & 0x50) != 0x50) {
+ /*
+ * This is not an IEEE Registered NAA
+ * designator, point cur_desc back to the
+ * header and skip this designator.
+ */
+ cur_desc = (struct vpd_desc * )
+ (((uint8_t *)cur_desc) -
+ sizeof (struct vpd_desc));
+ continue;
+ }
+
+ /* byte swap to have LID match what libses displays */
+ if (snprintf(lid, sizeof (lid), "%llx",
+ BE_IN64(cur_desc)) < 0)
+ return (libscsi_set_errno(hp, ESCSI_UNKNOWN));
+
+ if ((tp->lst_lid = libscsi_process_inquiry_string(hp,
+ lid, sizeof (lid))) == NULL)
+ return (libscsi_set_errno(hp, ESCSI_NOMEM));
+
+ return (0);
+ }
+ }
+
+ return (libscsi_set_errno(hp, ESCSI_NOTSUP));
+ }
+
+ /*
+ * Execute inquiry for VPD page 0x80 (unit serial #) and extract the USN
+ */
+ int
+ libscsi_get_inquiry_usn(libscsi_hdl_t *hp, libscsi_target_t *tp)
+ {
+ libscsi_action_t *ap;
+ spc3_inquiry_cdb_t *cp;
+ spc3_usn_vpd_page_impl_t data;
+ size_t len;
+
+ if ((ap = libscsi_action_alloc(hp, SPC3_CMD_INQUIRY,
+ LIBSCSI_AF_READ | LIBSCSI_AF_SILENT | LIBSCSI_AF_DIAGNOSE, &data,
+ sizeof (spc3_usn_vpd_page_impl_t))) == NULL)
+ return (libscsi_set_errno(hp, ESCSI_NOMEM));
+
+ cp = (spc3_inquiry_cdb_t *)libscsi_action_get_cdb(ap);
+ cp->ic_evpd = 1; /* return vital product data for bellow page code */
+ cp->ic_page_code = USN_VPD_PAGE_CODE;
+ SCSI_WRITE16(&cp->ic_allocation_length,
+ sizeof (spc3_usn_vpd_page_impl_t));
+
+ if (libscsi_exec(ap, tp) != 0 ||
+ libscsi_action_get_status(ap) != 0) {
+ libscsi_action_free(ap);
+ return (libscsi_set_errno(hp, ESCSI_IO));
+ }
+
+ (void) libscsi_action_get_buffer(ap, NULL, NULL, &len);
+ libscsi_action_free(ap);
+
+ /* make sure we at least got the header */
+ if (len < offsetof(spc3_usn_vpd_page_impl_t, uvpi_usn[0]))
+ return (libscsi_set_errno(hp, ESCSI_BADLENGTH));
+
+ /* make sure we got the page we asked for */
+ if (data.uvpi_hdr.page_code != USN_VPD_PAGE_CODE)
+ return (libscsi_set_errno(hp, ESCSI_IO));
+
+ /* check for USN truncation */
+ len = ((data.uvpi_hdr.page_len)[0] << 8 | (data.uvpi_hdr.page_len)[1]);
+ if (len == 0 || len > sizeof (data.uvpi_usn))
+ return (libscsi_set_errno(hp, ESCSI_BADLENGTH));
+
+ /* USN is ASCII encoded */
+ if ((tp->lst_usn = libscsi_process_inquiry_string(hp,
+ (char *)data.uvpi_usn, len)) == NULL)
+ return (libscsi_set_errno(hp, ESCSI_NOMEM));
+
+ return (0);
+ }
+
const char *
libscsi_vendor(libscsi_target_t *tp)
{
return (tp->lst_vendor);
}
*** 344,349 ****
--- 516,533 ----
const char *
libscsi_revision(libscsi_target_t *tp)
{
return (tp->lst_revision);
+ }
+
+ const char *
+ libscsi_lid(libscsi_target_t *tp)
+ {
+ return (tp->lst_lid);
+ }
+
+ const char *
+ libscsi_usn(libscsi_target_t *tp)
+ {
+ return (tp->lst_usn);
}