Skip to contentSkip to conversation

add device quiescing to the SCSI API

PATCH New James Bottomley 1 participant 1 message Mar 12, 2004 SCSI

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 add device quiescing to the SCSI API

This patch adds the ability to quiesce a SCSI device. The idea is that user issued commands (including filesystem ones) would get blocked, while mid-layer and device issued ones would be allowed to proceed. This is for things like Domain Validation which like to operate on an otherwise quiet device.

There is one big change: to get all of this to happen correctly, scsi_do_req() has to queue on the *head* of the request queue, not the tail as it was doing previously. The reason is that deferred requests block the queue, so anything needing executing after a deferred request has to go in front of it. I don't think there are any untoward consequences of this, but let me know if you spot any.

James

===== drivers/scsi/scsi.c 1.139 vs edited =====

drivers/scsi/scsi.c +1 -1
@@ -1097,7 +1097,7 @@
 	struct list_head *lh, *lh_sf;
 	unsigned long flags;
 
-	sdev->sdev_state = SDEV_CANCEL;
+	scsi_device_set_state(sdev, SDEV_CANCEL);
 
 	spin_lock_irqsave(&sdev->list_lock, flags);
 	list_for_each_entry(scmd, &sdev->cmd_list, list) {

===== drivers/scsi/scsi_lib.c 1.122 vs edited =====

drivers/scsi/scsi_lib.c +102 -5

135 lines not on this page · raw message

===== drivers/scsi/scsi_sysfs.c 1.41 vs edited =====

drivers/scsi/scsi_sysfs.c +4 -6
@@ -351,13 +351,11 @@
 int scsi_sysfs_add_sdev(struct scsi_device *sdev)
 {
 	struct class_device_attribute **attrs;
-	int error = -EINVAL, i;
+	int error, i;
 
-	if (sdev->sdev_state != SDEV_CREATED)
+	if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
 		return error;
 
-	sdev->sdev_state = SDEV_RUNNING;
-
 	error = device_add(&sdev->sdev_gendev);
 	if (error) {
 		printk(KERN_INFO "error 1\n");
@@ -419,7 +417,7 @@
  clean_device2:
 	class_device_del(&sdev->sdev_classdev);
  clean_device:
-	sdev->sdev_state = SDEV_CANCEL;
+	scsi_device_set_state(sdev, SDEV_CANCEL);
 
 	device_del(&sdev->sdev_gendev);
 	put_device(&sdev->sdev_gendev);
@@ -434,7 +432,7 @@
 void scsi_remove_device(struct scsi_device *sdev)
 {
 	if (sdev->sdev_state == SDEV_RUNNING || sdev->sdev_state == SDEV_CANCEL) {
-		sdev->sdev_state = SDEV_DEL;
+		scsi_device_set_state(sdev, SDEV_DEL);
 		class_device_unregister(&sdev->sdev_classdev);
 		class_device_unregister(&sdev->transport_classdev);
 		device_del(&sdev->sdev_gendev);

===== include/scsi/scsi_device.h 1.13 vs edited =====

include/scsi/scsi_device.h +8 -1
@@ -15,7 +15,7 @@
  * sdev state
  */
 enum scsi_device_state {
-	SDEV_CREATED,		/* device created but not added to sysfs
+	SDEV_CREATED = 1,	/* device created but not added to sysfs
 				 * Only internal commands allowed (for inq) */
 	SDEV_RUNNING,		/* device properly configured
 				 * All commands allowed */
@@ -23,6 +23,9 @@
 				 * Only error handler commands allowed */
 	SDEV_DEL,		/* device deleted 
 				 * no commands allowed */
+	SDEV_QUIESCE,		/* Device quiescent.  No block commands
+				 * will be accepted, only specials (which
+				 * originate in the mid-layer) */
 };
 
 struct scsi_device {
@@ -170,4 +173,8 @@
 extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
 			   unsigned char *buffer, int len, int timeout,
 			   int retries, struct scsi_mode_data *data);
+extern int scsi_device_set_state(struct scsi_device *sdev,
+				 enum scsi_device_state state);
+extern int scsi_device_quiesce(struct scsi_device *sdev);
+extern void scsi_device_resume(struct scsi_device *sdev);
 #endif /* _SCSI_SCSI_DEVICE_H */