[PATCH 3/3] qla2xxx: Make qla_tgt_stop_phase1 shutdown use tgt->sess_del_work

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>

This patch converts qla_tgt_stop_phase1() to queue up qla_tgt_sess deletion
for session shutdown operation using a parameter to signal immediate
schedule_delayed_work() execution in qla_tgt_schedule_sess_for_deletion(),
instead of the original final call to release qla_tgt_sess_put().

It also changes qla_tgt_stop_phase1() to call qla_tgt_clear_tgt_db() while
setting qla_tgt->tgt_stop during the first ->hardware_lock access, that
now uses flush_delayed_work_sync(&tgt->sess_del_work) ahead of waiting for
the last session to be released in qla_tgt_stop_phase1() calling context.

Cc: Christoph Hellwig <hch@xxxxxx>
Cc: Roland Dreier <roland@xxxxxxxxxxxxxxx>
Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
---
 drivers/scsi/qla2xxx/qla_target.c |   49 ++++++++++++-------------------------
 1 files changed, 16 insertions(+), 33 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 1f70fd0..c6b3771 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -106,9 +106,6 @@ static void qla_tgt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_
 	atio_from_isp_t *atio, int ha_locked);
 static void qla_tgt_reject_free_srr_imm(struct scsi_qla_host *ha, struct qla_tgt_srr_imm *imm,
 	int ha_lock);
-static int qla_tgt_set_data_offset(struct qla_tgt_cmd *cmd, uint32_t offset);
-static void qla_tgt_clear_tgt_db(struct qla_tgt *tgt, bool local_only);
-static int qla_tgt_unreg_sess(struct qla_tgt_sess *sess);
 /*
  * Global Variables
  */
@@ -513,38 +510,37 @@ static int qla_tgt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
 }
 
 /* ha->hardware_lock supposed to be held on entry */
-static void qla_tgt_schedule_sess_for_deletion(struct qla_tgt_sess *sess)
+static void qla_tgt_schedule_sess_for_deletion(struct qla_tgt_sess *sess, bool immediate)
 {
 	struct qla_tgt *tgt = sess->tgt;
 	uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5;
-	bool schedule;
 
 	if (sess->deleted)
 		return;
-	/*
-	 * If the list is empty, then, most likely, the work isn't
-	 * scheduled.
-	 */
-	schedule = list_empty(&tgt->del_sess_list);
 
 	ql_dbg(ql_dbg_tgt, sess->vha, 0xe004, "Scheduling sess %p for"
 		" deletion (schedule %d)", sess, schedule);
 	list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
 	sess->deleted = 1;
+
+	if (immediate)
+		dev_loss_tmo = 0;
+
 	sess->expires = jiffies + dev_loss_tmo * HZ;
 
 	printk(KERN_INFO "qla_target(%d): session for port %02x:%02x:%02x:"
 		"%02x:%02x:%02x:%02x:%02x (loop ID %d) scheduled for "
-		"deletion in %d secs\n", sess->vha->vp_idx,
+		"deletion in %u secs (expires: %lu) immed: %d\n", sess->vha->vp_idx,
 		sess->port_name[0], sess->port_name[1],
 		sess->port_name[2], sess->port_name[3],
 		sess->port_name[4], sess->port_name[5],
 		sess->port_name[6], sess->port_name[7],
-		sess->loop_id, dev_loss_tmo);
+		sess->loop_id, dev_loss_tmo, sess->expires, immediate);
 
-	if (schedule)
-		schedule_delayed_work(&tgt->sess_del_work,
-				jiffies - sess->expires);
+	if (immediate)
+		schedule_delayed_work(&tgt->sess_del_work, 0);
+	else
+		schedule_delayed_work(&tgt->sess_del_work, jiffies - sess->expires);
 }
 
 /* ha->hardware_lock supposed to be held on entry */
@@ -552,16 +548,8 @@ static void qla_tgt_clear_tgt_db(struct qla_tgt *tgt, bool local_only)
 {
 	struct qla_tgt_sess *sess;
 
-	while (!list_empty(&tgt->sess_list)) {
-		sess = list_first_entry(&tgt->sess_list, struct qla_tgt_sess,
-					sess_list_entry);
-		if (local_only) {
-			if (!sess->local)
-				continue;
-			qla_tgt_schedule_sess_for_deletion(sess);
-		} else
-			qla_tgt_sess_put(sess);
-	}
+	list_for_each_entry(sess, &tgt->sess_list, sess_list_entry)
+		qla_tgt_schedule_sess_for_deletion(sess, true);
 
 	/* At this point tgt could be already dead */
 }
@@ -1008,7 +996,7 @@ void qla_tgt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
 	ql_dbg(ql_dbg_tgt_mgt, vha, 0xe10b, "qla_tgt_fc_port_deleted %p", sess);
 
 	sess->local = 1;
-	qla_tgt_schedule_sess_for_deletion(sess);
+	qla_tgt_schedule_sess_for_deletion(sess, false);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 }
 
@@ -1052,10 +1040,11 @@ void qla_tgt_stop_phase1(struct qla_tgt *tgt)
 	mutex_lock(&ha->tgt_mutex);
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	tgt->tgt_stop = 1;
+	qla_tgt_clear_tgt_db(tgt, true);
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 	mutex_unlock(&ha->tgt_mutex);
 
-	cancel_delayed_work_sync(&tgt->sess_del_work);
+	flush_delayed_work_sync(&tgt->sess_del_work);
 
 	ql_dbg(ql_dbg_tgt_mgt, vha, 0xe10c, "Waiting for sess works (tgt %p)", tgt);
 	spin_lock_irqsave(&tgt->sess_work_lock, flags);
@@ -1066,12 +1055,6 @@ void qla_tgt_stop_phase1(struct qla_tgt *tgt)
 	}
 	spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
 
-	mutex_lock(&ha->tgt_mutex);
-	spin_lock_irqsave(&ha->hardware_lock, flags);
-	qla_tgt_clear_tgt_db(tgt, false);
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-	mutex_unlock(&ha->tgt_mutex);
-
 	ql_dbg(ql_dbg_tgt_mgt, vha, 0xe10d, "Waiting for tgt %p: list_empty(sess_list)=%d "
 		"sess_count=%d\n", tgt, list_empty(&tgt->sess_list),
 		tgt->sess_count);
-- 
1.7.2.5

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux