diff options
author | Stephen M. Cameron <scameron@beardog.cce.hp.com> | 2009-09-17 14:47:44 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-10-01 15:15:42 -0400 |
commit | 2d11d9931f5968bddac50d9d224c4812d4be869a (patch) | |
tree | 6ea99eba85cc2de4d061c5c6d262b91aab6226c5 /drivers | |
parent | 9ddb27b44ffeb3080b71cc493b2edff2224d9356 (diff) |
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, | |||
170 | static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); | 170 | static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); |
171 | 171 | ||
172 | static int cciss_revalidate(struct gendisk *disk); | 172 | static int cciss_revalidate(struct gendisk *disk); |
173 | static int rebuild_lun_table(ctlr_info_t *h, int first_time); | 173 | static int rebuild_lun_table(ctlr_info_t *h, int first_time, int via_ioctl); |
174 | static int deregister_disk(ctlr_info_t *h, int drv_index, | 174 | static int deregister_disk(ctlr_info_t *h, int drv_index, |
175 | int clear_all); | 175 | int clear_all, int via_ioctl); |
176 | 176 | ||
177 | static void cciss_read_capacity(int ctlr, int logvol, int withirq, | 177 | static void cciss_read_capacity(int ctlr, int logvol, int withirq, |
178 | sector_t *total_size, unsigned int *block_size); | 178 | sector_t *total_size, unsigned int *block_size); |
@@ -1211,7 +1211,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | |||
1211 | case CCISS_DEREGDISK: | 1211 | case CCISS_DEREGDISK: |
1212 | case CCISS_REGNEWD: | 1212 | case CCISS_REGNEWD: |
1213 | case CCISS_REVALIDVOLS: | 1213 | case CCISS_REVALIDVOLS: |
1214 | return rebuild_lun_table(host, 0); | 1214 | return rebuild_lun_table(host, 0, 1); |
1215 | 1215 | ||
1216 | case CCISS_GETLUNINFO:{ | 1216 | case CCISS_GETLUNINFO:{ |
1217 | LogvolInfo_struct luninfo; | 1217 | LogvolInfo_struct luninfo; |
@@ -1757,7 +1757,8 @@ init_queue_failure: | |||
1757 | * is also the controller node. Any changes to disk 0 will show up on | 1757 | * is also the controller node. Any changes to disk 0 will show up on |
1758 | * the next reboot. | 1758 | * the next reboot. |
1759 | */ | 1759 | */ |
1760 | static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) | 1760 | static void cciss_update_drive_info(int ctlr, int drv_index, int first_time, |
1761 | int via_ioctl) | ||
1761 | { | 1762 | { |
1762 | ctlr_info_t *h = hba[ctlr]; | 1763 | ctlr_info_t *h = hba[ctlr]; |
1763 | struct gendisk *disk; | 1764 | struct gendisk *disk; |
@@ -1835,7 +1836,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) | |||
1835 | * which keeps the interrupt handler from starting | 1836 | * which keeps the interrupt handler from starting |
1836 | * the queue. | 1837 | * the queue. |
1837 | */ | 1838 | */ |
1838 | ret = deregister_disk(h, drv_index, 0); | 1839 | ret = deregister_disk(h, drv_index, 0, via_ioctl); |
1839 | h->drv[drv_index].busy_configuring = 0; | 1840 | h->drv[drv_index].busy_configuring = 0; |
1840 | } | 1841 | } |
1841 | 1842 | ||
@@ -2000,7 +2001,8 @@ error: | |||
2000 | * INPUT | 2001 | * INPUT |
2001 | * h = The controller to perform the operations on | 2002 | * h = The controller to perform the operations on |
2002 | */ | 2003 | */ |
2003 | static int rebuild_lun_table(ctlr_info_t *h, int first_time) | 2004 | static int rebuild_lun_table(ctlr_info_t *h, int first_time, |
2005 | int via_ioctl) | ||
2004 | { | 2006 | { |
2005 | int ctlr = h->ctlr; | 2007 | int ctlr = h->ctlr; |
2006 | int num_luns; | 2008 | int num_luns; |
@@ -2079,7 +2081,7 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) | |||
2079 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 2081 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
2080 | h->drv[i].busy_configuring = 1; | 2082 | h->drv[i].busy_configuring = 1; |
2081 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | 2083 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
2082 | return_code = deregister_disk(h, i, 1); | 2084 | return_code = deregister_disk(h, i, 1, via_ioctl); |
2083 | h->drv[i].busy_configuring = 0; | 2085 | h->drv[i].busy_configuring = 0; |
2084 | } | 2086 | } |
2085 | } | 2087 | } |
@@ -2117,7 +2119,8 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) | |||
2117 | if (drv_index == -1) | 2119 | if (drv_index == -1) |
2118 | goto freeret; | 2120 | goto freeret; |
2119 | } | 2121 | } |
2120 | cciss_update_drive_info(ctlr, drv_index, first_time); | 2122 | cciss_update_drive_info(ctlr, drv_index, first_time, |
2123 | via_ioctl); | ||
2121 | } /* end for */ | 2124 | } /* end for */ |
2122 | 2125 | ||
2123 | freeret: | 2126 | freeret: |
@@ -2167,9 +2170,15 @@ static void cciss_clear_drive_info(drive_info_struct *drive_info) | |||
2167 | * the disk in preparation for re-adding it. In this case | 2170 | * the disk in preparation for re-adding it. In this case |
2168 | * the highest_lun should be left unchanged and the LunID | 2171 | * the highest_lun should be left unchanged and the LunID |
2169 | * should not be cleared. | 2172 | * should not be cleared. |
2173 | * via_ioctl | ||
2174 | * This indicates whether we've reached this path via ioctl. | ||
2175 | * This affects the maximum usage count allowed for c0d0 to be messed with. | ||
2176 | * If this path is reached via ioctl(), then the max_usage_count will | ||
2177 | * be 1, as the process calling ioctl() has got to have the device open. | ||
2178 | * If we get here via sysfs, then the max usage count will be zero. | ||
2170 | */ | 2179 | */ |
2171 | static int deregister_disk(ctlr_info_t *h, int drv_index, | 2180 | static int deregister_disk(ctlr_info_t *h, int drv_index, |
2172 | int clear_all) | 2181 | int clear_all, int via_ioctl) |
2173 | { | 2182 | { |
2174 | int i; | 2183 | int i; |
2175 | struct gendisk *disk; | 2184 | struct gendisk *disk; |
@@ -2183,7 +2192,7 @@ static int deregister_disk(ctlr_info_t *h, int drv_index, | |||
2183 | 2192 | ||
2184 | /* make sure logical volume is NOT is use */ | 2193 | /* make sure logical volume is NOT is use */ |
2185 | if (clear_all || (h->gendisk[0] == disk)) { | 2194 | if (clear_all || (h->gendisk[0] == disk)) { |
2186 | if (drv->usage_count > 1) | 2195 | if (drv->usage_count > via_ioctl) |
2187 | return -EBUSY; | 2196 | return -EBUSY; |
2188 | } else if (drv->usage_count > 0) | 2197 | } else if (drv->usage_count > 0) |
2189 | return -EBUSY; | 2198 | return -EBUSY; |
@@ -3452,7 +3461,7 @@ static int scan_thread(void *data) | |||
3452 | mutex_unlock(&scan_mutex); | 3461 | mutex_unlock(&scan_mutex); |
3453 | 3462 | ||
3454 | if (h) { | 3463 | if (h) { |
3455 | rebuild_lun_table(h, 0); | 3464 | rebuild_lun_table(h, 0, 0); |
3456 | complete_all(&h->scan_wait); | 3465 | complete_all(&h->scan_wait); |
3457 | mutex_lock(&scan_mutex); | 3466 | mutex_lock(&scan_mutex); |
3458 | h->busy_scanning = 0; | 3467 | h->busy_scanning = 0; |
@@ -4253,7 +4262,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
4253 | 4262 | ||
4254 | hba[i]->cciss_max_sectors = 2048; | 4263 | hba[i]->cciss_max_sectors = 2048; |
4255 | 4264 | ||
4256 | rebuild_lun_table(hba[i], 1); | 4265 | rebuild_lun_table(hba[i], 1, 0); |
4257 | hba[i]->busy_initializing = 0; | 4266 | hba[i]->busy_initializing = 0; |
4258 | return 1; | 4267 | return 1; |
4259 | 4268 | ||