[PATCH] cciss: add support for 1024 logical volumes

Add the support for a large number of logical volumes.  We will soon have
hardware that support up to 1024 logical volumes.

Signed-off-by: Mike Miller <mike.miller@hp.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Mike Miller 2006-12-06 20:35:12 -08:00 committed by Linus Torvalds
parent 3833a748aa
commit 799202cbd0
4 changed files with 80 additions and 41 deletions

View File

@ -1315,6 +1315,11 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
/* if it's the controller it's already added */ /* if it's the controller it's already added */
if (drv_index) { if (drv_index) {
disk->queue = blk_init_queue(do_cciss_request, &h->lock); disk->queue = blk_init_queue(do_cciss_request, &h->lock);
sprintf(disk->disk_name, "cciss/c%dd%d", ctlr, drv_index);
disk->major = h->major;
disk->first_minor = drv_index << NWD_SHIFT;
disk->fops = &cciss_fops;
disk->private_data = &h->drv[drv_index];
/* Set up queue information */ /* Set up queue information */
disk->queue->backing_dev_info.ra_pages = READ_AHEAD; disk->queue->backing_dev_info.ra_pages = READ_AHEAD;
@ -1393,11 +1398,6 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
/* Set busy_configuring flag for this operation */ /* Set busy_configuring flag for this operation */
spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
if (h->num_luns >= CISS_MAX_LUN) {
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return -EINVAL;
}
if (h->busy_configuring) { if (h->busy_configuring) {
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return -EBUSY; return -EBUSY;
@ -1430,17 +1430,8 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
0, 0, TYPE_CMD); 0, 0, TYPE_CMD);
if (return_code == IO_OK) { if (return_code == IO_OK) {
listlength |= listlength =
(0xff & (unsigned int)(ld_buff->LUNListLength[0])) be32_to_cpu(*(__u32 *) ld_buff->LUNListLength);
<< 24;
listlength |=
(0xff & (unsigned int)(ld_buff->LUNListLength[1]))
<< 16;
listlength |=
(0xff & (unsigned int)(ld_buff->LUNListLength[2]))
<< 8;
listlength |=
0xff & (unsigned int)(ld_buff->LUNListLength[3]);
} else { /* reading number of logical volumes failed */ } else { /* reading number of logical volumes failed */
printk(KERN_WARNING "cciss: report logical volume" printk(KERN_WARNING "cciss: report logical volume"
" command failed\n"); " command failed\n");
@ -1491,6 +1482,14 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
if (drv_index == -1) if (drv_index == -1)
goto freeret; goto freeret;
/*Check if the gendisk needs to be allocated */
if (!h->gendisk[drv_index]){
h->gendisk[drv_index] = alloc_disk(1 << NWD_SHIFT);
if (!h->gendisk[drv_index]){
printk(KERN_ERR "cciss: could not allocate new disk %d\n", drv_index);
goto mem_msg;
}
}
} }
h->drv[drv_index].LunID = lunid; h->drv[drv_index].LunID = lunid;
cciss_update_drive_info(ctlr, drv_index); cciss_update_drive_info(ctlr, drv_index);
@ -1528,6 +1527,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
int clear_all) int clear_all)
{ {
int i;
ctlr_info_t *h = get_host(disk); ctlr_info_t *h = get_host(disk);
if (!capable(CAP_SYS_RAWIO)) if (!capable(CAP_SYS_RAWIO))
@ -1551,9 +1551,35 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
del_gendisk(disk); del_gendisk(disk);
if (q) { if (q) {
blk_cleanup_queue(q); blk_cleanup_queue(q);
/* Set drv->queue to NULL so that we do not try
* to call blk_start_queue on this queue in the
* interrupt handler
*/
drv->queue = NULL; drv->queue = NULL;
} }
/* If clear_all is set then we are deleting the logical
* drive, not just refreshing its info. For drives
* other than disk 0 we will call put_disk. We do not
* do this for disk 0 as we need it to be able to
* configure the controller.
*/
if (clear_all){
/* This isn't pretty, but we need to find the
* disk in our array and NULL our the pointer.
* This is so that we will call alloc_disk if
* this index is used again later.
*/
for (i=0; i < CISS_MAX_LUN; i++){
if(h->gendisk[i] == disk){
h->gendisk[i] = NULL;
break;
}
}
put_disk(disk);
}
} }
} else {
set_capacity(disk, 0);
} }
--h->num_luns; --h->num_luns;
@ -3119,13 +3145,7 @@ static void cciss_getgeometry(int cntl_num)
/* Returns -1 if no free entries are left. */ /* Returns -1 if no free entries are left. */
static int alloc_cciss_hba(void) static int alloc_cciss_hba(void)
{ {
struct gendisk *disk[NWD]; int i;
int i, n;
for (n = 0; n < NWD; n++) {
disk[n] = alloc_disk(1 << NWD_SHIFT);
if (!disk[n])
goto out;
}
for (i = 0; i < MAX_CTLR; i++) { for (i = 0; i < MAX_CTLR; i++) {
if (!hba[i]) { if (!hba[i]) {
@ -3133,20 +3153,18 @@ static int alloc_cciss_hba(void)
p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL); p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL);
if (!p) if (!p)
goto Enomem; goto Enomem;
for (n = 0; n < NWD; n++) p->gendisk[0] = alloc_disk(1 << NWD_SHIFT);
p->gendisk[n] = disk[n]; if (!p->gendisk[0])
goto Enomem;
hba[i] = p; hba[i] = p;
return i; return i;
} }
} }
printk(KERN_WARNING "cciss: This driver supports a maximum" printk(KERN_WARNING "cciss: This driver supports a maximum"
" of %d controllers.\n", MAX_CTLR); " of %d controllers.\n", MAX_CTLR);
goto out; return -1;
Enomem: Enomem:
printk(KERN_ERR "cciss: out of memory.\n"); printk(KERN_ERR "cciss: out of memory.\n");
out:
while (n--)
put_disk(disk[n]);
return -1; return -1;
} }
@ -3156,7 +3174,7 @@ static void free_hba(int i)
int n; int n;
hba[i] = NULL; hba[i] = NULL;
for (n = 0; n < NWD; n++) for (n = 0; n < CISS_MAX_LUN; n++)
put_disk(p->gendisk[n]); put_disk(p->gendisk[n]);
kfree(p); kfree(p);
} }
@ -3169,9 +3187,8 @@ static void free_hba(int i)
static int __devinit cciss_init_one(struct pci_dev *pdev, static int __devinit cciss_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
request_queue_t *q;
int i; int i;
int j; int j = 0;
int rc; int rc;
int dac; int dac;
@ -3283,16 +3300,29 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
hba[i]->busy_initializing = 0; hba[i]->busy_initializing = 0;
for (j = 0; j < NWD; j++) { /* mfm */ do {
drive_info_struct *drv = &(hba[i]->drv[j]); drive_info_struct *drv = &(hba[i]->drv[j]);
struct gendisk *disk = hba[i]->gendisk[j]; struct gendisk *disk = hba[i]->gendisk[j];
request_queue_t *q;
/* Check if the disk was allocated already */
if (!disk){
hba[i]->gendisk[j] = alloc_disk(1 << NWD_SHIFT);
disk = hba[i]->gendisk[j];
}
/* Check that the disk was able to be allocated */
if (!disk) {
printk(KERN_ERR "cciss: unable to allocate memory for disk %d\n", j);
goto clean4;
}
q = blk_init_queue(do_cciss_request, &hba[i]->lock); q = blk_init_queue(do_cciss_request, &hba[i]->lock);
if (!q) { if (!q) {
printk(KERN_ERR printk(KERN_ERR
"cciss: unable to allocate queue for disk %d\n", "cciss: unable to allocate queue for disk %d\n",
j); j);
break; goto clean4;
} }
drv->queue = q; drv->queue = q;
@ -3324,7 +3354,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
blk_queue_hardsect_size(q, drv->block_size); blk_queue_hardsect_size(q, drv->block_size);
set_capacity(disk, drv->nr_blocks); set_capacity(disk, drv->nr_blocks);
add_disk(disk); add_disk(disk);
} j++;
} while (j <= hba[i]->highest_lun);
return 1; return 1;
@ -3347,6 +3378,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
unregister_blkdev(hba[i]->major, hba[i]->devname); unregister_blkdev(hba[i]->major, hba[i]->devname);
clean1: clean1:
hba[i]->busy_initializing = 0; hba[i]->busy_initializing = 0;
/* cleanup any queues that may have been initialized */
for (j=0; j <= hba[i]->highest_lun; j++){
drive_info_struct *drv = &(hba[i]->drv[j]);
if (drv->queue)
blk_cleanup_queue(drv->queue);
}
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
free_hba(i); free_hba(i);
return -1; return -1;
} }
@ -3394,7 +3434,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
remove_proc_entry(hba[i]->devname, proc_cciss); remove_proc_entry(hba[i]->devname, proc_cciss);
/* remove it from the disk list */ /* remove it from the disk list */
for (j = 0; j < NWD; j++) { for (j = 0; j < CISS_MAX_LUN; j++) {
struct gendisk *disk = hba[i]->gendisk[j]; struct gendisk *disk = hba[i]->gendisk[j];
if (disk) { if (disk) {
request_queue_t *q = disk->queue; request_queue_t *q = disk->queue;

View File

@ -6,7 +6,6 @@
#include "cciss_cmd.h" #include "cciss_cmd.h"
#define NWD 16
#define NWD_SHIFT 4 #define NWD_SHIFT 4
#define MAX_PART (1 << NWD_SHIFT) #define MAX_PART (1 << NWD_SHIFT)
@ -112,7 +111,7 @@ struct ctlr_info
int next_to_run; int next_to_run;
// Disk structures we need to pass back // Disk structures we need to pass back
struct gendisk *gendisk[NWD]; struct gendisk *gendisk[CISS_MAX_LUN];
#ifdef CONFIG_CISS_SCSI_TAPE #ifdef CONFIG_CISS_SCSI_TAPE
void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
/* list of block side commands the scsi error handling sucked up */ /* list of block side commands the scsi error handling sucked up */

View File

@ -89,7 +89,7 @@ typedef union _u64bit
//########################################################################### //###########################################################################
//STRUCTURES //STRUCTURES
//########################################################################### //###########################################################################
#define CISS_MAX_LUN 16 #define CISS_MAX_LUN 1024
#define CISS_MAX_PHYS_LUN 1024 #define CISS_MAX_PHYS_LUN 1024
// SCSI-3 Cmmands // SCSI-3 Cmmands

View File

@ -80,7 +80,7 @@ typedef __u32 DriverVer_type;
#define HWORD __u16 #define HWORD __u16
#define DWORD __u32 #define DWORD __u32
#define CISS_MAX_LUN 16 #define CISS_MAX_LUN 1024
#define LEVEL2LUN 1 // index into Target(x) structure, due to byte swapping #define LEVEL2LUN 1 // index into Target(x) structure, due to byte swapping
#define LEVEL3LUN 0 #define LEVEL3LUN 0