Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ac9b973 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents da2f6aba 951d77fd
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -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


+1 −1
Original line number Diff line number Diff line
@@ -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");
}
+2 −2
Original line number Diff line number Diff line
@@ -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");
@@ -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
+3 −1
Original line number Diff line number Diff line
@@ -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);
}
@@ -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