From cc76f881c233d4dc44edff2657052ddcb7afd69d Mon Sep 17 00:00:00 2001 From: vlnb Date: Tue, 3 Nov 2009 18:44:09 +0000 Subject: [PATCH] Fixes possible crash, caused by q2t_sess_work_fn() called on several CPUs at time. Reported by Gal Rosen git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1314 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t/qla2x00-target/qla2x00t.c | 19 +++++++++++-------- qla2x00t/qla2x00-target/qla2x00t.h | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index 3c80ac8..3bddddf 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -3173,9 +3173,10 @@ out_sched: prm->cmd = cmd; spin_lock_irqsave(&tgt->sess_work_lock, flags); - if (list_empty(&tgt->sess_works_list)) + if (!tgt->sess_works_pending) tgt->tm_to_unknown = 0; list_add_tail(&prm->sess_works_list_entry, &tgt->sess_works_list); + tgt->sess_works_pending = 1; spin_unlock_irqrestore(&tgt->sess_work_lock, flags); schedule_work(&tgt->sess_work); @@ -4855,18 +4856,18 @@ static void q2t_sess_work_fn(struct work_struct *work) tgt->sess_works_list.next, typeof(*prm), sess_works_list_entry); + /* + * This work can be scheduled on several CPUs at time, so we + * must delete the entry to eliminate double processing + */ + list_del(&prm->sess_works_list_entry); + spin_unlock_irq(&tgt->sess_work_lock); rc = q2t_exec_sess_work(tgt, prm); spin_lock_irq(&tgt->sess_work_lock); - /* - * Prm must be in the list on the exec time to sync with - * tm_to_unknown clearance - */ - list_del(&prm->sess_works_list_entry); - if (rc != 0) { PRINT_CRIT_ERROR("%s", "Unable to complete sess work"); q2t_free_cmd(prm->cmd); @@ -4878,8 +4879,10 @@ static void q2t_sess_work_fn(struct work_struct *work) spin_lock_irq(&tgt->ha->hardware_lock); spin_lock(&tgt->sess_work_lock); - if (list_empty(&tgt->sess_works_list)) + if (list_empty(&tgt->sess_works_list)) { + tgt->sess_works_pending = 0; tgt->tm_to_unknown = 0; + } spin_unlock(&tgt->sess_work_lock); spin_unlock_irq(&tgt->ha->hardware_lock); diff --git a/qla2x00t/qla2x00-target/qla2x00t.h b/qla2x00t/qla2x00-target/qla2x00t.h index 0fc79a6..4ed229d 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.h +++ b/qla2x00t/qla2x00-target/qla2x00t.h @@ -129,6 +129,7 @@ struct q2t_tgt { unsigned int tgt_enable_64bit_addr:1; /* 64-bits PCI addressing enabled */ unsigned int link_reinit_iocb_pending:1; unsigned int tm_to_unknown:1; /* TM to unknown session was sent */ + unsigned int sess_works_pending:1; /* there are sess_work entries */ /* * Protected by tgt_mutex AND hardware_lock for writing and tgt_mutex -- 2.17.1