Commit 4397a191 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] cpqarray fixes

This restores the special-case behaviour of open() on the minor 0;
cpqarray allows to open that guy for ioctls even if nothing is
configured.  That got broken when gendisk patches went in.  Patch
restores the old behaviour by keeping gendisk for the first disk on
controller always registered; instead of unregistering it we set size to
0.
parent bf78f301
...@@ -134,7 +134,7 @@ static int sendcmd( ...@@ -134,7 +134,7 @@ static int sendcmd(
static int ida_open(struct inode *inode, struct file *filep); static int ida_open(struct inode *inode, struct file *filep);
static int ida_release(struct inode *inode, struct file *filep); static int ida_release(struct inode *inode, struct file *filep);
static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io); static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
static void do_ida_request(request_queue_t *q); static void do_ida_request(request_queue_t *q);
static void start_io(ctlr_info_t *h); static void start_io(ctlr_info_t *h);
...@@ -147,7 +147,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout); ...@@ -147,7 +147,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout);
static irqreturn_t do_ida_intr(int irq, void *dev_id, struct pt_regs * regs); static irqreturn_t do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
static void ida_timer(unsigned long tdata); static void ida_timer(unsigned long tdata);
static int ida_revalidate(struct gendisk *disk); static int ida_revalidate(struct gendisk *disk);
static int revalidate_allvol(kdev_t dev); static int revalidate_allvol(ctlr_info_t *host);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static void ida_procinit(int i); static void ida_procinit(int i);
...@@ -158,6 +158,17 @@ static int ida_proc_get_info(char *buffer, char **start, off_t offset, ...@@ -158,6 +158,17 @@ static int ida_proc_get_info(char *buffer, char **start, off_t offset,
int length, int *eof, void *data) { return 0;} int length, int *eof, void *data) { return 0;}
#endif #endif
static inline drv_info_t *get_drv(struct gendisk *disk)
{
return disk->private_data;
}
static inline ctlr_info_t *get_host(struct gendisk *disk)
{
return disk->queue->queuedata;
}
static struct block_device_operations ida_fops = { static struct block_device_operations ida_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = ida_open, .open = ida_open,
...@@ -401,7 +412,7 @@ static int __init cpqarray_init(void) ...@@ -401,7 +412,7 @@ static int __init cpqarray_init(void)
disk->major = COMPAQ_SMART2_MAJOR + i; disk->major = COMPAQ_SMART2_MAJOR + i;
disk->first_minor = j<<NWD_SHIFT; disk->first_minor = j<<NWD_SHIFT;
disk->fops = &ida_fops; disk->fops = &ida_fops;
if (!drv->nr_blks) if (j && !drv->nr_blks)
continue; continue;
hba[i]->queue.hardsect_size = drv->blk_size; hba[i]->queue.hardsect_size = drv->blk_size;
set_capacity(disk, drv->nr_blks); set_capacity(disk, drv->nr_blks);
...@@ -704,27 +715,23 @@ DBGINFO( ...@@ -704,27 +715,23 @@ DBGINFO(
*/ */
static int ida_open(struct inode *inode, struct file *filep) static int ida_open(struct inode *inode, struct file *filep)
{ {
int ctlr = major(inode->i_rdev) - COMPAQ_SMART2_MAJOR; drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
int dsk = minor(inode->i_rdev) >> NWD_SHIFT; ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
DBGINFO(printk("ida_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
return -ENXIO;
DBGINFO(printk("ida_open %s\n", inode->i_bdev->bd_disk->disk_name));
/* /*
* 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. 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 (!hba[ctlr]->drv[dsk].nr_blks) { if (!drv->nr_blks) {
if (!capable(CAP_SYS_RAWIO)) if (!capable(CAP_SYS_RAWIO))
return -ENXIO; return -ENXIO;
/* Huh??? */ if (!capable(CAP_SYS_ADMIN) && drv != host->drv)
if (capable(CAP_SYS_ADMIN) && minor(inode->i_rdev) != 0)
return -ENXIO; return -ENXIO;
} }
hba[ctlr]->usage_count++; host->usage_count++;
return 0; return 0;
} }
...@@ -733,8 +740,8 @@ static int ida_open(struct inode *inode, struct file *filep) ...@@ -733,8 +740,8 @@ static int ida_open(struct inode *inode, struct file *filep)
*/ */
static int ida_release(struct inode *inode, struct file *filep) static int ida_release(struct inode *inode, struct file *filep)
{ {
int ctlr = major(inode->i_rdev) - COMPAQ_SMART2_MAJOR; ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
hba[ctlr]->usage_count--; host->usage_count--;
return 0; return 0;
} }
...@@ -1015,8 +1022,8 @@ static void ida_timer(unsigned long tdata) ...@@ -1015,8 +1022,8 @@ static void ida_timer(unsigned long tdata)
*/ */
static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
{ {
int ctlr = major(inode->i_rdev) - COMPAQ_SMART2_MAJOR; drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
int dsk = minor(inode->i_rdev) >> NWD_SHIFT; ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
int error; int error;
int diskinfo[4]; int diskinfo[4];
struct hd_geometry *geo = (struct hd_geometry *)arg; struct hd_geometry *geo = (struct hd_geometry *)arg;
...@@ -1025,14 +1032,14 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, ...@@ -1025,14 +1032,14 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
switch(cmd) { switch(cmd) {
case HDIO_GETGEO: case HDIO_GETGEO:
if (hba[ctlr]->drv[dsk].cylinders) { if (drv->cylinders) {
diskinfo[0] = hba[ctlr]->drv[dsk].heads; diskinfo[0] = drv->heads;
diskinfo[1] = hba[ctlr]->drv[dsk].sectors; diskinfo[1] = drv->sectors;
diskinfo[2] = hba[ctlr]->drv[dsk].cylinders; diskinfo[2] = drv->cylinders;
} else { } else {
diskinfo[0] = 0xff; diskinfo[0] = 0xff;
diskinfo[1] = 0x3f; diskinfo[1] = 0x3f;
diskinfo[2] = hba[ctlr]->drv[dsk].nr_blks / (0xff*0x3f); diskinfo[2] = drv->nr_blks / (0xff*0x3f);
} }
put_user(diskinfo[0], &geo->heads); put_user(diskinfo[0], &geo->heads);
put_user(diskinfo[1], &geo->sectors); put_user(diskinfo[1], &geo->sectors);
...@@ -1040,23 +1047,24 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, ...@@ -1040,23 +1047,24 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
put_user(get_start_sect(inode->i_bdev), &geo->start); put_user(get_start_sect(inode->i_bdev), &geo->start);
return 0; return 0;
case IDAGETDRVINFO: case IDAGETDRVINFO:
if (copy_to_user(&io->c.drv, &hba[ctlr]->drv[dsk], if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t)))
sizeof(drv_info_t)))
return -EFAULT; return -EFAULT;
return 0; return 0;
case IDAPASSTHRU: case IDAPASSTHRU:
if (!capable(CAP_SYS_RAWIO)) return -EPERM; if (!capable(CAP_SYS_RAWIO)) return -EPERM;
if (copy_from_user(&my_io, io, sizeof(my_io))) if (copy_from_user(&my_io, io, sizeof(my_io)))
return -EFAULT; return -EFAULT;
error = ida_ctlr_ioctl(ctlr, dsk, &my_io); error = ida_ctlr_ioctl(host, drv - host->drv, &my_io);
if (error) return error; if (error) return error;
return copy_to_user(io, &my_io, sizeof(my_io)) ? -EFAULT : 0; return copy_to_user(io, &my_io, sizeof(my_io)) ? -EFAULT : 0;
case IDAGETCTLRSIG: case IDAGETCTLRSIG:
if (!arg) return -EINVAL; if (!arg) return -EINVAL;
put_user(hba[ctlr]->ctlr_sig, (int*)arg); put_user(host->ctlr_sig, (int*)arg);
return 0; return 0;
case IDAREVALIDATEVOLS: case IDAREVALIDATEVOLS:
return revalidate_allvol(inode->i_rdev); if (minor(inode->i_rdev) != 0)
return -ENXIO;
return revalidate_allvol(host);
case IDADRIVERVERSION: case IDADRIVERVERSION:
if (!arg) return -EINVAL; if (!arg) return -EINVAL;
put_user(DRIVER_VERSION, (unsigned long*)arg); put_user(DRIVER_VERSION, (unsigned long*)arg);
...@@ -1067,9 +1075,9 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, ...@@ -1067,9 +1075,9 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
ida_pci_info_struct pciinfo; ida_pci_info_struct pciinfo;
if (!arg) return -EINVAL; if (!arg) return -EINVAL;
pciinfo.bus = hba[ctlr]->pci_dev->bus->number; pciinfo.bus = host->pci_dev->bus->number;
pciinfo.dev_fn = hba[ctlr]->pci_dev->devfn; pciinfo.dev_fn = host->pci_dev->devfn;
pciinfo.board_id = hba[ctlr]->board_id; pciinfo.board_id = host->board_id;
if(copy_to_user((void *) arg, &pciinfo, if(copy_to_user((void *) arg, &pciinfo,
sizeof( ida_pci_info_struct))) sizeof( ida_pci_info_struct)))
return -EFAULT; return -EFAULT;
...@@ -1091,9 +1099,9 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, ...@@ -1091,9 +1099,9 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
* any serious sanity checking on the arguments. Doing an IDA_WRITE_MEDIA and * any serious sanity checking on the arguments. Doing an IDA_WRITE_MEDIA and
* putting a 64M buffer in the sglist is probably a *bad* idea. * putting a 64M buffer in the sglist is probably a *bad* idea.
*/ */
static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io) static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io)
{ {
ctlr_info_t *h = hba[ctlr]; int ctlr = h->ctlr;
cmdlist_t *c; cmdlist_t *c;
void *p = NULL; void *p = NULL;
unsigned long flags; unsigned long flags;
...@@ -1387,59 +1395,57 @@ DBG( ...@@ -1387,59 +1395,57 @@ DBG(
* particualar logical volume (instead of all of them on a particular * particualar logical volume (instead of all of them on a particular
* controller). * controller).
*/ */
static int revalidate_allvol(kdev_t dev) static int revalidate_allvol(ctlr_info_t *host)
{ {
int ctlr, i; int ctlr = host->ctlr;
int i;
unsigned long flags; unsigned long flags;
if (minor(dev) != 0)
return -ENXIO;
ctlr = major(dev) - COMPAQ_SMART2_MAJOR;
spin_lock_irqsave(IDA_LOCK(ctlr), flags); spin_lock_irqsave(IDA_LOCK(ctlr), flags);
if (hba[ctlr]->usage_count > 1) { if (host->usage_count > 1) {
spin_unlock_irqrestore(IDA_LOCK(ctlr), flags); spin_unlock_irqrestore(IDA_LOCK(ctlr), flags);
printk(KERN_WARNING "cpqarray: Device busy for volume" printk(KERN_WARNING "cpqarray: Device busy for volume"
" revalidation (usage=%d)\n", hba[ctlr]->usage_count); " revalidation (usage=%d)\n", host->usage_count);
return -EBUSY; return -EBUSY;
} }
hba[ctlr]->usage_count++; host->usage_count++;
spin_unlock_irqrestore(IDA_LOCK(ctlr), flags); spin_unlock_irqrestore(IDA_LOCK(ctlr), flags);
/* /*
* Set the partition and block size structures for all volumes * Set the partition and block size structures for all volumes
* on this controller to zero. We will reread all of this data * on this controller to zero. We will reread all of this data
*/ */
for (i = 0; i < NWD; i++) { set_capacity(ida_gendisk[ctlr][0], 0);
for (i = 1; i < NWD; i++) {
struct gendisk *disk = ida_gendisk[ctlr][i]; struct gendisk *disk = ida_gendisk[ctlr][i];
if (disk->flags & GENHD_FL_UP) if (disk->flags & GENHD_FL_UP)
del_gendisk(disk); del_gendisk(disk);
} }
memset(hba[ctlr]->drv, 0, sizeof(drv_info_t)*NWD); memset(host->drv, 0, sizeof(drv_info_t)*NWD);
/* /*
* Tell the array controller not to give us any interrupts while * Tell the array controller not to give us any interrupts while
* we check the new geometry. Then turn interrupts back on when * we check the new geometry. Then turn interrupts back on when
* we're done. * we're done.
*/ */
hba[ctlr]->access.set_intr_mask(hba[ctlr], 0); host->access.set_intr_mask(host, 0);
getgeometry(ctlr); getgeometry(ctlr);
hba[ctlr]->access.set_intr_mask(hba[ctlr], FIFO_NOT_EMPTY); host->access.set_intr_mask(host, FIFO_NOT_EMPTY);
for(i=0; i<NWD; i++) { for(i=0; i<NWD; i++) {
struct gendisk *disk = ida_gendisk[ctlr][i]; struct gendisk *disk = ida_gendisk[ctlr][i];
drv_info_t *drv = &hba[ctlr]->drv[i]; drv_info_t *drv = &host->drv[i];
if (!drv->nr_blks) if (i && !drv->nr_blks)
continue; continue;
hba[ctlr]->queue.hardsect_size = drv->blk_size; host->queue.hardsect_size = drv->blk_size;
set_capacity(disk, drv->nr_blks); set_capacity(disk, drv->nr_blks);
disk->queue = &hba[ctlr]->queue; disk->queue = &host->queue;
disk->private_data = drv; disk->private_data = drv;
add_disk(disk); if (i)
add_disk(disk);
} }
hba[ctlr]->usage_count--; host->usage_count--;
return 0; return 0;
} }
......
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