diff options
author | Stephen M. Cameron <scameron@beardog.cce.hp.com> | 2009-09-17 13:47:44 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-10-01 21:15:42 +0200 |
commit | 2d11d9931f5968bddac50d9d224c4812d4be869a (patch) | |
tree | 6ea99eba85cc2de4d061c5c6d262b91aab6226c5 /drivers | |
parent | 9ddb27b44ffeb3080b71cc493b2edff2224d9356 (diff) | |
download | linux-2d11d9931f5968bddac50d9d224c4812d4be869a.tar.gz linux-2d11d9931f5968bddac50d9d224c4812d4be869a.tar.bz2 linux-2d11d9931f5968bddac50d9d224c4812d4be869a.zip |
cciss: Fix usage_count check in rebuild_lun_table when triggered via sysfs.
When rebuild_lun_table is reached via sysfs, the usage count that
is checked prior to messing with c0d0 has different constraints
(must be zero) than if rebuild_lun_table is reached via ioctl
(must be one.) Fix rebuild_lun_table to take that into account.
Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/cciss.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 09a0f7bb433b..0a3c057c7785 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -170,9 +170,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); static int cciss_revalidate(struct gendisk *disk); -static int rebuild_lun_table(ctlr_info_t *h, int first_time); +static int rebuild_lun_table(ctlr_info_t *h, int first_time, int via_ioctl); static int deregister_disk(ctlr_info_t *h, int drv_index, - int clear_all); + int clear_all, int via_ioctl); static void cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size, unsigned int *block_size); @@ -1211,7 +1211,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, case CCISS_DEREGDISK: case CCISS_REGNEWD: case CCISS_REVALIDVOLS: - return rebuild_lun_table(host, 0); + return rebuild_lun_table(host, 0, 1); case CCISS_GETLUNINFO:{ LogvolInfo_struct luninfo; @@ -1757,7 +1757,8 @@ init_queue_failure: * is also the controller node. Any changes to disk 0 will show up on * the next reboot. */ -static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) +static void cciss_update_drive_info(int ctlr, int drv_index, int first_time, + int via_ioctl) { ctlr_info_t *h = hba[ctlr]; struct gendisk *disk; @@ -1835,7 +1836,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) * which keeps the interrupt handler from starting * the queue. */ - ret = deregister_disk(h, drv_index, 0); + ret = deregister_disk(h, drv_index, 0, via_ioctl); h->drv[drv_index].busy_configuring = 0; } @@ -2000,7 +2001,8 @@ error: * INPUT * h = The controller to perform the operations on */ -static int rebuild_lun_table(ctlr_info_t *h, int first_time) +static int rebuild_lun_table(ctlr_info_t *h, int first_time, + int via_ioctl) { int ctlr = h->ctlr; int num_luns; @@ -2079,7 +2081,7 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); h->drv[i].busy_configuring = 1; spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); - return_code = deregister_disk(h, i, 1); + return_code = deregister_disk(h, i, 1, via_ioctl); h->drv[i].busy_configuring = 0; } } @@ -2117,7 +2119,8 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) if (drv_index == -1) goto freeret; } - cciss_update_drive_info(ctlr, drv_index, first_time); + cciss_update_drive_info(ctlr, drv_index, first_time, + via_ioctl); } /* end for */ freeret: @@ -2167,9 +2170,15 @@ static void cciss_clear_drive_info(drive_info_struct *drive_info) * the disk in preparation for re-adding it. In this case * the highest_lun should be left unchanged and the LunID * should not be cleared. + * via_ioctl + * This indicates whether we've reached this path via ioctl. + * This affects the maximum usage count allowed for c0d0 to be messed with. + * If this path is reached via ioctl(), then the max_usage_count will + * be 1, as the process calling ioctl() has got to have the device open. + * If we get here via sysfs, then the max usage count will be zero. */ static int deregister_disk(ctlr_info_t *h, int drv_index, - int clear_all) + int clear_all, int via_ioctl) { int i; struct gendisk *disk; @@ -2183,7 +2192,7 @@ static int deregister_disk(ctlr_info_t *h, int drv_index, /* make sure logical volume is NOT is use */ if (clear_all || (h->gendisk[0] == disk)) { - if (drv->usage_count > 1) + if (drv->usage_count > via_ioctl) return -EBUSY; } else if (drv->usage_count > 0) return -EBUSY; @@ -3452,7 +3461,7 @@ static int scan_thread(void *data) mutex_unlock(&scan_mutex); if (h) { - rebuild_lun_table(h, 0); + rebuild_lun_table(h, 0, 0); complete_all(&h->scan_wait); mutex_lock(&scan_mutex); h->busy_scanning = 0; @@ -4253,7 +4262,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, hba[i]->cciss_max_sectors = 2048; - rebuild_lun_table(hba[i], 1); + rebuild_lun_table(hba[i], 1, 0); hba[i]->busy_initializing = 0; return 1; |