* [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).