aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorVasu Dev <vasu.dev@intel.com>2010-10-08 20:12:31 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-10-25 16:11:35 -0400
commit8b7ac2bb07bbadb0636f21f51564e6d363bb6d20 (patch)
tree788c08b32a719f6c473482e7897ec5835dd9e03e /drivers/scsi
parent3067817a5d3ef99c5b1a4e4ca8c5b15bc7fc468d (diff)
[SCSI] libfc: possible race could panic system due to NULL fsp->cmd
It is unlikely but in case if it hits then it would cause panic due to null cmd ptr, so far only one instance seen recently with ESX though this was introduced long ago with this commit:- commit c1ecb90a66c5afc7cc5c9349f9c3714eef4a5cfb Author: Chris Leech <christopher.leech@intel.com> Date: Thu Dec 10 09:59:26 2009 -0800 [SCSI] libfc: reduce hold time on SCSI host lock Currently fsp->cmd is set to NULL w/o scsi_queue_lock before dequeuing from scsi_pkt_queue and that could cause NULL fsp->cmd in fc_fcp_cleanup_each_cmd for cmd completing with fsp->cmd = NULL after fc_fcp_cleanup_each_cmd taken reference. No need to set fsp->cmd to NULL as this is also protected by fc_fcp_lock_pkt(), for above race the fc_fcp_lock_pkt() in fc_fcp_cleanup_each_cmd() will fail as that cmd is already done. Mike mentioned same issue at http://www.open-fcoe.org/pipermail/devel/2010-September/010533.html Similarly moved sc_cmd->SCp.ptr = NULL under scsi_queue_lock so that scsi abort error handler won't abort on completed cmds. Signed-off-by: Vasu Dev <vasu.dev@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libfc/fc_fcp.c18
1 files changed, 6 insertions, 12 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 43866e6d0bf2..e340373b509b 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -58,8 +58,7 @@ struct kmem_cache *scsi_pkt_cachep;
58#define FC_SRB_WRITE (1 << 0) 58#define FC_SRB_WRITE (1 << 0)
59 59
60/* 60/*
61 * The SCp.ptr should be tested and set under the host lock. NULL indicates 61 * The SCp.ptr should be tested and set under the scsi_pkt_queue lock
62 * that the command has been retruned to the scsi layer.
63 */ 62 */
64#define CMD_SP(Cmnd) ((struct fc_fcp_pkt *)(Cmnd)->SCp.ptr) 63#define CMD_SP(Cmnd) ((struct fc_fcp_pkt *)(Cmnd)->SCp.ptr)
65#define CMD_ENTRY_STATUS(Cmnd) ((Cmnd)->SCp.have_data_in) 64#define CMD_ENTRY_STATUS(Cmnd) ((Cmnd)->SCp.have_data_in)
@@ -1880,8 +1879,6 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
1880 1879
1881 lport = fsp->lp; 1880 lport = fsp->lp;
1882 si = fc_get_scsi_internal(lport); 1881 si = fc_get_scsi_internal(lport);
1883 if (!fsp->cmd)
1884 return;
1885 1882
1886 /* 1883 /*
1887 * if can_queue ramp down is done then try can_queue ramp up 1884 * if can_queue ramp down is done then try can_queue ramp up
@@ -1891,11 +1888,6 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
1891 fc_fcp_can_queue_ramp_up(lport); 1888 fc_fcp_can_queue_ramp_up(lport);
1892 1889
1893 sc_cmd = fsp->cmd; 1890 sc_cmd = fsp->cmd;
1894 fsp->cmd = NULL;
1895
1896 if (!sc_cmd->SCp.ptr)
1897 return;
1898
1899 CMD_SCSI_STATUS(sc_cmd) = fsp->cdb_status; 1891 CMD_SCSI_STATUS(sc_cmd) = fsp->cdb_status;
1900 switch (fsp->status_code) { 1892 switch (fsp->status_code) {
1901 case FC_COMPLETE: 1893 case FC_COMPLETE:
@@ -1976,8 +1968,8 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
1976 1968
1977 spin_lock_irqsave(&si->scsi_queue_lock, flags); 1969 spin_lock_irqsave(&si->scsi_queue_lock, flags);
1978 list_del(&fsp->list); 1970 list_del(&fsp->list);
1979 spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
1980 sc_cmd->SCp.ptr = NULL; 1971 sc_cmd->SCp.ptr = NULL;
1972 spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
1981 sc_cmd->scsi_done(sc_cmd); 1973 sc_cmd->scsi_done(sc_cmd);
1982 1974
1983 /* release ref from initial allocation in queue command */ 1975 /* release ref from initial allocation in queue command */
@@ -1995,6 +1987,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd)
1995{ 1987{
1996 struct fc_fcp_pkt *fsp; 1988 struct fc_fcp_pkt *fsp;
1997 struct fc_lport *lport; 1989 struct fc_lport *lport;
1990 struct fc_fcp_internal *si;
1998 int rc = FAILED; 1991 int rc = FAILED;
1999 unsigned long flags; 1992 unsigned long flags;
2000 1993
@@ -2004,7 +1997,8 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd)
2004 else if (!lport->link_up) 1997 else if (!lport->link_up)
2005 return rc; 1998 return rc;
2006 1999
2007 spin_lock_irqsave(lport->host->host_lock, flags); 2000 si = fc_get_scsi_internal(lport);
2001 spin_lock_irqsave(&si->scsi_queue_lock, flags);
2008 fsp = CMD_SP(sc_cmd); 2002 fsp = CMD_SP(sc_cmd);
2009 if (!fsp) { 2003 if (!fsp) {
2010 /* command completed while scsi eh was setting up */ 2004 /* command completed while scsi eh was setting up */
@@ -2013,7 +2007,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd)
2013 } 2007 }
2014 /* grab a ref so the fsp and sc_cmd cannot be relased from under us */ 2008 /* grab a ref so the fsp and sc_cmd cannot be relased from under us */
2015 fc_fcp_pkt_hold(fsp); 2009 fc_fcp_pkt_hold(fsp);
2016 spin_unlock_irqrestore(lport->host->host_lock, flags); 2010 spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
2017 2011
2018 if (fc_fcp_lock_pkt(fsp)) { 2012 if (fc_fcp_lock_pkt(fsp)) {
2019 /* completed while we were waiting for timer to be deleted */ 2013 /* completed while we were waiting for timer to be deleted */