From c1de6b432cc0b36d10c0808eb66a341a3d7d482a Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 14 Aug 2008 21:34:05 -0500 Subject: [PATCH 12/23] libfc: make sure we cleanup the ep in fc_exch_reset If it is a non fcp command then fc_exch.c needs to cleanup the command, so this patch does a fc_exch_done_locked and fc_exch_mgr_delete_ep. I also removed the ESB_ST_COMPLETE clearing because it is not needed. And I removed the resp = NULL, because we should not have a command completed here. This can actaully occur due to a race or due to an abort timing out. If the abort was initaited from fc_exch.c we are actaully doing the wrong thing and the upper layer will leak the command. If the abort was initiated from scsi-ml then we are doing the wrong thing but we were doing the right thing before and I broke that with the abort patches. These issues will be fixed in the next patches, and in the end we should call the resp if there is one. Signed-off-by: Mike Christie --- drivers/scsi/libfc/fc_exch.c | 18 ++++++++++++++---- 1 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 2729f0d..0378e58 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1432,22 +1432,32 @@ static void fc_exch_reset(struct fc_exch *ep) struct fc_seq *sp; void (*resp)(struct fc_seq *, struct fc_frame *, void *); void *arg; + int rc = 1; + /* + * TODO: we should use del_timer_sync. If this is called for + * shutdown, and the driver will unload after this exits, we + * must not have any timers running. I do not think we can + * call del_timer_sync here though, because it looks like it + * is called with a port spin lock held. + */ spin_lock_bh(&ep->ex_lock); resp = ep->resp; ep->resp = NULL; if (ep->esb_stat & ESB_ST_REC_QUAL) atomic_dec(&ep->ex_refcnt); /* drop hold for rec_qual */ ep->esb_stat &= ~ESB_ST_REC_QUAL; - if (ep->esb_stat & ESB_ST_COMPLETE) - resp = NULL; arg = ep->resp_arg; if (del_timer(&ep->ex_timer)) atomic_dec(&ep->ex_refcnt); /* drop hold for timer */ - sp = &ep->seq; - ep->esb_stat |= ESB_ST_COMPLETE; + + if (ep->fh_type != FC_TYPE_FCP) + rc = fc_exch_done_locked(ep); spin_unlock_bh(&ep->ex_lock); + if (!rc) + fc_exch_mgr_delete_ep(ep); + if (resp) resp(sp, ERR_PTR(-FC_EX_CLOSED), arg); } -- 1.5.5.1