diff options
author | Mike Miller <mike.miller@hp.com> | 2008-08-04 05:54:51 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-08-06 06:30:03 -0400 |
commit | a72da29b6cbc5cf918567f2a0d76df6871e94b01 (patch) | |
tree | 1ec0caea10895d9265ee7769cffea09e808c378e | |
parent | f7108f91cdcaca07c6a99777b2724093294f36ee (diff) |
cciss: make rebuild_lun_table behave better
This patch makes the rebuild_lun_table smart enough to not rip a logical
volume out from under the OS. Without this fix if a customer is running
hpacucli to monitor their storage the driver will blindly remove and re-add
the disks whenever the utility calls the CCISS_REGNEWD ioctl. Unfortunately,
both hpacucli and ACUXE call the ioctl repeatedly. Customers have reported
IO coming to a standstill. Calling the ioctl is the problem, this patch is
the fix.
Signed-off-by: Stephen M. Cameron <scameron@beardog.cca.cpqcorp.net>
Signed-off-by: Mike Miller <mike.miller@hp.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | drivers/block/cciss.c | 336 | ||||
-rw-r--r-- | drivers/block/cciss.h | 2 |
2 files changed, 216 insertions, 122 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index aeaf465922e5..f9f10a15d253 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -1330,13 +1330,46 @@ static void cciss_softirq_done(struct request *rq) | |||
1330 | spin_unlock_irqrestore(&h->lock, flags); | 1330 | spin_unlock_irqrestore(&h->lock, flags); |
1331 | } | 1331 | } |
1332 | 1332 | ||
1333 | /* This function gets the serial number of a logical drive via | ||
1334 | * inquiry page 0x83. Serial no. is 16 bytes. If the serial | ||
1335 | * number cannot be had, for whatever reason, 16 bytes of 0xff | ||
1336 | * are returned instead. | ||
1337 | */ | ||
1338 | static void cciss_get_serial_no(int ctlr, int logvol, int withirq, | ||
1339 | unsigned char *serial_no, int buflen) | ||
1340 | { | ||
1341 | #define PAGE_83_INQ_BYTES 64 | ||
1342 | int rc; | ||
1343 | unsigned char *buf; | ||
1344 | |||
1345 | if (buflen > 16) | ||
1346 | buflen = 16; | ||
1347 | memset(serial_no, 0xff, buflen); | ||
1348 | buf = kzalloc(PAGE_83_INQ_BYTES, GFP_KERNEL); | ||
1349 | if (!buf) | ||
1350 | return; | ||
1351 | memset(serial_no, 0, buflen); | ||
1352 | if (withirq) | ||
1353 | rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf, | ||
1354 | PAGE_83_INQ_BYTES, 1, logvol, 0x83, TYPE_CMD); | ||
1355 | else | ||
1356 | rc = sendcmd(CISS_INQUIRY, ctlr, buf, | ||
1357 | PAGE_83_INQ_BYTES, 1, logvol, 0x83, NULL, TYPE_CMD); | ||
1358 | if (rc == IO_OK) | ||
1359 | memcpy(serial_no, &buf[8], buflen); | ||
1360 | kfree(buf); | ||
1361 | return; | ||
1362 | } | ||
1363 | |||
1333 | /* This function will check the usage_count of the drive to be updated/added. | 1364 | /* This function will check the usage_count of the drive to be updated/added. |
1334 | * If the usage_count is zero then the drive information will be updated and | 1365 | * If the usage_count is zero and it is a heretofore unknown drive, or, |
1335 | * the disk will be re-registered with the kernel. If not then it will be | 1366 | * the drive's capacity, geometry, or serial number has changed, |
1336 | * left alone for the next reboot. The exception to this is disk 0 which | 1367 | * then the drive information will be updated and the disk will be |
1337 | * will always be left registered with the kernel since it is also the | 1368 | * re-registered with the kernel. If these conditions don't hold, |
1338 | * controller node. Any changes to disk 0 will show up on the next | 1369 | * then it will be left alone for the next reboot. The exception to this |
1339 | * reboot. | 1370 | * is disk 0 which will always be left registered with the kernel since it |
1371 | * is also the controller node. Any changes to disk 0 will show up on | ||
1372 | * the next reboot. | ||
1340 | */ | 1373 | */ |
1341 | static void cciss_update_drive_info(int ctlr, int drv_index) | 1374 | static void cciss_update_drive_info(int ctlr, int drv_index) |
1342 | { | 1375 | { |
@@ -1347,9 +1380,65 @@ static void cciss_update_drive_info(int ctlr, int drv_index) | |||
1347 | sector_t total_size; | 1380 | sector_t total_size; |
1348 | unsigned long flags = 0; | 1381 | unsigned long flags = 0; |
1349 | int ret = 0; | 1382 | int ret = 0; |
1383 | drive_info_struct *drvinfo; | ||
1384 | |||
1385 | /* Get information about the disk and modify the driver structure */ | ||
1386 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); | ||
1387 | drvinfo = kmalloc(sizeof(*drvinfo), GFP_KERNEL); | ||
1388 | if (inq_buff == NULL || drvinfo == NULL) | ||
1389 | goto mem_msg; | ||
1390 | |||
1391 | /* testing to see if 16-byte CDBs are already being used */ | ||
1392 | if (h->cciss_read == CCISS_READ_16) { | ||
1393 | cciss_read_capacity_16(h->ctlr, drv_index, 1, | ||
1394 | &total_size, &block_size); | ||
1395 | |||
1396 | } else { | ||
1397 | cciss_read_capacity(ctlr, drv_index, 1, | ||
1398 | &total_size, &block_size); | ||
1399 | |||
1400 | /* if read_capacity returns all F's this volume is >2TB */ | ||
1401 | /* in size so we switch to 16-byte CDB's for all */ | ||
1402 | /* read/write ops */ | ||
1403 | if (total_size == 0xFFFFFFFFULL) { | ||
1404 | cciss_read_capacity_16(ctlr, drv_index, 1, | ||
1405 | &total_size, &block_size); | ||
1406 | h->cciss_read = CCISS_READ_16; | ||
1407 | h->cciss_write = CCISS_WRITE_16; | ||
1408 | } else { | ||
1409 | h->cciss_read = CCISS_READ_10; | ||
1410 | h->cciss_write = CCISS_WRITE_10; | ||
1411 | } | ||
1412 | } | ||
1413 | |||
1414 | cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, | ||
1415 | inq_buff, drvinfo); | ||
1416 | drvinfo->block_size = block_size; | ||
1417 | drvinfo->nr_blocks = total_size + 1; | ||
1418 | |||
1419 | cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no, | ||
1420 | sizeof(drvinfo->serial_no)); | ||
1421 | |||
1422 | /* Is it the same disk we already know, and nothing's changed? */ | ||
1423 | if (h->drv[drv_index].raid_level != -1 && | ||
1424 | ((memcmp(drvinfo->serial_no, | ||
1425 | h->drv[drv_index].serial_no, 16) == 0) && | ||
1426 | drvinfo->block_size == h->drv[drv_index].block_size && | ||
1427 | drvinfo->nr_blocks == h->drv[drv_index].nr_blocks && | ||
1428 | drvinfo->heads == h->drv[drv_index].heads && | ||
1429 | drvinfo->sectors == h->drv[drv_index].sectors && | ||
1430 | drvinfo->cylinders == h->drv[drv_index].cylinders)) { | ||
1431 | /* The disk is unchanged, nothing to update */ | ||
1432 | goto freeret; | ||
1433 | } | ||
1434 | |||
1435 | /* Not the same disk, or something's changed, so we need to */ | ||
1436 | /* deregister it, and re-register it, if it's not in use. */ | ||
1350 | 1437 | ||
1351 | /* if the disk already exists then deregister it before proceeding */ | 1438 | /* if the disk already exists then deregister it before proceeding */ |
1352 | if (h->drv[drv_index].raid_level != -1) { | 1439 | /* (unless it's the first disk (for the controller node). */ |
1440 | if (h->drv[drv_index].raid_level != -1 && drv_index != 0) { | ||
1441 | printk(KERN_WARNING "disk %d has changed.\n", drv_index); | ||
1353 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 1442 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
1354 | h->drv[drv_index].busy_configuring = 1; | 1443 | h->drv[drv_index].busy_configuring = 1; |
1355 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | 1444 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
@@ -1364,43 +1453,23 @@ static void cciss_update_drive_info(int ctlr, int drv_index) | |||
1364 | 1453 | ||
1365 | /* If the disk is in use return */ | 1454 | /* If the disk is in use return */ |
1366 | if (ret) | 1455 | if (ret) |
1367 | return; | 1456 | goto freeret; |
1368 | 1457 | ||
1369 | /* Get information about the disk and modify the driver structure */ | 1458 | /* Save the new information from cciss_geometry_inquiry */ |
1370 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); | 1459 | /* and serial number inquiry. */ |
1371 | if (inq_buff == NULL) | 1460 | h->drv[drv_index].block_size = drvinfo->block_size; |
1372 | goto mem_msg; | 1461 | h->drv[drv_index].nr_blocks = drvinfo->nr_blocks; |
1373 | 1462 | h->drv[drv_index].heads = drvinfo->heads; | |
1374 | /* testing to see if 16-byte CDBs are already being used */ | 1463 | h->drv[drv_index].sectors = drvinfo->sectors; |
1375 | if (h->cciss_read == CCISS_READ_16) { | 1464 | h->drv[drv_index].cylinders = drvinfo->cylinders; |
1376 | cciss_read_capacity_16(h->ctlr, drv_index, 1, | 1465 | h->drv[drv_index].raid_level = drvinfo->raid_level; |
1377 | &total_size, &block_size); | 1466 | memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16); |
1378 | goto geo_inq; | ||
1379 | } | ||
1380 | |||
1381 | cciss_read_capacity(ctlr, drv_index, 1, | ||
1382 | &total_size, &block_size); | ||
1383 | |||
1384 | /* if read_capacity returns all F's this volume is >2TB in size */ | ||
1385 | /* so we switch to 16-byte CDB's for all read/write ops */ | ||
1386 | if (total_size == 0xFFFFFFFFULL) { | ||
1387 | cciss_read_capacity_16(ctlr, drv_index, 1, | ||
1388 | &total_size, &block_size); | ||
1389 | h->cciss_read = CCISS_READ_16; | ||
1390 | h->cciss_write = CCISS_WRITE_16; | ||
1391 | } else { | ||
1392 | h->cciss_read = CCISS_READ_10; | ||
1393 | h->cciss_write = CCISS_WRITE_10; | ||
1394 | } | ||
1395 | geo_inq: | ||
1396 | cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, | ||
1397 | inq_buff, &h->drv[drv_index]); | ||
1398 | 1467 | ||
1399 | ++h->num_luns; | 1468 | ++h->num_luns; |
1400 | disk = h->gendisk[drv_index]; | 1469 | disk = h->gendisk[drv_index]; |
1401 | set_capacity(disk, h->drv[drv_index].nr_blocks); | 1470 | set_capacity(disk, h->drv[drv_index].nr_blocks); |
1402 | 1471 | ||
1403 | /* if it's the controller it's already added */ | 1472 | /* if it's the controller (if drv_index == 0) it's already added */ |
1404 | if (drv_index) { | 1473 | if (drv_index) { |
1405 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); | 1474 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); |
1406 | sprintf(disk->disk_name, "cciss/c%dd%d", ctlr, drv_index); | 1475 | sprintf(disk->disk_name, "cciss/c%dd%d", ctlr, drv_index); |
@@ -1437,6 +1506,7 @@ geo_inq: | |||
1437 | 1506 | ||
1438 | freeret: | 1507 | freeret: |
1439 | kfree(inq_buff); | 1508 | kfree(inq_buff); |
1509 | kfree(drvinfo); | ||
1440 | return; | 1510 | return; |
1441 | mem_msg: | 1511 | mem_msg: |
1442 | printk(KERN_ERR "cciss: out of memory\n"); | 1512 | printk(KERN_ERR "cciss: out of memory\n"); |
@@ -1478,7 +1548,6 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | |||
1478 | int ctlr = h->ctlr; | 1548 | int ctlr = h->ctlr; |
1479 | int num_luns; | 1549 | int num_luns; |
1480 | ReportLunData_struct *ld_buff = NULL; | 1550 | ReportLunData_struct *ld_buff = NULL; |
1481 | drive_info_struct *drv = NULL; | ||
1482 | int return_code; | 1551 | int return_code; |
1483 | int listlength = 0; | 1552 | int listlength = 0; |
1484 | int i; | 1553 | int i; |
@@ -1494,98 +1563,117 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | |||
1494 | return -EBUSY; | 1563 | return -EBUSY; |
1495 | } | 1564 | } |
1496 | h->busy_configuring = 1; | 1565 | h->busy_configuring = 1; |
1566 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
1497 | 1567 | ||
1498 | /* if del_disk is NULL then we are being called to add a new disk | 1568 | if (!capable(CAP_SYS_RAWIO)) |
1499 | * and update the logical drive table. If it is not NULL then | 1569 | return -EPERM; |
1500 | * we will check if the disk is in use or not. | ||
1501 | */ | ||
1502 | if (del_disk != NULL) { | ||
1503 | drv = get_drv(del_disk); | ||
1504 | drv->busy_configuring = 1; | ||
1505 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
1506 | return_code = deregister_disk(del_disk, drv, 1); | ||
1507 | drv->busy_configuring = 0; | ||
1508 | h->busy_configuring = 0; | ||
1509 | return return_code; | ||
1510 | } else { | ||
1511 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
1512 | if (!capable(CAP_SYS_RAWIO)) | ||
1513 | return -EPERM; | ||
1514 | 1570 | ||
1515 | ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); | 1571 | ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); |
1516 | if (ld_buff == NULL) | 1572 | if (ld_buff == NULL) |
1517 | goto mem_msg; | 1573 | goto mem_msg; |
1518 | 1574 | ||
1519 | return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, | 1575 | return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, |
1520 | sizeof(ReportLunData_struct), 0, | 1576 | sizeof(ReportLunData_struct), 0, |
1521 | 0, 0, TYPE_CMD); | 1577 | 0, 0, TYPE_CMD); |
1522 | |||
1523 | if (return_code == IO_OK) { | ||
1524 | listlength = | ||
1525 | be32_to_cpu(*(__be32 *) ld_buff->LUNListLength); | ||
1526 | } else { /* reading number of logical volumes failed */ | ||
1527 | printk(KERN_WARNING "cciss: report logical volume" | ||
1528 | " command failed\n"); | ||
1529 | listlength = 0; | ||
1530 | goto freeret; | ||
1531 | } | ||
1532 | 1578 | ||
1533 | num_luns = listlength / 8; /* 8 bytes per entry */ | 1579 | if (return_code == IO_OK) |
1534 | if (num_luns > CISS_MAX_LUN) { | 1580 | listlength = be32_to_cpu(*(__be32 *) ld_buff->LUNListLength); |
1535 | num_luns = CISS_MAX_LUN; | 1581 | else { /* reading number of logical volumes failed */ |
1536 | printk(KERN_WARNING "cciss: more luns configured" | 1582 | printk(KERN_WARNING "cciss: report logical volume" |
1537 | " on controller than can be handled by" | 1583 | " command failed\n"); |
1538 | " this driver.\n"); | 1584 | listlength = 0; |
1585 | goto freeret; | ||
1586 | } | ||
1587 | |||
1588 | num_luns = listlength / 8; /* 8 bytes per entry */ | ||
1589 | if (num_luns > CISS_MAX_LUN) { | ||
1590 | num_luns = CISS_MAX_LUN; | ||
1591 | printk(KERN_WARNING "cciss: more luns configured" | ||
1592 | " on controller than can be handled by" | ||
1593 | " this driver.\n"); | ||
1594 | } | ||
1595 | |||
1596 | /* Compare controller drive array to driver's drive array */ | ||
1597 | /* to see if any drives are missing on the controller due */ | ||
1598 | /* to action of Array Config Utility (user deletes drive) */ | ||
1599 | /* and deregister logical drives which have disappeared. */ | ||
1600 | for (i = 0; i <= h->highest_lun; i++) { | ||
1601 | int j; | ||
1602 | drv_found = 0; | ||
1603 | for (j = 0; j < num_luns; j++) { | ||
1604 | memcpy(&lunid, &ld_buff->LUN[j][0], 4); | ||
1605 | lunid = le32_to_cpu(lunid); | ||
1606 | if (h->drv[i].LunID == lunid) { | ||
1607 | drv_found = 1; | ||
1608 | break; | ||
1609 | } | ||
1610 | } | ||
1611 | if (!drv_found) { | ||
1612 | /* Deregister it from the OS, it's gone. */ | ||
1613 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
1614 | h->drv[i].busy_configuring = 1; | ||
1615 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
1616 | return_code = deregister_disk(h->gendisk[i], | ||
1617 | &h->drv[i], 1); | ||
1618 | h->drv[i].busy_configuring = 0; | ||
1539 | } | 1619 | } |
1620 | } | ||
1540 | 1621 | ||
1541 | /* Compare controller drive array to drivers drive array. | 1622 | /* Compare controller drive array to driver's drive array. |
1542 | * Check for updates in the drive information and any new drives | 1623 | * Check for updates in the drive information and any new drives |
1543 | * on the controller. | 1624 | * on the controller due to ACU adding logical drives, or changing |
1544 | */ | 1625 | * a logical drive's size, etc. Reregister any new/changed drives |
1545 | for (i = 0; i < num_luns; i++) { | 1626 | */ |
1546 | int j; | 1627 | for (i = 0; i < num_luns; i++) { |
1628 | int j; | ||
1547 | 1629 | ||
1548 | drv_found = 0; | 1630 | drv_found = 0; |
1549 | 1631 | ||
1550 | lunid = (0xff & | 1632 | memcpy(&lunid, &ld_buff->LUN[i][0], 4); |
1551 | (unsigned int)(ld_buff->LUN[i][3])) << 24; | 1633 | lunid = le32_to_cpu(lunid); |
1552 | lunid |= (0xff & | ||
1553 | (unsigned int)(ld_buff->LUN[i][2])) << 16; | ||
1554 | lunid |= (0xff & | ||
1555 | (unsigned int)(ld_buff->LUN[i][1])) << 8; | ||
1556 | lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); | ||
1557 | 1634 | ||
1558 | /* Find if the LUN is already in the drive array | 1635 | /* Find if the LUN is already in the drive array |
1559 | * of the controller. If so then update its info | 1636 | * of the driver. If so then update its info |
1560 | * if not is use. If it does not exist then find | 1637 | * if not in use. If it does not exist then find |
1561 | * the first free index and add it. | 1638 | * the first free index and add it. |
1562 | */ | 1639 | */ |
1563 | for (j = 0; j <= h->highest_lun; j++) { | 1640 | for (j = 0; j <= h->highest_lun; j++) { |
1564 | if (h->drv[j].LunID == lunid) { | 1641 | if (h->drv[j].raid_level != -1 && |
1565 | drv_index = j; | 1642 | h->drv[j].LunID == lunid) { |
1566 | drv_found = 1; | 1643 | drv_index = j; |
1567 | } | 1644 | drv_found = 1; |
1645 | break; | ||
1568 | } | 1646 | } |
1647 | } | ||
1569 | 1648 | ||
1570 | /* check if the drive was found already in the array */ | 1649 | /* check if the drive was found already in the array */ |
1571 | if (!drv_found) { | 1650 | if (!drv_found) { |
1572 | drv_index = cciss_find_free_drive_index(ctlr); | 1651 | drv_index = cciss_find_free_drive_index(ctlr); |
1573 | if (drv_index == -1) | 1652 | if (drv_index == -1) |
1574 | goto freeret; | 1653 | goto freeret; |
1575 | 1654 | /*Check if the gendisk needs to be allocated */ | |
1576 | /*Check if the gendisk needs to be allocated */ | 1655 | if (!h->gendisk[drv_index]) { |
1656 | h->gendisk[drv_index] = | ||
1657 | alloc_disk(1 << NWD_SHIFT); | ||
1577 | if (!h->gendisk[drv_index]){ | 1658 | if (!h->gendisk[drv_index]){ |
1578 | h->gendisk[drv_index] = alloc_disk(1 << NWD_SHIFT); | 1659 | printk(KERN_ERR "cciss: could not " |
1579 | if (!h->gendisk[drv_index]){ | 1660 | "allocate new disk %d\n", |
1580 | printk(KERN_ERR "cciss: could not allocate new disk %d\n", drv_index); | 1661 | drv_index); |
1581 | goto mem_msg; | 1662 | goto mem_msg; |
1582 | } | ||
1583 | } | 1663 | } |
1584 | } | 1664 | } |
1585 | h->drv[drv_index].LunID = lunid; | 1665 | h->drv[drv_index].LunID = lunid; |
1586 | cciss_update_drive_info(ctlr, drv_index); | 1666 | |
1587 | } /* end for */ | 1667 | /* Don't need to mark this busy because nobody |
1588 | } /* end else */ | 1668 | * else knows about this disk yet to contend |
1669 | * for access to it. | ||
1670 | */ | ||
1671 | h->drv[drv_index].busy_configuring = 0; | ||
1672 | wmb(); | ||
1673 | |||
1674 | } | ||
1675 | cciss_update_drive_info(ctlr, drv_index); | ||
1676 | } /* end for */ | ||
1589 | 1677 | ||
1590 | freeret: | 1678 | freeret: |
1591 | kfree(ld_buff); | 1679 | kfree(ld_buff); |
@@ -1597,6 +1685,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | |||
1597 | return -1; | 1685 | return -1; |
1598 | mem_msg: | 1686 | mem_msg: |
1599 | printk(KERN_ERR "cciss: out of memory\n"); | 1687 | printk(KERN_ERR "cciss: out of memory\n"); |
1688 | h->busy_configuring = 0; | ||
1600 | goto freeret; | 1689 | goto freeret; |
1601 | } | 1690 | } |
1602 | 1691 | ||
@@ -1652,15 +1741,15 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, | |||
1652 | * other than disk 0 we will call put_disk. We do not | 1741 | * other than disk 0 we will call put_disk. We do not |
1653 | * do this for disk 0 as we need it to be able to | 1742 | * do this for disk 0 as we need it to be able to |
1654 | * configure the controller. | 1743 | * configure the controller. |
1655 | */ | 1744 | */ |
1656 | if (clear_all){ | 1745 | if (clear_all){ |
1657 | /* This isn't pretty, but we need to find the | 1746 | /* This isn't pretty, but we need to find the |
1658 | * disk in our array and NULL our the pointer. | 1747 | * disk in our array and NULL our the pointer. |
1659 | * This is so that we will call alloc_disk if | 1748 | * This is so that we will call alloc_disk if |
1660 | * this index is used again later. | 1749 | * this index is used again later. |
1661 | */ | 1750 | */ |
1662 | for (i=0; i < CISS_MAX_LUN; i++){ | 1751 | for (i=0; i < CISS_MAX_LUN; i++){ |
1663 | if(h->gendisk[i] == disk){ | 1752 | if (h->gendisk[i] == disk) { |
1664 | h->gendisk[i] = NULL; | 1753 | h->gendisk[i] = NULL; |
1665 | break; | 1754 | break; |
1666 | } | 1755 | } |
@@ -1688,7 +1777,7 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, | |||
1688 | if (drv == h->drv + h->highest_lun) { | 1777 | if (drv == h->drv + h->highest_lun) { |
1689 | /* if so, find the new hightest lun */ | 1778 | /* if so, find the new hightest lun */ |
1690 | int i, newhighest = -1; | 1779 | int i, newhighest = -1; |
1691 | for (i = 0; i < h->highest_lun; i++) { | 1780 | for (i = 0; i <= h->highest_lun; i++) { |
1692 | /* if the disk has size > 0, it is available */ | 1781 | /* if the disk has size > 0, it is available */ |
1693 | if (h->drv[i].heads) | 1782 | if (h->drv[i].heads) |
1694 | newhighest = i; | 1783 | newhighest = i; |
@@ -3318,6 +3407,9 @@ geo_inq: | |||
3318 | cciss_geometry_inquiry(cntl_num, i, 0, total_size, | 3407 | cciss_geometry_inquiry(cntl_num, i, 0, total_size, |
3319 | block_size, inq_buff, | 3408 | block_size, inq_buff, |
3320 | &hba[cntl_num]->drv[i]); | 3409 | &hba[cntl_num]->drv[i]); |
3410 | cciss_get_serial_no(cntl_num, i, 0, | ||
3411 | hba[cntl_num]->drv[i].serial_no, | ||
3412 | sizeof(hba[cntl_num]->drv[i].serial_no)); | ||
3321 | } else { | 3413 | } else { |
3322 | /* initialize raid_level to indicate a free space */ | 3414 | /* initialize raid_level to indicate a free space */ |
3323 | hba[cntl_num]->drv[i].raid_level = -1; | 3415 | hba[cntl_num]->drv[i].raid_level = -1; |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index b70988dd33ec..24a7efa993ab 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -39,6 +39,8 @@ typedef struct _drive_info_struct | |||
39 | *to prevent it from being opened or it's queue | 39 | *to prevent it from being opened or it's queue |
40 | *from being started. | 40 | *from being started. |
41 | */ | 41 | */ |
42 | __u8 serial_no[16]; /* from inquiry page 0x83, */ | ||
43 | /* not necc. null terminated. */ | ||
42 | } drive_info_struct; | 44 | } drive_info_struct; |
43 | 45 | ||
44 | #ifdef CONFIG_CISS_SCSI_TAPE | 46 | #ifdef CONFIG_CISS_SCSI_TAPE |