Skip to content

Commit

Permalink
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/jejb/scsi

Pull SCSI fixes from James Bottomley:
 "Two straightforward fixes.

  One is a concurrency issue only affecting SAS connected SATA drives,
  but which could hang the storage subsystem if it triggers (because the
  outstanding command count on error never goes back to zero) and the
  other is a NO_TAG fallout from the switch to hostwide tags which
  causes the system to crash on module insertion (we've checked
  carefully and only the 53c700 family of drivers is vulnerable to this
  issue)"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  53c700: fix BUG on untagged commands
  scsi: fix race between simultaneous decrements of ->host_failed
  • Loading branch information
Linus Torvalds committed Jun 26, 2016
2 parents da2f6ab + 951d77f commit 2ac9b97
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 6 deletions.
8 changes: 6 additions & 2 deletions Documentation/scsi/scsi_eh.txt
Original file line number Diff line number Diff line change
Expand Up @@ -263,19 +263,23 @@ scmd->allowed.

3. scmd recovered
ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd
- shost->host_failed--
- clear scmd->eh_eflags
- scsi_setup_cmd_retry()
- move from local eh_work_q to local eh_done_q
LOCKING: none
CONCURRENCY: at most one thread per separate eh_work_q to
keep queue manipulation lockless

4. EH completes
ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper
layer of failure.
layer of failure. May be called concurrently but must have
a no more than one thread per separate eh_work_q to
manipulate the queue locklessly
- scmd is removed from eh_done_q and scmd->eh_entry is cleared
- if retry is necessary, scmd is requeued using
scsi_queue_insert()
- otherwise, scsi_finish_command() is invoked for scmd
- zero shost->host_failed
LOCKING: queue or finish function performs appropriate locking


Expand Down
2 changes: 1 addition & 1 deletion drivers/ata/libata-eh.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ void ata_scsi_error(struct Scsi_Host *host)
ata_scsi_port_error_handler(host, ap);

/* finish or retry handled scmd's and clean up */
WARN_ON(host->host_failed || !list_empty(&eh_work_q));
WARN_ON(!list_empty(&eh_work_q));

DPRINTK("EXIT\n");
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/scsi/53c700.c
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
} else {
struct scsi_cmnd *SCp;

SCp = scsi_host_find_tag(SDp->host, SCSI_NO_TAG);
SCp = SDp->current_cmnd;
if(unlikely(SCp == NULL)) {
sdev_printk(KERN_ERR, SDp,
"no saved request for untagged cmd\n");
Expand Down Expand Up @@ -1826,7 +1826,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
slot->tag, slot);
} else {
slot->tag = SCSI_NO_TAG;
/* must populate current_cmnd for scsi_host_find_tag to work */
/* save current command for reselection */
SCp->device->current_cmnd = SCp;
}
/* sanity check: some of the commands generated by the mid-layer
Expand Down
4 changes: 3 additions & 1 deletion drivers/scsi/scsi_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,6 @@ static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn)
*/
void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
{
scmd->device->host->host_failed--;
scmd->eh_eflags = 0;
list_move_tail(&scmd->eh_entry, done_q);
}
Expand Down Expand Up @@ -2227,6 +2226,9 @@ int scsi_error_handler(void *data)
else
scsi_unjam_host(shost);

/* All scmds have been handled */
shost->host_failed = 0;

/*
* Note - if the above fails completely, the action is to take
* individual devices offline and flush the queue of any
Expand Down

0 comments on commit 2ac9b97

Please sign in to comment.