linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] scsi host / scsi target state model update
@ 2005-06-16 18:10 Mike Anderson
  2005-06-16 18:12 ` [PATCH 1/5] " Mike Anderson
  0 siblings, 1 reply; 7+ messages in thread
From: Mike Anderson @ 2005-06-16 18:10 UTC (permalink / raw)
  To: linux-scsi

This patch sequence converts the SCSI host state model to a model like
SCSI device is using and adds a state model for SCSI targets. These new
state models are then used to help in the removal of targets and devices
during removal of a SCSI host.

I have done some simple add and delete testing. The target state model
should have more of the targets states covered. The
list_for_each_entry_safe in __scsi_remove_target needs to be cleaned up.

For background context please refer to previous mail.

http://marc.theaimsgroup.com/?t=111878458800003&r=1&w=2

http://marc.theaimsgroup.com/?t=111833447800002&r=1&w=2


-andmike
--
Michael Anderson
andmike@us.ibm.com


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] scsi host / scsi target state model update
  2005-06-16 18:10 [PATCH 0/5] scsi host / scsi target state model update Mike Anderson
@ 2005-06-16 18:12 ` Mike Anderson
  2005-06-16 18:13   ` [PATCH 2/5] " Mike Anderson
  0 siblings, 1 reply; 7+ messages in thread
From: Mike Anderson @ 2005-06-16 18:12 UTC (permalink / raw)
  To: linux-scsi

Migrate the current SCSI host state model to a model like SCSI
device is using.

Signed-off-by: Mike Anderson <andmike@us.ibm.com>
---

 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/hosts.c      |   88 +++++++++++++++--
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi.c       |    2 
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_error.c |    7 -
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_ioctl.c |    3 
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_lib.c   |    4 
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_sysfs.c |   62 +++++++++++
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/sg.c         |    3 
 linux-2.6.12-rc6-mm1-andmike/include/scsi/scsi_host.h  |   14 +-
 8 files changed, 162 insertions(+), 21 deletions(-)

diff -puN include/scsi/scsi_host.h~host_state include/scsi/scsi_host.h
--- linux-2.6.12-rc6-mm1/include/scsi/scsi_host.h~host_state	2005-06-10 15:32:17.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/include/scsi/scsi_host.h	2005-06-16 10:27:40.000000000 -0700
@@ -429,12 +429,15 @@ struct scsi_host_template {
 };
 
 /*
- * shost states
+ * shost state: If you alter this, you also need to alter scsi_sysfs.c
+ * (for the ascii descriptions) and the state model enforcer:
+ * scsi_host_set_state()
  */
-enum {
-	SHOST_ADD,
-	SHOST_DEL,
+enum scsi_host_state {
+	SHOST_CREATED = 1,
+	SHOST_RUNNING,
 	SHOST_CANCEL,
+	SHOST_DEL,
 	SHOST_RECOVERY,
 };
 
@@ -575,7 +578,7 @@ struct Scsi_Host {
 	unsigned int  irq;
 	
 
-	unsigned long shost_state;
+	enum scsi_host_state shost_state;
 
 	/* ldm bits */
 	struct device		shost_gendev;
@@ -633,6 +636,7 @@ extern void scsi_remove_host(struct Scsi
 extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
 extern void scsi_host_put(struct Scsi_Host *t);
 extern struct Scsi_Host *scsi_host_lookup(unsigned short);
+extern const char *scsi_host_state_name(enum scsi_host_state);
 
 extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *);
 
diff -puN drivers/scsi/scsi_sysfs.c~host_state drivers/scsi/scsi_sysfs.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi_sysfs.c~host_state	2005-06-10 15:32:17.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_sysfs.c	2005-06-16 10:27:38.000000000 -0700
@@ -48,6 +48,30 @@ const char *scsi_device_state_name(enum 
 	return name;
 }
 
+static struct {
+	enum scsi_host_state	value;
+	char			*name;
+} shost_states[] = {
+	{ SHOST_CREATED, "created" },
+	{ SHOST_RUNNING, "running" },
+	{ SHOST_CANCEL, "cancel" },
+	{ SHOST_DEL, "deleted" },
+	{ SHOST_RECOVERY, "recovery" },
+};
+const char *scsi_host_state_name(enum scsi_host_state state)
+{
+	int i;
+	char *name = NULL;
+
+	for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
+		if (shost_states[i].value == state) {
+			name = shost_states[i].name;
+			break;
+		}
+	}
+	return name;
+}
+
 static int check_set(unsigned int *val, char *src)
 {
 	char *last;
@@ -124,6 +148,43 @@ static ssize_t store_scan(struct class_d
 };
 static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
 
+static ssize_t
+store_shost_state(struct class_device *class_dev, const char *buf, size_t count)
+{
+	int i;
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	enum scsi_host_state state = 0;
+
+	for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
+		const int len = strlen(shost_states[i].name);
+		if (strncmp(shost_states[i].name, buf, len) == 0 &&
+		   buf[len] == '\n') {
+			state = shost_states[i].value;
+			break;
+		}
+	}
+	if (!state)
+		return -EINVAL;
+
+	if (scsi_host_set_state(shost, state))
+		return -EINVAL;
+	return count;
+}
+
+static ssize_t
+show_shost_state(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	const char *name = scsi_host_state_name(shost->shost_state);
+
+	if (!name)
+		return -EINVAL;
+
+	return snprintf(buf, 20, "%s\n", name);
+}
+
+static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
+
 shost_rd_attr(unique_id, "%u\n");
 shost_rd_attr(host_busy, "%hu\n");
 shost_rd_attr(cmd_per_lun, "%hd\n");
@@ -139,6 +200,7 @@ static struct class_device_attribute *sc
 	&class_device_attr_unchecked_isa_dma,
 	&class_device_attr_proc_name,
 	&class_device_attr_scan,
+	&class_device_attr_state,
 	NULL
 };
 
diff -puN drivers/scsi/hosts.c~host_state drivers/scsi/hosts.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/hosts.c~host_state	2005-06-10 15:32:17.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/hosts.c	2005-06-16 10:34:22.000000000 -0700
@@ -52,6 +52,82 @@ static struct class shost_class = {
 };
 
 /**
+ *	scsi_host_set_state - Take the given host through the host
+ *		state model.
+ *	@shost:	scsi host to change the state of.
+ *	@state:	state to change to.
+ *
+ *	Returns zero if unsuccessful or an error if the requested
+ *	transition is illegal.
+ **/
+int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
+{
+	enum scsi_host_state oldstate = shost->shost_state;
+
+	if (state == oldstate)
+		return 0;
+
+	switch (state) {
+	case SHOST_CREATED:
+		/* There are no legal states that come back to
+		 * created.  This is the manually initialised start
+		 * state */
+		goto illegal;
+
+	case SHOST_RUNNING:
+		switch (oldstate) {
+		case SHOST_CREATED:
+		case SHOST_RECOVERY:
+			break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	case SHOST_RECOVERY:
+		switch (oldstate) {
+		case SHOST_RUNNING:
+			break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	case SHOST_CANCEL:
+		switch (oldstate) {
+		case SHOST_CREATED:
+		case SHOST_RUNNING:
+			break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	case SHOST_DEL:
+		switch (oldstate) {
+		case SHOST_CANCEL:
+			break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	}
+	shost->shost_state = state;
+	return 0;
+
+ illegal:
+	SCSI_LOG_ERROR_RECOVERY(1,
+				dev_printk(KERN_ERR, &shost->shost_gendev,
+					   "Illegal host state transition"
+					   "%s->%s\n",
+					   scsi_host_state_name(oldstate),
+					   scsi_host_state_name(state)));
+	return -EINVAL;
+}
+EXPORT_SYMBOL(scsi_host_set_state);
+
+/**
  * scsi_host_cancel - cancel outstanding IO to this host
  * @shost:	pointer to struct Scsi_Host
  * recovery:	recovery requested to run.
@@ -60,12 +136,11 @@ static void scsi_host_cancel(struct Scsi
 {
 	struct scsi_device *sdev;
 
-	set_bit(SHOST_CANCEL, &shost->shost_state);
+	scsi_host_set_state(shost, SHOST_CANCEL);
 	shost_for_each_device(sdev, shost) {
 		scsi_device_cancel(sdev, recovery);
 	}
-	wait_event(shost->host_wait, (!test_bit(SHOST_RECOVERY,
-						&shost->shost_state)));
+	wait_event(shost->host_wait, (shost->shost_state != SHOST_RECOVERY));
 }
 
 /**
@@ -78,7 +153,7 @@ void scsi_remove_host(struct Scsi_Host *
 	scsi_host_cancel(shost, 0);
 	scsi_proc_host_rm(shost);
 
-	set_bit(SHOST_DEL, &shost->shost_state);
+	scsi_host_set_state(shost, SHOST_DEL);
 
 	transport_unregister_device(&shost->shost_gendev);
 	class_device_unregister(&shost->shost_classdev);
@@ -115,7 +190,7 @@ int scsi_add_host(struct Scsi_Host *shos
 	if (error)
 		goto out;
 
-	set_bit(SHOST_ADD, &shost->shost_state);
+	scsi_host_set_state(shost, SHOST_RUNNING);
 	get_device(shost->shost_gendev.parent);
 
 	error = class_device_add(&shost->shost_classdev);
@@ -231,6 +306,7 @@ struct Scsi_Host *scsi_host_alloc(struct
 
 	spin_lock_init(&shost->default_lock);
 	scsi_assign_lock(shost, &shost->default_lock);
+	shost->shost_state = SHOST_CREATED;
 	INIT_LIST_HEAD(&shost->__devices);
 	INIT_LIST_HEAD(&shost->__targets);
 	INIT_LIST_HEAD(&shost->eh_cmd_q);
@@ -387,7 +463,7 @@ EXPORT_SYMBOL(scsi_host_lookup);
  **/
 struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost)
 {
-	if (test_bit(SHOST_DEL, &shost->shost_state) ||
+	if ((shost->shost_state == SHOST_DEL) ||
 		!get_device(&shost->shost_gendev))
 		return NULL;
 	return shost;
diff -puN drivers/scsi/scsi.c~host_state drivers/scsi/scsi.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi.c~host_state	2005-06-10 15:32:17.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi.c	2005-06-16 10:27:42.000000000 -0700
@@ -632,7 +632,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
 	spin_lock_irqsave(host->host_lock, flags);
 	scsi_cmd_get_serial(host, cmd); 
 
-	if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) {
+	if (unlikely(host->shost_state == SHOST_CANCEL)) {
 		cmd->result = (DID_NO_CONNECT << 16);
 		scsi_done(cmd);
 	} else {
diff -puN drivers/scsi/scsi_error.c~host_state drivers/scsi/scsi_error.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi_error.c~host_state	2005-06-16 10:34:33.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_error.c	2005-06-16 10:38:04.000000000 -0700
@@ -80,7 +80,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *s
 	scmd->owner = SCSI_OWNER_ERROR_HANDLER;
 	scmd->state = SCSI_STATE_FAILED;
 	list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
-	set_bit(SHOST_RECOVERY, &shost->shost_state);
+	scsi_host_set_state(shost, SHOST_RECOVERY);
 	shost->host_failed++;
 	scsi_eh_wakeup(shost);
 	spin_unlock_irqrestore(shost->host_lock, flags);
@@ -202,7 +202,8 @@ int scsi_block_when_processing_errors(st
 {
 	int online;
 
-	wait_event(sdev->host->host_wait, (!test_bit(SHOST_RECOVERY, &sdev->host->shost_state)));
+	wait_event(sdev->host->host_wait, (sdev->host->shost_state !=
+					   SHOST_RECOVERY));
 
 	online = scsi_device_online(sdev);
 
@@ -1513,7 +1514,7 @@ static void scsi_restart_operations(stru
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
 					  __FUNCTION__));
 
-	clear_bit(SHOST_RECOVERY, &shost->shost_state);
+	scsi_host_set_state(shost, SHOST_RUNNING);
 
 	wake_up(&shost->host_wait);
 
diff -puN drivers/scsi/scsi_ioctl.c~host_state drivers/scsi/scsi_ioctl.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi_ioctl.c~host_state	2005-06-16 10:38:28.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_ioctl.c	2005-06-16 10:39:26.000000000 -0700
@@ -475,8 +475,7 @@ int scsi_nonblockable_ioctl(struct scsi_
 	 * error processing, as long as the device was opened
 	 * non-blocking */
 	if (filp && filp->f_flags & O_NONBLOCK) {
-		if (test_bit(SHOST_RECOVERY,
-			     &sdev->host->shost_state))
+		if (sdev->host->shost_state == SHOST_RECOVERY)
 			return -ENODEV;
 	} else if (!scsi_block_when_processing_errors(sdev))
 		return -ENODEV;
diff -puN drivers/scsi/scsi_lib.c~host_state drivers/scsi/scsi_lib.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi_lib.c~host_state	2005-06-16 10:39:38.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_lib.c	2005-06-16 10:41:22.000000000 -0700
@@ -357,7 +357,7 @@ void scsi_device_unbusy(struct scsi_devi
 
 	spin_lock_irqsave(shost->host_lock, flags);
 	shost->host_busy--;
-	if (unlikely(test_bit(SHOST_RECOVERY, &shost->shost_state) &&
+	if (unlikely((shost->shost_state == SHOST_RECOVERY) &&
 		     shost->host_failed))
 		scsi_eh_wakeup(shost);
 	spin_unlock(shost->host_lock);
@@ -1218,7 +1218,7 @@ static inline int scsi_host_queue_ready(
 				   struct Scsi_Host *shost,
 				   struct scsi_device *sdev)
 {
-	if (test_bit(SHOST_RECOVERY, &shost->shost_state))
+	if (shost->shost_state == SHOST_RECOVERY)
 		return 0;
 	if (shost->host_busy == 0 && shost->host_blocked) {
 		/*
diff -puN drivers/scsi/sg.c~host_state drivers/scsi/sg.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/sg.c~host_state	2005-06-16 10:41:42.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/sg.c	2005-06-16 10:42:17.000000000 -0700
@@ -1027,8 +1027,7 @@ sg_ioctl(struct inode *inode, struct fil
 		if (sdp->detached)
 			return -ENODEV;
 		if (filp->f_flags & O_NONBLOCK) {
-			if (test_bit(SHOST_RECOVERY,
-				     &sdp->device->host->shost_state))
+			if (sdp->device->host->shost_state == SHOST_RECOVERY)
 				return -EBUSY;
 		} else if (!scsi_block_when_processing_errors(sdp->device))
 			return -EBUSY;
_

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/5] scsi host / scsi target state model update
  2005-06-16 18:12 ` [PATCH 1/5] " Mike Anderson
@ 2005-06-16 18:13   ` Mike Anderson
  2005-06-16 18:14     ` [PATCH 3/5] " Mike Anderson
  0 siblings, 1 reply; 7+ messages in thread
From: Mike Anderson @ 2005-06-16 18:13 UTC (permalink / raw)
  To: linux-scsi

Remove the old scsi_host_cancel function as it has not been working for
sometime do to the device list possibly being empty when it is called and
possible race issues. Add setting of SHOST_CANCEL at the state of beginning
of scsi_remove_host.

Signed-off-by: Mike Anderson <andmike@us.ibm.com>
---

 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/hosts.c |   18 +-----------------
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi.c  |    2 +-
 2 files changed, 2 insertions(+), 18 deletions(-)

diff -puN drivers/scsi/hosts.c~host_cancel drivers/scsi/hosts.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/hosts.c~host_cancel	2005-06-16 10:43:44.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/hosts.c	2005-06-16 10:45:21.000000000 -0700
@@ -128,29 +128,13 @@ int scsi_host_set_state(struct Scsi_Host
 EXPORT_SYMBOL(scsi_host_set_state);
 
 /**
- * scsi_host_cancel - cancel outstanding IO to this host
- * @shost:	pointer to struct Scsi_Host
- * recovery:	recovery requested to run.
- **/
-static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
-{
-	struct scsi_device *sdev;
-
-	scsi_host_set_state(shost, SHOST_CANCEL);
-	shost_for_each_device(sdev, shost) {
-		scsi_device_cancel(sdev, recovery);
-	}
-	wait_event(shost->host_wait, (shost->shost_state != SHOST_RECOVERY));
-}
-
-/**
  * scsi_remove_host - remove a scsi host
  * @shost:	a pointer to a scsi host to remove
  **/
 void scsi_remove_host(struct Scsi_Host *shost)
 {
+	scsi_host_set_state(shost, SHOST_CANCEL);
 	scsi_forget_host(shost);
-	scsi_host_cancel(shost, 0);
 	scsi_proc_host_rm(shost);
 
 	scsi_host_set_state(shost, SHOST_DEL);
diff -puN drivers/scsi/scsi.c~host_cancel drivers/scsi/scsi.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi.c~host_cancel	2005-06-16 10:43:44.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi.c	2005-06-16 10:43:44.000000000 -0700
@@ -632,7 +632,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
 	spin_lock_irqsave(host->host_lock, flags);
 	scsi_cmd_get_serial(host, cmd); 
 
-	if (unlikely(host->shost_state == SHOST_CANCEL)) {
+	if (unlikely(host->shost_state == SHOST_DEL)) {
 		cmd->result = (DID_NO_CONNECT << 16);
 		scsi_done(cmd);
 	} else {
_

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/5] scsi host / scsi target state model update
  2005-06-16 18:13   ` [PATCH 2/5] " Mike Anderson
@ 2005-06-16 18:14     ` Mike Anderson
  2005-06-16 18:15       ` [PATCH 4/5] " Mike Anderson
  0 siblings, 1 reply; 7+ messages in thread
From: Mike Anderson @ 2005-06-16 18:14 UTC (permalink / raw)
  To: linux-scsi

Add support to not allow additions to a host when it is being removed.

Signed-off-by: Mike Anderson <andmike@us.ibm.com>
---

 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/hosts.c     |    2 +
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_scan.c |   21 ++++++++++++------
 linux-2.6.12-rc6-mm1-andmike/include/scsi/scsi_host.h |    9 +++++++
 3 files changed, 25 insertions(+), 7 deletions(-)

diff -puN drivers/scsi/hosts.c~host_scan drivers/scsi/hosts.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/hosts.c~host_scan	2005-06-16 10:47:17.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/hosts.c	2005-06-16 10:47:17.000000000 -0700
@@ -133,7 +133,9 @@ EXPORT_SYMBOL(scsi_host_set_state);
  **/
 void scsi_remove_host(struct Scsi_Host *shost)
 {
+	down(&shost->scan_mutex);
 	scsi_host_set_state(shost, SHOST_CANCEL);
+	up(&shost->scan_mutex);
 	scsi_forget_host(shost);
 	scsi_proc_host_rm(shost);
 
diff -puN include/scsi/scsi_host.h~host_scan include/scsi/scsi_host.h
--- linux-2.6.12-rc6-mm1/include/scsi/scsi_host.h~host_scan	2005-06-16 10:47:17.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/include/scsi/scsi_host.h	2005-06-16 10:47:17.000000000 -0700
@@ -656,6 +656,15 @@ static inline struct device *scsi_get_de
         return shost->shost_gendev.parent;
 }
 
+/**
+ * scsi_host_scan_allowed - Is scanning of this host allowed
+ * @shost:	Pointer to Scsi_Host.
+ **/
+static inline int scsi_host_scan_allowed(struct Scsi_Host *shost)
+{
+	return shost->shost_state == SHOST_RUNNING;
+}
+
 extern void scsi_unblock_requests(struct Scsi_Host *);
 extern void scsi_block_requests(struct Scsi_Host *);
 
diff -puN drivers/scsi/scsi_scan.c~host_scan drivers/scsi/scsi_scan.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi_scan.c~host_scan	2005-06-16 10:47:17.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_scan.c	2005-06-16 10:47:17.000000000 -0700
@@ -1218,9 +1218,12 @@ struct scsi_device *__scsi_add_device(st
 
 	get_device(&starget->dev);
 	down(&shost->scan_mutex);
-	res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
-	if (res != SCSI_SCAN_LUN_PRESENT)
-		sdev = ERR_PTR(-ENODEV);
+	if (scsi_host_scan_allowed(shost)) {
+		res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1,
+					     hostdata);
+		if (res != SCSI_SCAN_LUN_PRESENT)
+			sdev = ERR_PTR(-ENODEV);
+	}
 	up(&shost->scan_mutex);
 	scsi_target_reap(starget);
 	put_device(&starget->dev);
@@ -1370,11 +1373,15 @@ int scsi_scan_host_selected(struct Scsi_
 		return -EINVAL;
 
 	down(&shost->scan_mutex);
-	if (channel == SCAN_WILD_CARD) 
-		for (channel = 0; channel <= shost->max_channel; channel++)
+	if (scsi_host_scan_allowed(shost)) {
+		if (channel == SCAN_WILD_CARD)
+			for (channel = 0; channel <= shost->max_channel;
+			     channel++)
+				scsi_scan_channel(shost, channel, id, lun,
+						  rescan);
+		else
 			scsi_scan_channel(shost, channel, id, lun, rescan);
-	else
-		scsi_scan_channel(shost, channel, id, lun, rescan);
+	}
 	up(&shost->scan_mutex);
 
 	return 0;
_

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 4/5] scsi host / scsi target state model update
  2005-06-16 18:14     ` [PATCH 3/5] " Mike Anderson
@ 2005-06-16 18:15       ` Mike Anderson
  2005-06-16 18:16         ` [PATCH 5/5] " Mike Anderson
  2005-07-12 16:44         ` [PATCH 4/5] " James Bottomley
  0 siblings, 2 replies; 7+ messages in thread
From: Mike Anderson @ 2005-06-16 18:15 UTC (permalink / raw)
  To: linux-scsi

Add a SCSI target state model similar to the SCSI device state model.

Signed-off-by: Mike Anderson <andmike@us.ibm.com>
---

 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_lib.c    |   57 ++++++++++++++++
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_scan.c   |    1 
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_sysfs.c  |   23 ++++++
 linux-2.6.12-rc6-mm1-andmike/include/scsi/scsi_device.h |   13 +++
 4 files changed, 94 insertions(+)

diff -puN include/scsi/scsi_device.h~tgt_state include/scsi/scsi_device.h
--- linux-2.6.12-rc6-mm1/include/scsi/scsi_device.h~tgt_state	2005-06-16 10:47:35.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/include/scsi/scsi_device.h	2005-06-16 10:47:35.000000000 -0700
@@ -140,6 +140,16 @@ struct scsi_device {
 	to_scsi_device(class_dev->dev)
 
 /*
+ * stgt state:
+ * scsi_lib:scsi_device_set_state().
+ */
+enum scsi_target_state {
+	STGT_RUNNING = 1,	/* Target properly configured */
+	STGT_CANCEL,		/* Beginning to delete Target */
+	STGT_DEL,		/* Target deleted */
+};
+
+/*
  * scsi_target: representation of a scsi target, for now, this is only
  * used for single_lun devices. If no one has active IO to the target,
  * starget_sdev_user is NULL, else it points to the active sdev.
@@ -155,6 +165,7 @@ struct scsi_target {
 				     * scsi_device.id eventually */
 	unsigned long		create:1; /* signal that it needs to be added */
 	void 			*hostdata; /* available to low-level driver */
+	enum scsi_target_state	stgt_state;
 	unsigned long		starget_data[0]; /* for the transport */
 	/* starget_data must be the last element!!!! */
 } __attribute__((aligned(sizeof(unsigned long))));
@@ -233,6 +244,8 @@ extern int scsi_test_unit_ready(struct s
 				int retries);
 extern int scsi_device_set_state(struct scsi_device *sdev,
 				 enum scsi_device_state state);
+extern int scsi_target_set_state(struct scsi_target *,
+				 enum scsi_device_state);
 extern int scsi_device_quiesce(struct scsi_device *sdev);
 extern void scsi_device_resume(struct scsi_device *sdev);
 extern void scsi_target_quiesce(struct scsi_target *);
diff -puN drivers/scsi/scsi_lib.c~tgt_state drivers/scsi/scsi_lib.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi_lib.c~tgt_state	2005-06-16 10:47:35.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_lib.c	2005-06-16 10:47:35.000000000 -0700
@@ -1819,6 +1819,63 @@ scsi_device_set_state(struct scsi_device
 EXPORT_SYMBOL(scsi_device_set_state);
 
 /**
+ *	scsi_target_set_state - Take the given target through the target
+ *		state model.
+ *	@starget: scsi target to change the state of.
+ *	@state:	state to change to.
+ *
+ *	Returns zero if unsuccessful or an error if the requested
+ *	transition is illegal.
+ **/
+int
+scsi_target_set_state(struct scsi_target *starget, enum scsi_target_state state)
+{
+	enum scsi_target_state oldstate = starget->stgt_state;
+
+	if (state == oldstate)
+		return 0;
+
+	switch (state) {
+	case STGT_RUNNING:
+		/* There are no legal states that come back to
+		 * created.  This is the manually initialised start
+		 * state */
+		goto illegal;
+
+	case STGT_CANCEL:
+		switch (oldstate) {
+		case STGT_RUNNING:
+			break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	case STGT_DEL:
+		switch (oldstate) {
+		case STGT_CANCEL:
+			break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	}
+	starget->stgt_state = state;
+	return 0;
+
+ illegal:
+	SCSI_LOG_ERROR_RECOVERY(1,
+				dev_printk(KERN_ERR, &starget->dev,
+					   "Illegal state transition %s->%s\n",
+					   scsi_target_state_name(oldstate),
+					   scsi_target_state_name(state))
+				);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(scsi_target_set_state);
+
+/**
  *	scsi_device_quiesce - Block user issued commands.
  *	@sdev:	scsi device to quiesce.
  *
diff -puN drivers/scsi/scsi_sysfs.c~tgt_state drivers/scsi/scsi_sysfs.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi_sysfs.c~tgt_state	2005-06-16 10:47:35.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_sysfs.c	2005-06-16 10:47:35.000000000 -0700
@@ -49,6 +49,29 @@ const char *scsi_device_state_name(enum 
 }
 
 static struct {
+	enum scsi_target_state	value;
+	char			*name;
+} stgt_states[] = {
+	{ STGT_RUNNING, "running" },
+	{ STGT_CANCEL, "cancel" },
+	{ STGT_DEL, "deleted" },
+};
+
+const char *scsi_target_state_name(enum scsi_target_state state)
+{
+	int i;
+	char *name = NULL;
+
+	for (i = 0; i < sizeof(stgt_states)/sizeof(stgt_states[0]); i++) {
+		if (stgt_states[i].value == state) {
+			name = stgt_states[i].name;
+			break;
+		}
+	}
+	return name;
+}
+
+static struct {
 	enum scsi_host_state	value;
 	char			*name;
 } shost_states[] = {
diff -puN drivers/scsi/scsi_scan.c~tgt_state drivers/scsi/scsi_scan.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi_scan.c~tgt_state	2005-06-16 10:47:35.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_scan.c	2005-06-16 10:47:35.000000000 -0700
@@ -361,6 +361,7 @@ static struct scsi_target *scsi_alloc_ta
 	if (found_target)
 		goto found;
 
+	starget->stgt_state = STGT_RUNNING;
 	list_add_tail(&starget->siblings, &shost->__targets);
 	spin_unlock_irqrestore(shost->host_lock, flags);
 	/* allocate and add */
_

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 5/5] scsi host / scsi target state model update
  2005-06-16 18:15       ` [PATCH 4/5] " Mike Anderson
@ 2005-06-16 18:16         ` Mike Anderson
  2005-07-12 16:44         ` [PATCH 4/5] " James Bottomley
  1 sibling, 0 replies; 7+ messages in thread
From: Mike Anderson @ 2005-06-16 18:16 UTC (permalink / raw)
  To: linux-scsi

Use new SCSI target state model in scsi_forget_host to help with list
traversal and deletion of devices.

Signed-off-by: Mike Anderson <andmike@us.ibm.com>
---

 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_scan.c  |   32 +++++++++--------
 linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_sysfs.c |    1 
 2 files changed, 18 insertions(+), 15 deletions(-)

diff -puN drivers/scsi/scsi_scan.c~tgt_remove drivers/scsi/scsi_scan.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi_scan.c~tgt_remove	2005-06-16 10:48:38.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_scan.c	2005-06-16 10:48:38.000000000 -0700
@@ -1414,25 +1414,27 @@ EXPORT_SYMBOL(scsi_scan_single_target);
 
 void scsi_forget_host(struct Scsi_Host *shost)
 {
-	struct scsi_target *starget, *tmp;
+	struct scsi_target *starget;
 	unsigned long flags;
 
-	/*
-	 * Ok, this look a bit strange.  We always look for the first device
-	 * on the list as scsi_remove_device removes them from it - thus we
-	 * also have to release the lock.
-	 * We don't need to get another reference to the device before
-	 * releasing the lock as we already own the reference from
-	 * scsi_register_device that's release in scsi_remove_device.  And
-	 * after that we don't look at sdev anymore.
-	 */
-	spin_lock_irqsave(shost->host_lock, flags);
-	list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) {
-		spin_unlock_irqrestore(shost->host_lock, flags);
-		scsi_remove_target(&starget->dev);
+	while (1) {
+		starget = NULL;
 		spin_lock_irqsave(shost->host_lock, flags);
+		list_for_each_entry(starget, &shost->__targets, siblings) {
+			if (starget->stgt_state == STGT_DEL)
+				continue;
+			if (starget->stgt_state != STGT_CANCEL) {
+				scsi_target_set_state(starget, STGT_CANCEL);
+				break;
+			}
+		}
+		spin_unlock_irqrestore(shost->host_lock, flags);
+
+		if (starget && starget->stgt_state != STGT_DEL)
+			scsi_remove_target(&starget->dev);
+		else
+			return;
 	}
-	spin_unlock_irqrestore(shost->host_lock, flags);
 }
 
 /*
diff -puN drivers/scsi/scsi_sysfs.c~tgt_remove drivers/scsi/scsi_sysfs.c
--- linux-2.6.12-rc6-mm1/drivers/scsi/scsi_sysfs.c~tgt_remove	2005-06-16 10:48:38.000000000 -0700
+++ linux-2.6.12-rc6-mm1-andmike/drivers/scsi/scsi_sysfs.c	2005-06-16 10:48:38.000000000 -0700
@@ -750,6 +750,7 @@ void __scsi_remove_target(struct scsi_ta
 		scsi_remove_device(sdev);
 		spin_lock_irqsave(shost->host_lock, flags);
 	}
+	scsi_target_set_state(starget, STGT_DEL);
 	spin_unlock_irqrestore(shost->host_lock, flags);
 	scsi_target_reap(starget);
 }
_

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/5] scsi host / scsi target state model update
  2005-06-16 18:15       ` [PATCH 4/5] " Mike Anderson
  2005-06-16 18:16         ` [PATCH 5/5] " Mike Anderson
@ 2005-07-12 16:44         ` James Bottomley
  1 sibling, 0 replies; 7+ messages in thread
From: James Bottomley @ 2005-07-12 16:44 UTC (permalink / raw)
  To: Mike Anderson; +Cc: SCSI Mailing List

On Thu, 2005-06-16 at 11:15 -0700, Mike Anderson wrote:
> Add a SCSI target state model similar to the SCSI device state model.

The first three patches look good (sorry been a hectic month, just
getting around to looking through them) so I'll stick them in scsi-misc
and see how they work out.

Currently, the target is really slaved to the devices, so we have no
actual need of a target state model (if you destroy the last device on a
target, the target is also destroyed).

However, ressurecting this could be part of a more comprehensive target
model if someone actually proves a need for it.

James



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2005-07-12 17:51 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-06-16 18:10 [PATCH 0/5] scsi host / scsi target state model update Mike Anderson
2005-06-16 18:12 ` [PATCH 1/5] " Mike Anderson
2005-06-16 18:13   ` [PATCH 2/5] " Mike Anderson
2005-06-16 18:14     ` [PATCH 3/5] " Mike Anderson
2005-06-16 18:15       ` [PATCH 4/5] " Mike Anderson
2005-06-16 18:16         ` [PATCH 5/5] " Mike Anderson
2005-07-12 16:44         ` [PATCH 4/5] " James Bottomley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).