Commit 76ad3e59 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by James Bottomley

[SCSI] Unlock accesses to eh_deadline

32bit accesses are guaranteed to be atomic, so we can remove
the spinlock when checking for eh_deadline. We only need to
make sure to catch any updates which might happened during
the call to time_before(); if so we just recheck with the
correct value.
Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent e494f6a7
...@@ -94,8 +94,15 @@ static int scsi_host_eh_past_deadline(struct Scsi_Host *shost) ...@@ -94,8 +94,15 @@ static int scsi_host_eh_past_deadline(struct Scsi_Host *shost)
if (!shost->last_reset || !shost->eh_deadline) if (!shost->last_reset || !shost->eh_deadline)
return 0; return 0;
if (time_before(jiffies, /*
shost->last_reset + shost->eh_deadline)) * 32bit accesses are guaranteed to be atomic
* (on all supported architectures), so instead
* of using a spinlock we can as well double check
* if eh_deadline has been unset during the
* time_before call.
*/
if (time_before(jiffies, shost->last_reset + shost->eh_deadline) &&
shost->eh_deadline != 0)
return 0; return 0;
return 1; return 1;
...@@ -111,18 +118,14 @@ scmd_eh_abort_handler(struct work_struct *work) ...@@ -111,18 +118,14 @@ scmd_eh_abort_handler(struct work_struct *work)
struct scsi_cmnd *scmd = struct scsi_cmnd *scmd =
container_of(work, struct scsi_cmnd, abort_work.work); container_of(work, struct scsi_cmnd, abort_work.work);
struct scsi_device *sdev = scmd->device; struct scsi_device *sdev = scmd->device;
unsigned long flags;
int rtn; int rtn;
spin_lock_irqsave(sdev->host->host_lock, flags);
if (scsi_host_eh_past_deadline(sdev->host)) { if (scsi_host_eh_past_deadline(sdev->host)) {
spin_unlock_irqrestore(sdev->host->host_lock, flags);
SCSI_LOG_ERROR_RECOVERY(3, SCSI_LOG_ERROR_RECOVERY(3,
scmd_printk(KERN_INFO, scmd, scmd_printk(KERN_INFO, scmd,
"scmd %p eh timeout, not aborting\n", "scmd %p eh timeout, not aborting\n",
scmd)); scmd));
} else { } else {
spin_unlock_irqrestore(sdev->host->host_lock, flags);
SCSI_LOG_ERROR_RECOVERY(3, SCSI_LOG_ERROR_RECOVERY(3,
scmd_printk(KERN_INFO, scmd, scmd_printk(KERN_INFO, scmd,
"aborting command %p\n", scmd)); "aborting command %p\n", scmd));
...@@ -1132,7 +1135,6 @@ int scsi_eh_get_sense(struct list_head *work_q, ...@@ -1132,7 +1135,6 @@ int scsi_eh_get_sense(struct list_head *work_q,
struct scsi_cmnd *scmd, *next; struct scsi_cmnd *scmd, *next;
struct Scsi_Host *shost; struct Scsi_Host *shost;
int rtn; int rtn;
unsigned long flags;
list_for_each_entry_safe(scmd, next, work_q, eh_entry) { list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) || if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) ||
...@@ -1140,16 +1142,13 @@ int scsi_eh_get_sense(struct list_head *work_q, ...@@ -1140,16 +1142,13 @@ int scsi_eh_get_sense(struct list_head *work_q,
continue; continue;
shost = scmd->device->host; shost = scmd->device->host;
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_eh_past_deadline(shost)) { if (scsi_host_eh_past_deadline(shost)) {
spin_unlock_irqrestore(shost->host_lock, flags);
SCSI_LOG_ERROR_RECOVERY(3, SCSI_LOG_ERROR_RECOVERY(3,
shost_printk(KERN_INFO, shost, shost_printk(KERN_INFO, shost,
"skip %s, past eh deadline\n", "skip %s, past eh deadline\n",
__func__)); __func__));
break; break;
} }
spin_unlock_irqrestore(shost->host_lock, flags);
SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd, SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd,
"%s: requesting sense\n", "%s: requesting sense\n",
current->comm)); current->comm));
...@@ -1235,26 +1234,21 @@ static int scsi_eh_test_devices(struct list_head *cmd_list, ...@@ -1235,26 +1234,21 @@ static int scsi_eh_test_devices(struct list_head *cmd_list,
struct scsi_cmnd *scmd, *next; struct scsi_cmnd *scmd, *next;
struct scsi_device *sdev; struct scsi_device *sdev;
int finish_cmds; int finish_cmds;
unsigned long flags;
while (!list_empty(cmd_list)) { while (!list_empty(cmd_list)) {
scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry); scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry);
sdev = scmd->device; sdev = scmd->device;
if (!try_stu) { if (!try_stu) {
spin_lock_irqsave(sdev->host->host_lock, flags);
if (scsi_host_eh_past_deadline(sdev->host)) { if (scsi_host_eh_past_deadline(sdev->host)) {
/* Push items back onto work_q */ /* Push items back onto work_q */
list_splice_init(cmd_list, work_q); list_splice_init(cmd_list, work_q);
spin_unlock_irqrestore(sdev->host->host_lock,
flags);
SCSI_LOG_ERROR_RECOVERY(3, SCSI_LOG_ERROR_RECOVERY(3,
shost_printk(KERN_INFO, sdev->host, shost_printk(KERN_INFO, sdev->host,
"skip %s, past eh deadline", "skip %s, past eh deadline",
__func__)); __func__));
break; break;
} }
spin_unlock_irqrestore(sdev->host->host_lock, flags);
} }
finish_cmds = !scsi_device_online(scmd->device) || finish_cmds = !scsi_device_online(scmd->device) ||
...@@ -1295,15 +1289,12 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, ...@@ -1295,15 +1289,12 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
LIST_HEAD(check_list); LIST_HEAD(check_list);
int rtn; int rtn;
struct Scsi_Host *shost; struct Scsi_Host *shost;
unsigned long flags;
list_for_each_entry_safe(scmd, next, work_q, eh_entry) { list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
if (!(scmd->eh_eflags & SCSI_EH_CANCEL_CMD)) if (!(scmd->eh_eflags & SCSI_EH_CANCEL_CMD))
continue; continue;
shost = scmd->device->host; shost = scmd->device->host;
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_eh_past_deadline(shost)) { if (scsi_host_eh_past_deadline(shost)) {
spin_unlock_irqrestore(shost->host_lock, flags);
list_splice_init(&check_list, work_q); list_splice_init(&check_list, work_q);
SCSI_LOG_ERROR_RECOVERY(3, SCSI_LOG_ERROR_RECOVERY(3,
shost_printk(KERN_INFO, shost, shost_printk(KERN_INFO, shost,
...@@ -1311,7 +1302,6 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, ...@@ -1311,7 +1302,6 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
__func__)); __func__));
return list_empty(work_q); return list_empty(work_q);
} }
spin_unlock_irqrestore(shost->host_lock, flags);
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:" SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:"
"0x%p\n", current->comm, "0x%p\n", current->comm,
scmd)); scmd));
...@@ -1375,19 +1365,15 @@ static int scsi_eh_stu(struct Scsi_Host *shost, ...@@ -1375,19 +1365,15 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
{ {
struct scsi_cmnd *scmd, *stu_scmd, *next; struct scsi_cmnd *scmd, *stu_scmd, *next;
struct scsi_device *sdev; struct scsi_device *sdev;
unsigned long flags;
shost_for_each_device(sdev, shost) { shost_for_each_device(sdev, shost) {
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_eh_past_deadline(shost)) { if (scsi_host_eh_past_deadline(shost)) {
spin_unlock_irqrestore(shost->host_lock, flags);
SCSI_LOG_ERROR_RECOVERY(3, SCSI_LOG_ERROR_RECOVERY(3,
shost_printk(KERN_INFO, shost, shost_printk(KERN_INFO, shost,
"skip %s, past eh deadline\n", "skip %s, past eh deadline\n",
__func__)); __func__));
break; break;
} }
spin_unlock_irqrestore(shost->host_lock, flags);
stu_scmd = NULL; stu_scmd = NULL;
list_for_each_entry(scmd, work_q, eh_entry) list_for_each_entry(scmd, work_q, eh_entry)
if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) && if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) &&
...@@ -1441,20 +1427,16 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, ...@@ -1441,20 +1427,16 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
{ {
struct scsi_cmnd *scmd, *bdr_scmd, *next; struct scsi_cmnd *scmd, *bdr_scmd, *next;
struct scsi_device *sdev; struct scsi_device *sdev;
unsigned long flags;
int rtn; int rtn;
shost_for_each_device(sdev, shost) { shost_for_each_device(sdev, shost) {
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_eh_past_deadline(shost)) { if (scsi_host_eh_past_deadline(shost)) {
spin_unlock_irqrestore(shost->host_lock, flags);
SCSI_LOG_ERROR_RECOVERY(3, SCSI_LOG_ERROR_RECOVERY(3,
shost_printk(KERN_INFO, shost, shost_printk(KERN_INFO, shost,
"skip %s, past eh deadline\n", "skip %s, past eh deadline\n",
__func__)); __func__));
break; break;
} }
spin_unlock_irqrestore(shost->host_lock, flags);
bdr_scmd = NULL; bdr_scmd = NULL;
list_for_each_entry(scmd, work_q, eh_entry) list_for_each_entry(scmd, work_q, eh_entry)
if (scmd->device == sdev) { if (scmd->device == sdev) {
...@@ -1515,11 +1497,8 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, ...@@ -1515,11 +1497,8 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
struct scsi_cmnd *next, *scmd; struct scsi_cmnd *next, *scmd;
int rtn; int rtn;
unsigned int id; unsigned int id;
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_eh_past_deadline(shost)) { if (scsi_host_eh_past_deadline(shost)) {
spin_unlock_irqrestore(shost->host_lock, flags);
/* push back on work queue for further processing */ /* push back on work queue for further processing */
list_splice_init(&check_list, work_q); list_splice_init(&check_list, work_q);
list_splice_init(&tmp_list, work_q); list_splice_init(&tmp_list, work_q);
...@@ -1529,7 +1508,6 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, ...@@ -1529,7 +1508,6 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
__func__)); __func__));
return list_empty(work_q); return list_empty(work_q);
} }
spin_unlock_irqrestore(shost->host_lock, flags);
scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry); scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry);
id = scmd_id(scmd); id = scmd_id(scmd);
...@@ -1574,7 +1552,6 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, ...@@ -1574,7 +1552,6 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
LIST_HEAD(check_list); LIST_HEAD(check_list);
unsigned int channel; unsigned int channel;
int rtn; int rtn;
unsigned long flags;
/* /*
* we really want to loop over the various channels, and do this on * we really want to loop over the various channels, and do this on
...@@ -1584,9 +1561,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, ...@@ -1584,9 +1561,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
*/ */
for (channel = 0; channel <= shost->max_channel; channel++) { for (channel = 0; channel <= shost->max_channel; channel++) {
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_eh_past_deadline(shost)) { if (scsi_host_eh_past_deadline(shost)) {
spin_unlock_irqrestore(shost->host_lock, flags);
list_splice_init(&check_list, work_q); list_splice_init(&check_list, work_q);
SCSI_LOG_ERROR_RECOVERY(3, SCSI_LOG_ERROR_RECOVERY(3,
shost_printk(KERN_INFO, shost, shost_printk(KERN_INFO, shost,
...@@ -1594,7 +1569,6 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, ...@@ -1594,7 +1569,6 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
__func__)); __func__));
return list_empty(work_q); return list_empty(work_q);
} }
spin_unlock_irqrestore(shost->host_lock, flags);
chan_scmd = NULL; chan_scmd = NULL;
list_for_each_entry(scmd, work_q, eh_entry) { list_for_each_entry(scmd, work_q, eh_entry) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment