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); }