summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-11-28 23:29:20 +0400
committerJames Bottomley <JBottomley@Parallels.com>2012-02-20 00:06:08 +0400
commit9095a64a9aead653df320e3a6fc70835c15d46e4 (patch)
tree63ad804f78668bf28d90ea2f8c9640ce92dacdea /include
parenta3a142524aa4b1539a64a55087bf12ffa4b1f94e (diff)
downloadlinux-9095a64a9aead653df320e3a6fc70835c15d46e4.tar.xz
[SCSI] libsas: fix timeout vs completion race
Until we have told the lldd to forget a task a timed out operation can return from the hardware at any time. Since completion frees the task we need to make sure that no tasks run their normal completion handler once eh has decided to manage the task. Similar to ata_scsi_cmd_error_handler() freeze completions to let eh judge the outcome of the race. Task collector mode is problematic because it presents a situation where a task can be timed out and aborted before the lldd has even seen it. For this case we need to guarantee that a task that an lldd has been told to forget does not get queued after the lldd says "never seen it". With sas_scsi_timed_out we achieve this with the ->task_queue_flush mutex, rather than adding more time. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'include')
-rw-r--r--include/scsi/libsas.h3
-rw-r--r--include/scsi/sas_ata.h8
2 files changed, 3 insertions, 8 deletions
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 071041b290d6..aa7192ff4355 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -178,6 +178,7 @@ enum {
};
struct domain_device {
+ spinlock_t done_lock;
enum sas_dev_type dev_type;
enum sas_linkrate linkrate;
@@ -321,6 +322,7 @@ struct asd_sas_phy {
struct scsi_core {
struct Scsi_Host *shost;
+ struct mutex task_queue_flush;
spinlock_t task_queue_lock;
struct list_head task_queue;
int task_queue_size;
@@ -337,6 +339,7 @@ enum sas_ha_state {
SAS_HA_REGISTERED,
SAS_HA_DRAINING,
SAS_HA_ATA_EH_ACTIVE,
+ SAS_HA_FROZEN,
};
struct sas_ha_struct {
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
index 557fc9a8559b..9f7a23d1146d 100644
--- a/include/scsi/sas_ata.h
+++ b/include/scsi/sas_ata.h
@@ -41,8 +41,6 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,
void sas_ata_task_abort(struct sas_task *task);
void sas_ata_strategy_handler(struct Scsi_Host *shost);
-int sas_ata_timed_out(struct scsi_cmnd *cmd, struct sas_task *task,
- enum blk_eh_timer_return *rtn);
int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
struct list_head *done_q);
void sas_probe_sata(struct work_struct *work);
@@ -67,12 +65,6 @@ static inline void sas_ata_strategy_handler(struct Scsi_Host *shost)
{
}
-static inline int sas_ata_timed_out(struct scsi_cmnd *cmd,
- struct sas_task *task,
- enum blk_eh_timer_return *rtn)
-{
- return 0;
-}
static inline int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
struct list_head *done_q)
{