X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=extras%2Fscsi_id%2Fscsi_serial.c;h=516a6f16c5c791cd0b6dc00c3ee914af5ac55831;hb=0c0b3f97cad4c34140dda3aa85a9bc74badb4b16;hp=92359122d838413992490cf2abc1f9a796c3e43b;hpb=24355313dc9686a14a618fcd9bbdedc29c57b651;p=elogind.git diff --git a/extras/scsi_id/scsi_serial.c b/extras/scsi_id/scsi_serial.c index 92359122d..516a6f16c 100644 --- a/extras/scsi_id/scsi_serial.c +++ b/extras/scsi_id/scsi_serial.c @@ -1,16 +1,20 @@ /* - * scsi_serial.c + * Copyright (C) IBM Corp. 2003 * - * Code related to requesting and getting an id from a scsi device + * Author: Patrick Mansfield * - * Copyright (C) IBM Corp. 2003 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. * - * Author: - * Patrick Mansfield + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 of the License. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #include @@ -44,6 +48,7 @@ * is normally one or some small number of descriptors. */ static const struct scsi_id_search_values id_search_list[] = { + { SCSI_ID_TGTGROUP, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_BINARY }, { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_ASCII }, { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_BINARY }, @@ -85,11 +90,15 @@ static const char hex_str[]="0123456789abcdef"; #define SG_ERR_CAT_MEDIA_CHANGED 1 /* interpreted from sense buffer */ #define SG_ERR_CAT_RESET 2 /* interpreted from sense buffer */ #define SG_ERR_CAT_TIMEOUT 3 -#define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */ -#define SG_ERR_CAT_NOTSUPPORTED 5 /* Illegal / unsupported command */ +#define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */ +#define SG_ERR_CAT_NOTSUPPORTED 5 /* Illegal / unsupported command */ #define SG_ERR_CAT_SENSE 98 /* Something else in the sense buffer */ #define SG_ERR_CAT_OTHER 99 /* Some other error/warning */ +static int do_scsi_page80_inquiry(struct udev *udev, + struct scsi_id_device *dev_scsi, int fd, + char *serial, char *serial_short, int max_len); + static int sg_err_category_new(struct udev *udev, int scsi_status, int msg_status, int host_status, int driver_status, const @@ -420,7 +429,7 @@ static int do_scsi_page0_inquiry(struct udev *udev, return 1; } if (buffer[3] > len) { - info(udev, "%s: page 0 buffer too long %d\n", dev_scsi->kernel, buffer[3]); + info(udev, "%s: page 0 buffer too long %d\n", dev_scsi->kernel, buffer[3]); return 1; } @@ -477,15 +486,22 @@ static int check_fill_0x83_id(struct udev *udev, struct scsi_id_device *dev_scsi, unsigned char *page_83, const struct scsi_id_search_values - *id_search, char *serial, char *serial_short, int max_len) + *id_search, char *serial, char *serial_short, + int max_len, char *wwn, + char *wwn_vendor_extension, char *tgpt_group) { int i, j, s, len; /* * ASSOCIATION must be with the device (value 0) + * or with the target port for SCSI_ID_TGTPORT */ - if ((page_83[1] & 0x30) != 0) + if ((page_83[1] & 0x30) == 0x10) { + if (id_search->id_type != SCSI_ID_TGTGROUP) + return 1; + } else if ((page_83[1] & 0x30) != 0) { return 1; + } if ((page_83[1] & 0x0f) != id_search->id_type) return 1; @@ -526,6 +542,14 @@ static int check_fill_0x83_id(struct udev *udev, return 1; } + if (id_search->id_type == SCSI_ID_TGTGROUP && tgpt_group != NULL) { + unsigned int group; + + group = ((unsigned int)page_83[6] << 8) | page_83[7]; + sprintf(tgpt_group,"%x", group); + return 1; + } + serial[0] = hex_str[id_search->id_type]; /* @@ -561,6 +585,14 @@ static int check_fill_0x83_id(struct udev *udev, } strcpy(serial_short, &serial[s]); + + if (id_search->id_type == SCSI_ID_NAA && wwn != NULL) { + strncpy(wwn, &serial[s], 16); + if (wwn_vendor_extension != NULL) { + strncpy(wwn_vendor_extension, &serial[s + 16], 16); + } + } + return 0; } @@ -578,11 +610,12 @@ static int check_fill_0x83_prespc3(struct udev *udev, /* serial has been memset to zero before */ j = strlen(serial); /* j = 1; */ - for (i = 0; i < page_83[3]; ++i) { + for (i = 0; (i < page_83[3]) && (j < max_len-3); ++i) { serial[j++] = hex_str[(page_83[4+i] & 0xf0) >> 4]; serial[j++] = hex_str[ page_83[4+i] & 0x0f]; } - strcpy(serial_short, serial); + serial[max_len-1] = 0; + strncpy(serial_short, serial, max_len-1); return 0; } @@ -590,12 +623,17 @@ static int check_fill_0x83_prespc3(struct udev *udev, /* Get device identification VPD page */ static int do_scsi_page83_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, int fd, - char *serial, char *serial_short, int len) + char *serial, char *serial_short, int len, + char *unit_serial_number, char *wwn, + char *wwn_vendor_extension, char *tgpt_group) { int retval; unsigned int id_ind, j; unsigned char page_83[SCSI_INQ_BUFF_LEN]; + /* also pick up the page 80 serial number */ + do_scsi_page80_inquiry(udev, dev_scsi, fd, NULL, unit_serial_number, MAX_SERIAL_LEN); + memset(page_83, 0, SCSI_INQ_BUFF_LEN); retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN); @@ -642,7 +680,8 @@ static int do_scsi_page83_inquiry(struct udev *udev, serial, serial_short, len); /* - * Search for a match in the prioritized id_search_list. + * Search for a match in the prioritized id_search_list - since WWN ids + * come first we can pick up the WWN in check_fill_0x83_id(). */ for (id_ind = 0; id_ind < sizeof(id_search_list)/sizeof(id_search_list[0]); @@ -655,7 +694,9 @@ static int do_scsi_page83_inquiry(struct udev *udev, retval = check_fill_0x83_id(udev, dev_scsi, &page_83[j], &id_search_list[id_ind], - serial, serial_short, len); + serial, serial_short, len, + wwn, wwn_vendor_extension, + tgpt_group); dbg(udev, "%s id desc %d/%d/%d\n", dev_scsi->kernel, id_search_list[id_ind].id_type, id_search_list[id_ind].naa_type, @@ -774,15 +815,19 @@ static int do_scsi_page80_inquiry(struct udev *udev, * Prepend 'S' to avoid unlikely collision with page 0x83 vendor * specific type where we prepend '0' + vendor + model. */ - serial[0] = 'S'; - ser_ind = prepend_vendor_model(udev, dev_scsi, &serial[1]); - if (ser_ind < 0) - return 1; - len = buf[3]; - for (i = 4; i < len + 4; i++, ser_ind++) - serial[ser_ind] = buf[i]; - memcpy(serial_short, &buf[4], len); - serial_short[len] = '\0'; + len = buf[3]; + if (serial != NULL) { + serial[0] = 'S'; + ser_ind = prepend_vendor_model(udev, dev_scsi, &serial[1]); + if (ser_ind < 0) + return 1; + for (i = 4; i < len + 4; i++, ser_ind++) + serial[ser_ind] = buf[i]; + } + if (serial_short != NULL) { + memcpy(serial_short, &buf[4], len); + serial_short[len] = '\0'; + } return 0; } @@ -836,21 +881,21 @@ int scsi_get_serial(struct udev *udev, { unsigned char page0[SCSI_INQ_BUFF_LEN]; int fd = -1; - int cnt = 10; + int cnt; int ind; int retval; memset(dev_scsi->serial, 0, len); dbg(udev, "opening %s\n", devname); - while (--cnt) { - const struct timespec duration = { 0, 500 * 1000 * 1000 }; + srand((unsigned int)getpid()); + for (cnt = 20; cnt > 0; cnt--) { + struct timespec duration; fd = open(devname, O_RDONLY | O_NONBLOCK); - if (fd >= 0) - break; - info(udev, "%s: cannot open %s: %s\n", dev_scsi->kernel, devname, strerror(errno)); - if (errno != EBUSY) + if (fd >= 0 || errno != EBUSY) break; + duration.tv_sec = 0; + duration.tv_nsec = (200 * 1000 * 1000) + (rand() % 100 * 1000 * 1000); nanosleep(&duration, NULL); } if (fd < 0) @@ -865,7 +910,7 @@ int scsi_get_serial(struct udev *udev, goto completed; } } else if (page_code == PAGE_83) { - if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) { + if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { retval = 1; goto completed; } else { @@ -881,7 +926,7 @@ int scsi_get_serial(struct udev *udev, * conform to pre-SPC3 expectations. */ if (retval == 2) { - if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) { + if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { retval = 1; goto completed; } else { @@ -921,7 +966,7 @@ int scsi_get_serial(struct udev *udev, for (ind = 4; ind <= page0[3] + 3; ind++) if (page0[ind] == PAGE_83) if (!do_scsi_page83_inquiry(udev, dev_scsi, fd, - dev_scsi->serial, dev_scsi->serial_short, len)) { + dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { /* * Success */