Commit 3cf172fe authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Linus Torvalds

[PATCH] scsi_scan.c

Wondering why my CD-writer did not have a name in sysfs, I saw
that when the name is longer than 50 bytes no name at all is used.
The (much smaller) code below constructs a truncated name instead.
parent dae700f9
...@@ -543,32 +543,6 @@ static void scsi_free_sdev(struct scsi_device *sdev) ...@@ -543,32 +543,6 @@ static void scsi_free_sdev(struct scsi_device *sdev)
kfree(sdev); kfree(sdev);
} }
/**
* scsi_check_id_size - check if size fits in the driverfs name
* @sdev: Scsi_Device to use for error message
* @size: the length of the id we want to store
*
* Description:
* Use a function for this since the same code is used in various
* places, and we only create one string and call to printk.
*
* Return:
* 0 - fits
* 1 - size too large
**/
static int scsi_check_id_size(Scsi_Device *sdev, int size)
{
if (size > DEVICE_NAME_SIZE) {
printk(KERN_WARNING "scsi scan: host %d channel %d id %d lun %d"
" identifier too long, length %d, max %d. Device might"
" be improperly identified.\n", sdev->host->host_no,
sdev->channel, sdev->id, sdev->lun, size,
DEVICE_NAME_SIZE);
return 1;
} else
return 0;
}
/** /**
* scsi_get_evpd_page - get a list of supported vpd pages * scsi_get_evpd_page - get a list of supported vpd pages
* @sdev: Scsi_Device to send an INQUIRY VPD * @sdev: Scsi_Device to send an INQUIRY VPD
...@@ -715,17 +689,16 @@ static const struct scsi_id_search_values id_search_list[] = { ...@@ -715,17 +689,16 @@ static const struct scsi_id_search_values id_search_list[] = {
* scsi_check_fill_deviceid - check the id and if OK fill it * scsi_check_fill_deviceid - check the id and if OK fill it
* @sdev: device to use for error messages * @sdev: device to use for error messages
* @id_page: id descriptor for INQUIRY VPD DEVICE ID, page 0x83 * @id_page: id descriptor for INQUIRY VPD DEVICE ID, page 0x83
* @name: store the id in name * @name: store the id in name (of size DEVICE_NAME_SIZE > 26)
* @id_search: store if the id_page matches these values * @id_search: store if the id_page matches these values
* *
* Description: * Description:
* Check if @id_page matches the @id_search, if so store an id (uid) * Check if @id_page matches the @id_search, if so store an id (uid)
* into name. * into name, that is all zero on entrance.
* *
* Return: * Return:
* 0: Success * 0: Success
* 1: No match * 1: No match
* 2: Failure due to size constraints
**/ **/
static int scsi_check_fill_deviceid(Scsi_Device *sdev, char *id_page, static int scsi_check_fill_deviceid(Scsi_Device *sdev, char *id_page,
char *name, const struct scsi_id_search_values *id_search) char *name, const struct scsi_id_search_values *id_search)
...@@ -755,70 +728,41 @@ static int scsi_check_fill_deviceid(Scsi_Device *sdev, char *id_page, ...@@ -755,70 +728,41 @@ static int scsi_check_fill_deviceid(Scsi_Device *sdev, char *id_page,
if ((id_page[0] & 0x0f) != id_search->code_set) if ((id_page[0] & 0x0f) != id_search->code_set)
return 1; return 1;
name[0] = hex_str[id_search->id_type]; /*
* All OK - store ID
*/
name[0] = hex_str[id_search->id_type];
/*
* Prepend the vendor and model before the id, since the id
* might not be unique across all vendors and models.
* The same code is used below, with a different size.
*/
if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) {
strncat(name, sdev->vendor, 8);
strncat(name, sdev->model, 16);
}
i = 4;
j = strlen(name);
if ((id_page[0] & 0x0f) == SCSI_ID_ASCII) { if ((id_page[0] & 0x0f) == SCSI_ID_ASCII) {
/* /*
* ASCII descriptor. * ASCII descriptor.
*/ */
if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) { while (i < 4 + id_page[3] && j < DEVICE_NAME_SIZE-1)
/* name[j++] = id_page[i++];
* Prepend the vendor and model before the id, } else {
* since the id might not be unique across all
* vendors and models. The same code is used
* below, with a differnt size.
*
* Need 1 byte for the idtype, 1 for trailing
* '\0', 8 for vendor, 16 for model total 26, plus
* the name descriptor length.
*/
if (scsi_check_id_size(sdev, 26 + id_page[3]))
return 2;
else {
strncat(name, sdev->vendor, 8);
strncat(name, sdev->model, 16);
}
} else if (scsi_check_id_size (sdev, (2 + id_page[3])))
/*
* Need 1 byte for the idtype, 1 byte for
* the trailing '\0', plus the descriptor length.
*/
return 2;
memcpy(&name[strlen(name)], &id_page[4], id_page[3]);
return 0;
} else if ((id_page[0] & 0x0f) == SCSI_ID_BINARY) {
if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) {
/*
* Prepend the vendor and model before the id.
*/
if (scsi_check_id_size(sdev, 26 + (id_page[3] * 2)))
return 2;
else {
strncat(name, sdev->vendor, 8);
strncat(name, sdev->model, 16);
}
} else if (scsi_check_id_size(sdev, 2 + (id_page[3] * 2)))
/*
* Need 1 byte for the idtype, 1 for trailing
* '\0', 8 for vendor, 16 for model total 26, plus
* the name descriptor length.
*/
return 2;
/* /*
* Binary descriptor, convert to ASCII, using two bytes of * Binary descriptor, convert to ASCII, using two bytes of
* ASCII for each byte in the id_page. Store starting at * ASCII for each byte in the id_page.
* the end of name.
*/ */
for(i = 4, j = strlen(name); i < 4 + id_page[3]; i++) { while (i < 4 + id_page[3] && j < DEVICE_NAME_SIZE-2) {
name[j++] = hex_str[(id_page[i] & 0xf0) >> 4]; name[j++] = hex_str[(id_page[i] & 0xf0) >> 4];
name[j++] = hex_str[id_page[i] & 0x0f]; name[j++] = hex_str[id_page[i] & 0x0f];
i++;
} }
return 0;
} }
/* return 0;
* Code set must have already matched.
*/
printk(KERN_ERR "scsi scan: scsi_check_fill_deviceid unexpected state.\n");
return 1;
} }
/** /**
...@@ -834,7 +778,7 @@ static int scsi_check_fill_deviceid(Scsi_Device *sdev, char *id_page, ...@@ -834,7 +778,7 @@ static int scsi_check_fill_deviceid(Scsi_Device *sdev, char *id_page,
* 0: Failure * 0: Failure
* 1: Success * 1: Success
**/ **/
int scsi_get_deviceid(Scsi_Device *sdev, Scsi_Request *sreq) static int scsi_get_deviceid(Scsi_Device *sdev, Scsi_Request *sreq)
{ {
unsigned char *id_page; unsigned char *id_page;
unsigned char scsi_cmd[MAX_COMMAND_SIZE]; unsigned char scsi_cmd[MAX_COMMAND_SIZE];
...@@ -879,14 +823,14 @@ int scsi_get_deviceid(Scsi_Device *sdev, Scsi_Request *sreq) ...@@ -879,14 +823,14 @@ int scsi_get_deviceid(Scsi_Device *sdev, Scsi_Request *sreq)
} }
/* /*
* Search for a match in the proiritized id_search_list. * Search for a match in the prioritized id_search_list.
*/ */
for (id_idx = 0; id_idx < ARRAY_SIZE(id_search_list); id_idx++) { for (id_idx = 0; id_idx < ARRAY_SIZE(id_search_list); id_idx++) {
/* /*
* Examine each descriptor returned. There is normally only * Examine each descriptor returned. There is normally only
* one or a small number of descriptors. * one or a small number of descriptors.
*/ */
for(scnt = 4; scnt <= id_page[3] + 3; for (scnt = 4; scnt <= id_page[3] + 3;
scnt += id_page[scnt + 3] + 4) { scnt += id_page[scnt + 3] + 4) {
if ((scsi_check_fill_deviceid(sdev, &id_page[scnt], if ((scsi_check_fill_deviceid(sdev, &id_page[scnt],
sdev->sdev_driverfs_dev.name, sdev->sdev_driverfs_dev.name,
...@@ -941,12 +885,11 @@ int scsi_get_serialnumber(Scsi_Device *sdev, Scsi_Request *sreq) ...@@ -941,12 +885,11 @@ int scsi_get_serialnumber(Scsi_Device *sdev, Scsi_Request *sreq)
{ {
unsigned char *serialnumber_page; unsigned char *serialnumber_page;
unsigned char scsi_cmd[MAX_COMMAND_SIZE]; unsigned char scsi_cmd[MAX_COMMAND_SIZE];
int max_lgth = 255; const int max_lgth = 255;
int len;
retry:
serialnumber_page = kmalloc(max_lgth, GFP_ATOMIC | serialnumber_page = kmalloc(max_lgth, GFP_ATOMIC |
(sdev->host->unchecked_isa_dma) ? (sdev->host->unchecked_isa_dma) ? GFP_DMA : 0);
GFP_DMA : 0);
if (!serialnumber_page) { if (!serialnumber_page) {
printk(KERN_WARNING "scsi scan: Allocation failure identifying" printk(KERN_WARNING "scsi scan: Allocation failure identifying"
" host %d channel %d id %d lun %d, device might be" " host %d channel %d id %d lun %d, device might be"
...@@ -969,26 +912,19 @@ int scsi_get_serialnumber(Scsi_Device *sdev, Scsi_Request *sreq) ...@@ -969,26 +912,19 @@ int scsi_get_serialnumber(Scsi_Device *sdev, Scsi_Request *sreq)
if (sreq->sr_result) if (sreq->sr_result)
goto leave; goto leave;
/*
* check to see if response was truncated
*/
if (serialnumber_page[3] > max_lgth) {
max_lgth = serialnumber_page[3] + 4;
kfree(serialnumber_page);
goto retry;
}
/* /*
* Need 1 byte for SCSI_UID_SER_NUM, 1 for trailing '\0', 8 for * a check to see if response was truncated is superfluous,
* vendor, 16 for model = 26, plus serial number size. * since serialnumber_page[3] cannot be larger than 255
*/ */
if (scsi_check_id_size (sdev, (26 + serialnumber_page[3])))
goto leave;
sdev->sdev_driverfs_dev.name[0] = SCSI_UID_SER_NUM; sdev->sdev_driverfs_dev.name[0] = SCSI_UID_SER_NUM;
strncat(sdev->sdev_driverfs_dev.name, sdev->vendor, 8); strncat(sdev->sdev_driverfs_dev.name, sdev->vendor, 8);
strncat(sdev->sdev_driverfs_dev.name, sdev->model, 16); strncat(sdev->sdev_driverfs_dev.name, sdev->model, 16);
strncat(sdev->sdev_driverfs_dev.name, &serialnumber_page[4], len = serialnumber_page[3];
serialnumber_page[3]); if (len > DEVICE_NAME_SIZE-26)
len = DEVICE_NAME_SIZE-26;
strncat(sdev->sdev_driverfs_dev.name, &serialnumber_page[4], len);
kfree(serialnumber_page); kfree(serialnumber_page);
return 1; return 1;
leave: leave:
...@@ -1002,23 +938,19 @@ int scsi_get_serialnumber(Scsi_Device *sdev, Scsi_Request *sreq) ...@@ -1002,23 +938,19 @@ int scsi_get_serialnumber(Scsi_Device *sdev, Scsi_Request *sreq)
* @sdev: get a default name for this device * @sdev: get a default name for this device
* *
* Description: * Description:
* Set the name of @sdev to the concatenation of the vendor, model, * Set the name of @sdev (of size DEVICE_NAME_SIZE > 29) to the
* and revision found in @sdev. * concatenation of the vendor, model, and revision found in @sdev.
* *
* Return: * Return:
* 1: Success * 1: Success
**/ **/
int scsi_get_default_name(Scsi_Device *sdev) int scsi_get_default_name(Scsi_Device *sdev)
{ {
if (scsi_check_id_size(sdev, 29)) sdev->sdev_driverfs_dev.name[0] = SCSI_UID_UNKNOWN;
return 0; strncpy(&sdev->sdev_driverfs_dev.name[1], sdev->vendor, 8);
else { strncat(sdev->sdev_driverfs_dev.name, sdev->model, 16);
sdev->sdev_driverfs_dev.name[0] = SCSI_UID_UNKNOWN; strncat(sdev->sdev_driverfs_dev.name, sdev->rev, 4);
strncpy(&sdev->sdev_driverfs_dev.name[1], sdev->vendor, 8); return 1;
strncat(sdev->sdev_driverfs_dev.name, sdev->model, 16);
strncat(sdev->sdev_driverfs_dev.name, sdev->rev, 4);
return 1;
}
} }
/** /**
...@@ -1065,12 +997,12 @@ static void scsi_load_identifier(Scsi_Device *sdev, Scsi_Request *sreq) ...@@ -1065,12 +997,12 @@ static void scsi_load_identifier(Scsi_Device *sdev, Scsi_Request *sreq)
* XXX search high to low, since the pages are lowest to * XXX search high to low, since the pages are lowest to
* highest - page 0x83 will be after page 0x80. * highest - page 0x83 will be after page 0x80.
*/ */
for(cnt = 4; cnt <= evpd_page[3] + 3; cnt++) for (cnt = 4; cnt <= evpd_page[3] + 3; cnt++)
if (evpd_page[cnt] == 0x83) if (evpd_page[cnt] == 0x83)
if (scsi_get_deviceid(sdev, sreq)) if (scsi_get_deviceid(sdev, sreq))
goto leave; goto leave;
for(cnt = 4; cnt <= evpd_page[3] + 3; cnt++) for (cnt = 4; cnt <= evpd_page[3] + 3; cnt++)
if (evpd_page[cnt] == 0x80) if (evpd_page[cnt] == 0x80)
if (scsi_get_serialnumber(sdev, sreq)) if (scsi_get_serialnumber(sdev, sreq))
goto leave; goto leave;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment