Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cciss: Fix cciss SCSI rescan code to better notice device changes

Fix cciss SCSI rescan code to better notice device changes.
If you hot-unplug a tape drive, then hot-plug a different
tape drive into the same slot in a storage enclosure,
the cciss driver wouldn't notice anything had changed, as
it was only looking at the LUN address and device type.
Now it looks at the inquiry page 0x83 device identifier,
and vendor and model strings as well.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cca.cpqcorp.net>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

authored by

scameron@beardog.cca.cpqcorp.net and committed by
Jens Axboe
905bd78f 79eb0145

+101 -52
+97 -52
drivers/block/cciss_scsi.c
··· 365 365 366 366 static int 367 367 cciss_scsi_add_entry(int ctlr, int hostno, 368 - unsigned char *scsi3addr, int devtype, 368 + struct cciss_scsi_dev_t *device, 369 369 struct scsi2map *added, int *nadded) 370 370 { 371 371 /* assumes hba[ctlr]->scsi_ctlr->lock is held */ ··· 384 384 lun = 0; 385 385 /* Is this device a non-zero lun of a multi-lun device */ 386 386 /* byte 4 of the 8-byte LUN addr will contain the logical unit no. */ 387 - if (scsi3addr[4] != 0) { 387 + if (device->scsi3addr[4] != 0) { 388 388 /* Search through our list and find the device which */ 389 389 /* has the same 8 byte LUN address, excepting byte 4. */ 390 390 /* Assign the same bus and target for this new LUN. */ 391 391 /* Use the logical unit number from the firmware. */ 392 - memcpy(addr1, scsi3addr, 8); 392 + memcpy(addr1, device->scsi3addr, 8); 393 393 addr1[4] = 0; 394 394 for (i = 0; i < n; i++) { 395 395 sd = &ccissscsi[ctlr].dev[i]; ··· 399 399 if (memcmp(addr1, addr2, 8) == 0) { 400 400 bus = sd->bus; 401 401 target = sd->target; 402 - lun = scsi3addr[4]; 402 + lun = device->scsi3addr[4]; 403 403 break; 404 404 } 405 405 } ··· 420 420 added[*nadded].lun = sd->lun; 421 421 (*nadded)++; 422 422 423 - memcpy(&sd->scsi3addr[0], scsi3addr, 8); 424 - sd->devtype = devtype; 423 + memcpy(sd->scsi3addr, device->scsi3addr, 8); 424 + memcpy(sd->vendor, device->vendor, sizeof(sd->vendor)); 425 + memcpy(sd->revision, device->revision, sizeof(sd->revision)); 426 + memcpy(sd->device_id, device->device_id, sizeof(sd->device_id)); 427 + sd->devtype = device->devtype; 428 + 425 429 ccissscsi[ctlr].ndevices++; 426 430 427 431 /* initially, (before registering with scsi layer) we don't ··· 491 487 CPQ_TAPE_UNLOCK(ctlr, flags); 492 488 } 493 489 490 + static int device_is_the_same(struct cciss_scsi_dev_t *dev1, 491 + struct cciss_scsi_dev_t *dev2) 492 + { 493 + return dev1->devtype == dev2->devtype && 494 + memcmp(dev1->scsi3addr, dev2->scsi3addr, 495 + sizeof(dev1->scsi3addr)) == 0 && 496 + memcmp(dev1->device_id, dev2->device_id, 497 + sizeof(dev1->device_id)) == 0 && 498 + memcmp(dev1->vendor, dev2->vendor, 499 + sizeof(dev1->vendor)) == 0 && 500 + memcmp(dev1->model, dev2->model, 501 + sizeof(dev1->model)) == 0 && 502 + memcmp(dev1->revision, dev2->revision, 503 + sizeof(dev1->revision)) == 0; 504 + } 505 + 494 506 static int 495 507 adjust_cciss_scsi_table(int ctlr, int hostno, 496 508 struct cciss_scsi_dev_t sd[], int nsds) ··· 552 532 for (j=0;j<nsds;j++) { 553 533 if (SCSI3ADDR_EQ(sd[j].scsi3addr, 554 534 csd->scsi3addr)) { 555 - if (sd[j].devtype == csd->devtype) 535 + if (device_is_the_same(&sd[j], csd)) 556 536 found=2; 557 537 else 558 538 found=1; ··· 568 548 cciss_scsi_remove_entry(ctlr, hostno, i, 569 549 removed, &nremoved); 570 550 /* remove ^^^, hence i not incremented */ 571 - } 572 - else if (found == 1) { /* device is different kind */ 551 + } else if (found == 1) { /* device is different in some way */ 573 552 changes++; 574 - printk("cciss%d: device c%db%dt%dl%d type changed " 575 - "(device type now %s).\n", 576 - ctlr, hostno, csd->bus, csd->target, csd->lun, 577 - scsi_device_type(csd->devtype)); 553 + printk("cciss%d: device c%db%dt%dl%d has changed.\n", 554 + ctlr, hostno, csd->bus, csd->target, csd->lun); 578 555 cciss_scsi_remove_entry(ctlr, hostno, i, 579 556 removed, &nremoved); 580 557 /* remove ^^^, hence i not incremented */ 581 - if (cciss_scsi_add_entry(ctlr, hostno, 582 - &sd[j].scsi3addr[0], sd[j].devtype, 558 + if (cciss_scsi_add_entry(ctlr, hostno, &sd[j], 583 559 added, &nadded) != 0) 584 560 /* we just removed one, so add can't fail. */ 585 561 BUG(); 586 562 csd->devtype = sd[j].devtype; 563 + memcpy(csd->device_id, sd[j].device_id, 564 + sizeof(csd->device_id)); 565 + memcpy(csd->vendor, sd[j].vendor, 566 + sizeof(csd->vendor)); 567 + memcpy(csd->model, sd[j].model, 568 + sizeof(csd->model)); 569 + memcpy(csd->revision, sd[j].revision, 570 + sizeof(csd->revision)); 587 571 } else /* device is same as it ever was, */ 588 572 i++; /* so just move along. */ 589 573 } ··· 601 577 csd = &ccissscsi[ctlr].dev[j]; 602 578 if (SCSI3ADDR_EQ(sd[i].scsi3addr, 603 579 csd->scsi3addr)) { 604 - if (sd[i].devtype == csd->devtype) 580 + if (device_is_the_same(&sd[i], csd)) 605 581 found=2; /* found device */ 606 582 else 607 583 found=1; /* found a bug. */ ··· 610 586 } 611 587 if (!found) { 612 588 changes++; 613 - if (cciss_scsi_add_entry(ctlr, hostno, 614 - 615 - &sd[i].scsi3addr[0], sd[i].devtype, 589 + if (cciss_scsi_add_entry(ctlr, hostno, &sd[i], 616 590 added, &nadded) != 0) 617 591 break; 618 592 } else if (found == 1) { 619 593 /* should never happen... */ 620 594 changes++; 621 - printk("cciss%d: device unexpectedly changed type\n", 622 - ctlr); 595 + printk(KERN_WARNING "cciss%d: device " 596 + "unexpectedly changed\n", ctlr); 623 597 /* but if it does happen, we just ignore that device */ 624 598 } 625 599 } ··· 1034 1012 1035 1013 static int 1036 1014 cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, 1037 - unsigned char *buf, unsigned char bufsize) 1015 + unsigned char page, unsigned char *buf, 1016 + unsigned char bufsize) 1038 1017 { 1039 1018 int rc; 1040 1019 CommandList_struct *cp; ··· 1055 1032 ei = cp->err_info; 1056 1033 1057 1034 cdb[0] = CISS_INQUIRY; 1058 - cdb[1] = 0; 1059 - cdb[2] = 0; 1035 + cdb[1] = (page != 0); 1036 + cdb[2] = page; 1060 1037 cdb[3] = 0; 1061 1038 cdb[4] = bufsize; 1062 1039 cdb[5] = 0; ··· 1074 1051 scsi_cmd_free(c, cp); 1075 1052 spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags); 1076 1053 return rc; 1054 + } 1055 + 1056 + /* Get the device id from inquiry page 0x83 */ 1057 + static int cciss_scsi_get_device_id(ctlr_info_t *c, unsigned char *scsi3addr, 1058 + unsigned char *device_id, int buflen) 1059 + { 1060 + int rc; 1061 + unsigned char *buf; 1062 + 1063 + if (buflen > 16) 1064 + buflen = 16; 1065 + buf = kzalloc(64, GFP_KERNEL); 1066 + if (!buf) 1067 + return -1; 1068 + rc = cciss_scsi_do_inquiry(c, scsi3addr, 0x83, buf, 64); 1069 + if (rc == 0) 1070 + memcpy(device_id, &buf[8], buflen); 1071 + kfree(buf); 1072 + return rc != 0; 1077 1073 } 1078 1074 1079 1075 static int ··· 1184 1142 ctlr_info_t *c; 1185 1143 __u32 num_luns=0; 1186 1144 unsigned char *ch; 1187 - /* unsigned char found[CCISS_MAX_SCSI_DEVS_PER_HBA]; */ 1188 - struct cciss_scsi_dev_t currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA]; 1145 + struct cciss_scsi_dev_t *currentsd, *this_device; 1189 1146 int ncurrent=0; 1190 1147 int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8; 1191 1148 int i; 1192 1149 1193 1150 c = (ctlr_info_t *) hba[cntl_num]; 1194 1151 ld_buff = kzalloc(reportlunsize, GFP_KERNEL); 1195 - if (ld_buff == NULL) { 1196 - printk(KERN_ERR "cciss: out of memory\n"); 1197 - return; 1198 - } 1199 1152 inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); 1200 - if (inq_buff == NULL) { 1201 - printk(KERN_ERR "cciss: out of memory\n"); 1202 - kfree(ld_buff); 1203 - return; 1153 + currentsd = kzalloc(sizeof(*currentsd) * 1154 + (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL); 1155 + if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) { 1156 + printk(KERN_ERR "cciss: out of memory\n"); 1157 + goto out; 1204 1158 } 1205 - 1159 + this_device = &currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA]; 1206 1160 if (cciss_scsi_do_report_phys_luns(c, ld_buff, reportlunsize) == 0) { 1207 1161 ch = &ld_buff->LUNListLength[0]; 1208 1162 num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8; ··· 1217 1179 1218 1180 1219 1181 /* adjust our table of devices */ 1220 - for(i=0; i<num_luns; i++) 1221 - { 1222 - int devtype; 1223 - 1182 + for (i = 0; i < num_luns; i++) { 1224 1183 /* for each physical lun, do an inquiry */ 1225 1184 if (ld_buff->LUN[i][3] & 0xC0) continue; 1226 1185 memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE); 1227 1186 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8); 1228 1187 1229 - if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff, 1230 - (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) { 1188 + if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, 0, inq_buff, 1189 + (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) 1231 1190 /* Inquiry failed (msg printed already) */ 1232 - devtype = 0; /* so we will skip this device. */ 1233 - } else /* what kind of device is this? */ 1234 - devtype = (inq_buff[0] & 0x1f); 1191 + continue; /* so we will skip this device. */ 1235 1192 1236 - switch (devtype) 1193 + this_device->devtype = (inq_buff[0] & 0x1f); 1194 + this_device->bus = -1; 1195 + this_device->target = -1; 1196 + this_device->lun = -1; 1197 + memcpy(this_device->scsi3addr, scsi3addr, 8); 1198 + memcpy(this_device->vendor, &inq_buff[8], 1199 + sizeof(this_device->vendor)); 1200 + memcpy(this_device->model, &inq_buff[16], 1201 + sizeof(this_device->model)); 1202 + memcpy(this_device->revision, &inq_buff[32], 1203 + sizeof(this_device->revision)); 1204 + memset(this_device->device_id, 0, 1205 + sizeof(this_device->device_id)); 1206 + cciss_scsi_get_device_id(hba[cntl_num], scsi3addr, 1207 + this_device->device_id, sizeof(this_device->device_id)); 1208 + 1209 + switch (this_device->devtype) 1237 1210 { 1238 1211 case 0x05: /* CD-ROM */ { 1239 1212 ··· 1269 1220 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { 1270 1221 printk(KERN_INFO "cciss%d: %s ignored, " 1271 1222 "too many devices.\n", cntl_num, 1272 - scsi_device_type(devtype)); 1223 + scsi_device_type(this_device->devtype)); 1273 1224 break; 1274 1225 } 1275 - memcpy(&currentsd[ncurrent].scsi3addr[0], 1276 - &scsi3addr[0], 8); 1277 - currentsd[ncurrent].devtype = devtype; 1278 - currentsd[ncurrent].bus = -1; 1279 - currentsd[ncurrent].target = -1; 1280 - currentsd[ncurrent].lun = -1; 1226 + currentsd[ncurrent] = *this_device; 1281 1227 ncurrent++; 1282 1228 break; 1283 1229 default: ··· 1284 1240 out: 1285 1241 kfree(inq_buff); 1286 1242 kfree(ld_buff); 1243 + kfree(currentsd); 1287 1244 return; 1288 1245 } 1289 1246
+4
drivers/block/cciss_scsi.h
··· 66 66 int devtype; 67 67 int bus, target, lun; /* as presented to the OS */ 68 68 unsigned char scsi3addr[8]; /* as presented to the HW */ 69 + unsigned char device_id[16]; /* from inquiry pg. 0x83 */ 70 + unsigned char vendor[8]; /* bytes 8-15 of inquiry data */ 71 + unsigned char model[16]; /* bytes 16-31 of inquiry data */ 72 + unsigned char revision[4]; /* bytes 32-35 of inquiry data */ 69 73 }; 70 74 71 75 struct cciss_scsi_hba_t {