cciss: Preserve all 8 bytes of LUN ID for logical drives.
Stephen M. Cameron [Thu, 17 Sep 2009 18:48:00 +0000 (13:48 -0500)]
Preserve all 8 bytes of the LunID field returned
by CCISS_REPORT_LOGICAL instead of only saving 4 bytes.
This fixes a bug with logical volume addressing encountered on
an MSA2012.

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

drivers/block/cciss.c
drivers/block/cciss.h

index 67c4899..d6ea937 100644 (file)
@@ -846,7 +846,8 @@ static int cciss_open(struct block_device *bdev, fmode_t mode)
                        if (MINOR(bdev->bd_dev) & 0x0f) {
                                return -ENXIO;
                                /* if it is, make sure we have a LUN ID */
-                       } else if (drv->LunID == 0) {
+                       } else if (memcmp(drv->LunID, CTLR_LUNID,
+                               sizeof(drv->LunID))) {
                                return -ENXIO;
                        }
                }
@@ -1216,7 +1217,8 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
        case CCISS_GETLUNINFO:{
                        LogvolInfo_struct luninfo;
 
-                       luninfo.LunID = drv->LunID;
+                       memcpy(&luninfo.LunID, drv->LunID,
+                               sizeof(luninfo.LunID));
                        luninfo.num_opens = drv->usage_count;
                        luninfo.num_parts = 0;
                        if (copy_to_user(argp, &luninfo,
@@ -1611,13 +1613,11 @@ static void cciss_softirq_done(struct request *rq)
        spin_unlock_irqrestore(&h->lock, flags);
 }
 
-static void log_unit_to_scsi3addr(ctlr_info_t *h, unsigned char scsi3addr[],
-       uint32_t log_unit)
+static inline void log_unit_to_scsi3addr(ctlr_info_t *h,
+       unsigned char scsi3addr[], uint32_t log_unit)
 {
-       log_unit = h->drv[log_unit].LunID & 0x03fff;
-       memset(&scsi3addr[4], 0, 4);
-       memcpy(&scsi3addr[0], &log_unit, 4);
-       scsi3addr[3] |= 0x40;
+       memcpy(scsi3addr, h->drv[log_unit].LunID,
+               sizeof(h->drv[log_unit].LunID));
 }
 
 /* This function gets the SCSI vendor, model, and revision of a logical drive
@@ -1924,7 +1924,8 @@ static void cciss_free_gendisk(ctlr_info_t *h, int drv_index)
  * a means to talk to the controller in case no logical
  * drives have yet been configured.
  */
-static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node)
+static int cciss_add_gendisk(ctlr_info_t *h, unsigned char lunid[],
+       int controller_node)
 {
        int drv_index;
 
@@ -1943,7 +1944,8 @@ static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node)
                        return -1;
                }
        }
-       h->drv[drv_index].LunID = lunid;
+       memcpy(h->drv[drv_index].LunID, lunid,
+               sizeof(h->drv[drv_index].LunID));
        if (h->drv[drv_index].dev == NULL) {
                if (cciss_create_ld_sysfs_entry(h, drv_index))
                        goto err_free_disk;
@@ -1973,7 +1975,7 @@ static void cciss_add_controller_node(ctlr_info_t *h)
        if (h->gendisk[0] != NULL) /* already did this? Then bail. */
                return;
 
-       drv_index = cciss_add_gendisk(h, 0, 1);
+       drv_index = cciss_add_gendisk(h, CTLR_LUNID, 1);
        if (drv_index == -1)
                goto error;
        h->drv[drv_index].block_size = 512;
@@ -2012,7 +2014,7 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time,
        int i;
        int drv_found;
        int drv_index = 0;
-       __u32 lunid = 0;
+       unsigned char lunid[8] = CTLR_LUNID;
        unsigned long flags;
 
        if (!capable(CAP_SYS_RAWIO))
@@ -2069,9 +2071,9 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time,
                        continue;
 
                for (j = 0; j < num_luns; j++) {
-                       memcpy(&lunid, &ld_buff->LUN[j][0], 4);
-                       lunid = le32_to_cpu(lunid);
-                       if (h->drv[i].LunID == lunid) {
+                       memcpy(lunid, &ld_buff->LUN[j][0], sizeof(lunid));
+                       if (memcmp(h->drv[i].LunID, lunid,
+                               sizeof(lunid)) == 0) {
                                drv_found = 1;
                                break;
                        }
@@ -2096,9 +2098,7 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time,
 
                drv_found = 0;
 
-               memcpy(&lunid, &ld_buff->LUN[i][0], 4);
-               lunid = le32_to_cpu(lunid);
-
+               memcpy(lunid, &ld_buff->LUN[i][0], sizeof(lunid));
                /* Find if the LUN is already in the drive array
                 * of the driver.  If so then update its info
                 * if not in use.  If it does not exist then find
@@ -2106,7 +2106,8 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time,
                 */
                for (j = 0; j <= h->highest_lun; j++) {
                        if (h->drv[j].raid_level != -1 &&
-                               h->drv[j].LunID == lunid) {
+                               memcmp(h->drv[j].LunID, lunid,
+                                       sizeof(h->drv[j].LunID)) == 0) {
                                drv_index = j;
                                drv_found = 1;
                                break;
@@ -2254,8 +2255,7 @@ static int deregister_disk(ctlr_info_t *h, int drv_index,
                        }
                        h->highest_lun = newhighest;
                }
-
-               drv->LunID = 0;
+               memset(drv->LunID, 0, sizeof(drv->LunID));
        }
        return 0;
 }
@@ -2686,7 +2686,8 @@ static int cciss_revalidate(struct gendisk *disk)
        InquiryData_struct *inq_buff = NULL;
 
        for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
-               if (h->drv[logvol].LunID == drv->LunID) {
+               if (memcmp(h->drv[logvol].LunID, drv->LunID,
+                       sizeof(drv->LunID)) == 0) {
                        FOUND = 1;
                        break;
                }
@@ -3171,8 +3172,7 @@ static void do_cciss_request(struct request_queue *q)
        /* The first 2 bits are reserved for controller error reporting. */
        c->Header.Tag.lower = (c->cmdindex << 3);
        c->Header.Tag.lower |= 0x04;    /* flag for direct lookup. */
-       c->Header.LUN.LogDev.VolId = drv->LunID;
-       c->Header.LUN.LogDev.Mode = 1;
+       memcpy(&c->Header.LUN, drv->LunID, sizeof(drv->LunID));
        c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
        c->Request.Type.Type = TYPE_CMD;        // It is a command.
        c->Request.Type.Attribute = ATTR_SIMPLE;
index 9679342..5188f71 100644 (file)
@@ -30,7 +30,7 @@ struct access_method {
 };
 typedef struct _drive_info_struct
 {
-       __u32   LunID;  
+       unsigned char LunID[8];
        int     usage_count;
        struct request_queue *queue;
        sector_t nr_blocks;