From 366a99f78102e8346829abf726129116627372f6 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 11 Mar 2008 14:27:13 +0000 Subject: [PATCH] Protect initiators list using tmds_lock. Avoid possibility to allocate initiator twice. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@300 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla_isp/linux/isp_scst.c | 79 ++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/qla_isp/linux/isp_scst.c b/qla_isp/linux/isp_scst.c index b3aa59902..39d24004d 100644 --- a/qla_isp/linux/isp_scst.c +++ b/qla_isp/linux/isp_scst.c @@ -471,11 +471,11 @@ scsi_target_start_cmd(tmd_cmd_t *tmd, int from_intr) spin_unlock_irqrestore(&scsi_target_lock, flags); tmd->cd_bus = bp; - tmd->cd_ini = ini_from_tmd(bp, tmd); tmd->cd_hnext = NULL; /* then, add commands to queue */ spin_lock_irqsave(&bp->tmds_lock, flags); + tmd->cd_ini = ini_from_tmd(bp, tmd); if (bp->tmds_front == NULL) { bp->tmds_front = tmd; } else { @@ -519,35 +519,47 @@ add_initiators(void) spin_lock_irq(&bp->tmds_lock); tmd = bp->tmds_front; while (tmd) { - spin_unlock_irq(&bp->tmds_lock); - if (tmd->cd_ini == NULL) { - ini = alloc_ini(bp, tmd->cd_iid); + if (tmd->cd_ini != NULL) { + /* ini assigned, go to the next command */ + prev_tmd = tmd; + tmd = tmd->cd_hnext; + } else { + /* check if proper initiator exist already */ + ini = ini_from_tmd(bp, tmd); if (ini != NULL) { - tmd->cd_ini = ini; - add_ini(bp, tmd->cd_iid, ini); - } - } - spin_lock_irq(&bp->tmds_lock); - if (tmd->cd_ini == NULL) { - /* fail to alloc initiator, remove from queue and send busy */ - if (prev_tmd == NULL) { - bp->tmds_front = tmd->cd_hnext; - } else { - prev_tmd->cd_hnext = tmd->cd_hnext; - } - if (bp->tmds_tail == tmd) { - bp->tmds_tail = prev_tmd; - } - // FIXME: spin unlock/lock - tmd->cd_scsi_status = SCSI_BUSY; - xact = &tmd->cd_xact; - xact->td_hflags |= TDFH_STSVALID; - xact->td_hflags &= ~TDFH_DATA_MASK; - xact->td_xfrlen = 0; - (*bp->h.r_action)(QIN_TMD_CONT, xact); - } - prev_tmd = tmd; - tmd = tmd->cd_hnext; + tmd->cd_ini = ini; + } else { + spin_unlock_irq(&bp->tmds_lock); + + ini = alloc_ini(bp, tmd->cd_iid); + + spin_lock_irq(&bp->tmds_lock); + if (ini != NULL) { + tmd->cd_ini = ini; + add_ini(bp, tmd->cd_iid, ini); + } else { + /* fail to alloc initiator, remove from queue and send busy */ + if (prev_tmd == NULL) { + bp->tmds_front = tmd->cd_hnext; + } else { + prev_tmd->cd_hnext = tmd->cd_hnext; + } + if (bp->tmds_tail == tmd) { + bp->tmds_tail = prev_tmd; + } + // FIXME: spin unlock/lock ? + tmd->cd_scsi_status = SCSI_BUSY; + xact = &tmd->cd_xact; + xact->td_hflags |= TDFH_STSVALID; + xact->td_hflags &= ~TDFH_DATA_MASK; + xact->td_xfrlen = 0; + (*bp->h.r_action)(QIN_TMD_CONT, xact); + + /* iterate to the next command, previous is not changed */ + tmd = tmd->cd_hnext; + } + } + } } spin_unlock_irq(&bp->tmds_lock); } @@ -666,10 +678,13 @@ scsi_target_notify(tmd_notify_t *np) Eprintk("TMD_NOTIFY cannot find bus\n"); return; } - ini = ini_from_notify(bp, np); spin_unlock_irqrestore(&scsi_target_lock, flags); SDprintk("scsi_target: MGT code %x from %s%d iid 0x%016llx\n", np->nt_ncode, bp->h.r_name, bp->h.r_inst, np->nt_iid); + spin_lock_irqsave(&bp->tmds_lock, flags); + ini = ini_from_notify(bp, np); + spin_unlock_irqrestore(&bp->tmds_lock, flags); + switch (np->nt_ncode) { case NT_ABORT_TASK: if (abort_task(bp, np->nt_tagval)) { @@ -863,8 +878,8 @@ scsi_target_thread(void *arg) register_scst(); } if (test_and_clear_bit(SF_ADD_INITIATORS, &schedule_flags)) { - add_initiators(); - } + add_initiators(); + } if (test_and_clear_bit(SF_UNREGISTER_SCST, &schedule_flags)) { unregister_scst(); }