Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 297

kernel-2.6.18-238.el5.src.rpm

From: Tomas Henzl <thenzl@redhat.com>
Date: Sun, 29 Aug 2010 15:49:53 -0400
Subject: [block] cciss: add via_ioctl param to rebuild_lun_table
Message-id: <1283097002-3341-55-git-send-email-thenzl@redhat.com>
Patchwork-id: 27897
O-Subject: [RHEL6 PATCH 54/63] cciss: Add via_ioctl parameter to
	rebuild_lun_table
Bugzilla: 568830
RH-Acked-by: Neil Horman <nhorman@redhat.com>

Add via_ioctl parameter to rebuild_lun_table, et al.
This is because rebuild_lun_table wants to know if a disk is
in use before messing with it.  If the ioctl is invoked on
/dev/cciss/c0d0, then a usage count of 1 means the disk is
(otherwise) unused -- only the caller of ioctl is using it.
If rebuild_lun_table is entered another way (e.g: via
pci_init_one) then the usage count should be zero.

diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 00d3158..58fd681 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -165,8 +165,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 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 deregister_disk(ctlr_info_t *h, int drv_index, int clear_all);
+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 via_ioctl);
 static void cciss_read_capacity(int ctlr, int logvol, sector_t *total_size,
 			unsigned int *block_size);
 static void cciss_read_capacity_16(int ctlr, int logvol, sector_t *total_size,
@@ -1364,7 +1365,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 	case CCISS_REGNEWD:
 	case CCISS_DEREGDISK:
 	case CCISS_REVALIDVOLS:
-		return rebuild_lun_table(host, 0);
+		return rebuild_lun_table(host, 0, 1);
 
 	case CCISS_GETLUNINFO:{
 			LogvolInfo_struct luninfo;
@@ -1966,7 +1967,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;
@@ -2045,7 +2047,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time)
 		/* deregister_disk sets h->drv[drv_index]->queue = NULL */
 		/* 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);
 	}
 
 	/* If the disk is in use return */
@@ -2252,10 +2254,9 @@ error:
  * without a re-ordering of those drives.
  * INPUT
  * h		= The controller to perform the operations on
- * del_disk	= The disk to remove if specified.  If the value given
- *		  is NULL then no disk is removed.
  */
-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;
@@ -2334,7 +2335,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);
 			if (h->drv[i] != NULL)
 				h->drv[i]->busy_configuring = 0;
 		}
@@ -2374,7 +2375,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:
@@ -2423,9 +2425,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;
@@ -2440,7 +2448,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;
@@ -4264,7 +4272,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
 	cciss_procinit(i);
 	hba[i]->cciss_sector_size = 8192;
 	hba[i]->busy_initializing = 0;
-	rebuild_lun_table(hba[i], 1);
+	rebuild_lun_table(hba[i], 1, 0);
 
 	return 1;