Commit 2207252b authored by Mike Miller's avatar Mike Miller Committed by James Bottomley

[PATCH] cciss: fixes for clustering

This patch changes our open specifically for clustering software. We must
allow root to access any volume or device with a LUN ID. We also modified
our revalidate function for this reason.
If a logical is reserved, we must register it with the OS with size=0. Then
the backup system can call BLKRRPART after breaking the reservation to
set the device to the correct size.
We also must register a controller with no logical volumes for the online
utilities to function. This is the way we've done it since the 2.2 kernel.
Which doesn't neccesarily make it right, but we have legacy apps to consider.

Signed off by: Mike Miller <mike.miller@hp.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 2f68cfe3
...@@ -438,13 +438,22 @@ static int cciss_open(struct inode *inode, struct file *filep) ...@@ -438,13 +438,22 @@ static int cciss_open(struct inode *inode, struct file *filep)
/* /*
* Root is allowed to open raw volume zero even if it's not configured * Root is allowed to open raw volume zero even if it's not configured
* so array config can still work. I don't think I really like this, * so array config can still work. Root is also allowed to open any
* volume that has a LUN ID, so it can issue IOCTL to reread the
* disk information. I don't think I really like this
* but I'm already using way to many device nodes to claim another one * but I'm already using way to many device nodes to claim another one
* for "raw controller". * for "raw controller".
*/ */
if (drv->nr_blocks == 0) { if (drv->nr_blocks == 0) {
if (iminor(inode) != 0) if (iminor(inode) != 0) { /* not node 0? */
/* if not node 0 make sure it is a partition = 0 */
if (iminor(inode) & 0x0f) {
return -ENXIO; return -ENXIO;
/* if it is, make sure we have a LUN ID */
} else if (drv->LunID == 0) {
return -ENXIO;
}
}
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
} }
...@@ -1095,13 +1104,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, ...@@ -1095,13 +1104,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
} }
static int cciss_revalidate(struct gendisk *disk)
{
drive_info_struct *drv = disk->private_data;
set_capacity(disk, drv->nr_blocks);
return 0;
}
/* /*
* revalidate_allvol is for online array config utilities. After a * revalidate_allvol is for online array config utilities. After a
* utility reconfigures the drives in the array, it can use this function * utility reconfigures the drives in the array, it can use this function
...@@ -1153,7 +1155,9 @@ static int revalidate_allvol(ctlr_info_t *host) ...@@ -1153,7 +1155,9 @@ static int revalidate_allvol(ctlr_info_t *host)
for (i = 0; i < NWD; i++) { for (i = 0; i < NWD; i++) {
struct gendisk *disk = host->gendisk[i]; struct gendisk *disk = host->gendisk[i];
drive_info_struct *drv = &(host->drv[i]); drive_info_struct *drv = &(host->drv[i]);
if (!drv->nr_blocks) /* we must register the controller even if no disks exist */
/* this is for the online array utilities */
if (!drv->heads && i)
continue; continue;
blk_queue_hardsect_size(host->queue, drv->block_size); blk_queue_hardsect_size(host->queue, drv->block_size);
set_capacity(disk, drv->nr_blocks); set_capacity(disk, drv->nr_blocks);
...@@ -1485,13 +1489,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, ...@@ -1485,13 +1489,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
} }
} }
} else { /* Get geometry failed */ } else { /* Get geometry failed */
printk(KERN_WARNING "cciss: reading geometry failed, " printk(KERN_WARNING "cciss: reading geometry failed\n");
"continuing with default geometry\n");
drv->block_size = block_size;
drv->nr_blocks = total_size;
drv->heads = 255;
drv->sectors = 32; // Sectors per track
drv->cylinders = total_size / 255 / 32;
} }
printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n",
drv->heads, drv->sectors, drv->cylinders); drv->heads, drv->sectors, drv->cylinders);
...@@ -1520,6 +1518,7 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, ...@@ -1520,6 +1518,7 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
*total_size, *block_size); *total_size, *block_size);
return; return;
} }
static int register_new_disk(ctlr_info_t *h) static int register_new_disk(ctlr_info_t *h)
{ {
struct gendisk *disk; struct gendisk *disk;
...@@ -1663,6 +1662,8 @@ static int register_new_disk(ctlr_info_t *h) ...@@ -1663,6 +1662,8 @@ static int register_new_disk(ctlr_info_t *h)
/* setup partitions per disk */ /* setup partitions per disk */
disk = h->gendisk[logvol]; disk = h->gendisk[logvol];
set_capacity(disk, h->drv[logvol].nr_blocks); set_capacity(disk, h->drv[logvol].nr_blocks);
/* if it's the controller it's already added */
if(logvol)
add_disk(disk); add_disk(disk);
freeret: freeret:
kfree(ld_buff); kfree(ld_buff);
...@@ -1675,6 +1676,53 @@ static int register_new_disk(ctlr_info_t *h) ...@@ -1675,6 +1676,53 @@ static int register_new_disk(ctlr_info_t *h)
logvol = -1; logvol = -1;
goto freeret; goto freeret;
} }
static int cciss_revalidate(struct gendisk *disk)
{
ctlr_info_t *h = get_host(disk);
drive_info_struct *drv = get_drv(disk);
int logvol;
int FOUND=0;
unsigned int block_size;
unsigned int total_size;
ReadCapdata_struct *size_buff = NULL;
InquiryData_struct *inq_buff = NULL;
for(logvol=0; logvol < CISS_MAX_LUN; logvol++)
{
if(h->drv[logvol].LunID == drv->LunID) {
FOUND=1;
break;
}
}
if (!FOUND) return 1;
size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
if (size_buff == NULL)
{
printk(KERN_WARNING "cciss: out of memory\n");
return 1;
}
inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL)
{
printk(KERN_WARNING "cciss: out of memory\n");
kfree(size_buff);
return 1;
}
cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size, &block_size);
cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, inq_buff, drv);
blk_queue_hardsect_size(h->queue, drv->block_size);
set_capacity(disk, drv->nr_blocks);
kfree(size_buff);
kfree(inq_buff);
return 0;
}
/* /*
* Wait polling for a command to complete. * Wait polling for a command to complete.
* The memory mapped FIFO is polled for the completion. * The memory mapped FIFO is polled for the completion.
...@@ -2762,7 +2810,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, ...@@ -2762,7 +2810,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
disk->fops = &cciss_fops; disk->fops = &cciss_fops;
disk->queue = hba[i]->queue; disk->queue = hba[i]->queue;
disk->private_data = drv; disk->private_data = drv;
if( !(drv->nr_blocks)) /* we must register the controller even if no disks exist */
/* this is for the online array utilities */
if(!drv->heads && j)
continue; continue;
blk_queue_hardsect_size(hba[i]->queue, drv->block_size); blk_queue_hardsect_size(hba[i]->queue, drv->block_size);
set_capacity(disk, drv->nr_blocks); set_capacity(disk, drv->nr_blocks);
......
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