diff options
author | David Zeuthen <davidz@redhat.com> | 2009-11-20 20:21:58 -0500 |
---|---|---|
committer | Kay Sievers <kay.sievers@vrfy.org> | 2009-11-23 21:38:21 +0100 |
commit | 4e9fdfccbdd16f0cfdb5c8fa8484a8ba0f2e69d3 (patch) | |
tree | a033c562826b6a90c736837b4c128eb44f87c315 | |
parent | 5d490002b339f33a033fe09cef4272afb38da676 (diff) |
scsi_id: Export WWN and Unit Serial Number
Since the Unit Serial Number and the WWN are useful bits of
information export them as properties in the udev database. These
bits of information are often printed on the physical disk, see
http://people.freedesktop.org/~david/FUJITSU-MAY2036RC-sas-disk-picture.jpg
and displaying them separately in the UI (or in /dev/disk) might help
users identify the physical disk. This patch exports these bits of
information as ID_WWN and ID_SCSI_SERIAL.
Note that ata_id also use the ID_WWN property since commit
66094a4a7fc1d303e80785d586800eae9841502b (2009-11-04).
Also print out ID_SCSI=1 so users of the udev database knows the disk
speaks SCSI.
Here's the scsi_id output from one of my SAS disks with these changes:
ID_SCSI=1
ID_VENDOR=FUJITSU
ID_VENDOR_ENC=FUJITSU\x20
ID_MODEL=MAY2036RC
ID_MODEL_ENC=MAY2036RC\x20\x20\x20\x20\x20\x20\x20
ID_REVISION=0103
ID_TYPE=disk
ID_SERIAL=3500000e01b83f520
ID_SERIAL_SHORT=500000e01b83f520
ID_WWN=0x500000e01b83f520
ID_SCSI_SERIAL=B3G1P8500RWT
Unfortunately we can't overload ID_SERIAL for two reasons
1. ID_SERIAL (and ID_SERIAL_SHORT) exported by scsi_id isn't really
the unit serial number (as defined by SCSI) - it is sometimes the
WWN (since it is more unique than the Unit Serial Number) and
complex rules (to make the serial unique) govern what value to
use.
2. It would break existing setups if the value of ID_SERIAL changed
Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r-- | extras/scsi_id/scsi_id.c | 7 | ||||
-rw-r--r-- | extras/scsi_id/scsi_id.h | 6 | ||||
-rw-r--r-- | extras/scsi_id/scsi_serial.c | 57 |
3 files changed, 51 insertions, 19 deletions
diff --git a/extras/scsi_id/scsi_id.c b/extras/scsi_id/scsi_id.c index 72a7257113..9c5b2c3a3c 100644 --- a/extras/scsi_id/scsi_id.c +++ b/extras/scsi_id/scsi_id.c @@ -549,6 +549,7 @@ static int scsi_id(struct udev *udev, char *maj_min_dev) if (export) { char serial_str[MAX_SERIAL_LEN]; + printf("ID_SCSI=1\n"); printf("ID_VENDOR=%s\n", vendor_str); printf("ID_VENDOR_ENC=%s\n", vendor_enc_str); printf("ID_MODEL=%s\n", model_str); @@ -563,6 +564,12 @@ static int scsi_id(struct udev *udev, char *maj_min_dev) udev_util_replace_chars(serial_str, NULL); printf("ID_SERIAL_SHORT=%s\n", serial_str); } + if (dev_scsi.wwn[0] != '\0') { + printf("ID_WWN=0x%s\n", dev_scsi.wwn); + } + if (dev_scsi.unit_serial_number[0] != '\0') { + printf("ID_SCSI_SERIAL=%s\n", dev_scsi.unit_serial_number); + } goto out; } diff --git a/extras/scsi_id/scsi_id.h b/extras/scsi_id/scsi_id.h index 9fcadec173..4536cfd4f2 100644 --- a/extras/scsi_id/scsi_id.h +++ b/extras/scsi_id/scsi_id.h @@ -39,6 +39,12 @@ struct scsi_id_device { char serial[MAX_SERIAL_LEN]; char serial_short[MAX_SERIAL_LEN]; int use_sg; + + /* Always from page 0x80 e.g. 'B3G1P8500RWT' - may not be unique */ + char unit_serial_number[MAX_SERIAL_LEN]; + + /* NULs if not set - otherwise hex encoding using lower-case e.g. '50014ee0016eb572' */ + char wwn[17]; }; extern int scsi_std_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, const char *devname); diff --git a/extras/scsi_id/scsi_serial.c b/extras/scsi_id/scsi_serial.c index ab0ffd62aa..5b18b225a5 100644 --- a/extras/scsi_id/scsi_serial.c +++ b/extras/scsi_id/scsi_serial.c @@ -85,11 +85,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 +424,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,7 +481,8 @@ 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) { int i, j, s, len; @@ -561,6 +566,10 @@ 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); + } return 0; } @@ -591,12 +600,16 @@ 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) { 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); @@ -643,7 +656,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]); @@ -656,7 +670,8 @@ 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); 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, @@ -775,15 +790,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; } @@ -866,7 +885,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)) { retval = 1; goto completed; } else { @@ -882,7 +901,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)) { retval = 1; goto completed; } else { @@ -922,7 +941,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)) { /* * Success */ |