From: Mike Christie <michael.christie@oracle.com>
To: lduncan@suse.com, cleech@redhat.com, njavali@marvell.com,
mrangankar@marvell.com, GR-QLogic-Storage-Upstream@marvell.com,
varun@chelsio.com, martin.petersen@oracle.com,
linux-scsi@vger.kernel.org, jejb@linux.ibm.com
Subject: [PATCH 15/22] libiscsi: use scsi_host_busy_iter
Date: Thu, 17 Dec 2020 00:42:05 -0600 [thread overview]
Message-ID: <1608187332-4434-16-git-send-email-michael.christie@oracle.com> (raw)
In-Reply-To: <1608187332-4434-1-git-send-email-michael.christie@oracle.com>
The next patches remove the session->cmds array for the scsi_cmnd
iscsi tasks. This patch has us use scsi_host_busy_iter instead of
looping over that array for the scsi_cmnd case, so we can remove
it in the next patches when we also switch over to using the blk
layer cmd allocators.
Signed-off-by: Mike Christie <michael.christie@oracle.com>
---
drivers/scsi/libiscsi.c | 160 +++++++++++++++++++++++++++++-------------------
include/scsi/libiscsi.h | 12 ++++
2 files changed, 110 insertions(+), 62 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 0c9e220..2b3dd42 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1902,39 +1902,66 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
return 0;
}
-/*
- * Fail commands. session frwd lock held and xmit thread flushed.
- */
-static void fail_scsi_tasks(struct iscsi_conn *conn, u64 lun, int error)
+static bool fail_scsi_task_iter(struct scsi_cmnd *sc, void *data, bool rsvd)
{
+ struct iscsi_task *task = (struct iscsi_task *)sc->SCp.ptr;
+ struct iscsi_sc_iter_data *iter_data = data;
+ struct iscsi_conn *conn = iter_data->conn;
struct iscsi_session *session = conn->session;
- struct iscsi_task *task;
- int i;
+
+ ISCSI_DBG_SESSION(session, "failing sc %p itt 0x%x state %d\n",
+ task->sc, task->itt, task->state);
+ __iscsi_get_task(task);
+ spin_unlock_bh(&session->back_lock);
+
+ fail_scsi_task(task, *(int *)iter_data->data);
+
+ spin_unlock_bh(&session->frwd_lock);
+ iscsi_put_task(task);
+ spin_lock_bh(&session->frwd_lock);
spin_lock_bh(&session->back_lock);
- for (i = 0; i < session->cmds_max; i++) {
- task = session->cmds[i];
- if (!task->sc || task->state == ISCSI_TASK_FREE)
- continue;
+ return true;
+}
- if (lun != -1 && lun != task->sc->device->lun)
- continue;
+static bool iscsi_sc_iter(struct scsi_cmnd *sc, void *data, bool rsvd)
+{
+ struct iscsi_task *task = (struct iscsi_task *)sc->SCp.ptr;
+ struct iscsi_sc_iter_data *iter_data = data;
- __iscsi_get_task(task);
- spin_unlock_bh(&session->back_lock);
+ if (!task->sc || task->state == ISCSI_TASK_FREE ||
+ task->conn != iter_data->conn)
+ return true;
- ISCSI_DBG_SESSION(session,
- "failing sc %p itt 0x%x state %d\n",
- task->sc, task->itt, task->state);
- fail_scsi_task(task, error);
+ if (iter_data->lun != -1 && iter_data->lun != task->sc->device->lun)
+ return true;
- spin_unlock_bh(&session->frwd_lock);
- iscsi_put_task(task);
- spin_lock_bh(&session->frwd_lock);
+ return iter_data->fn(sc, iter_data, rsvd);
+}
- spin_lock_bh(&session->back_lock);
- }
+void iscsi_conn_for_each_sc(struct Scsi_Host *shost,
+ struct iscsi_sc_iter_data *iter_data)
+{
+ scsi_host_busy_iter(shost, iscsi_sc_iter, iter_data);
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_for_each_sc);
+
+/*
+ * Fail commands. session frwd lock held and xmit thread flushed.
+ */
+static void fail_scsi_tasks(struct iscsi_conn *conn, u64 lun, int error)
+{
+ struct iscsi_session *session = conn->session;
+
+ struct iscsi_sc_iter_data iter_data = {
+ .conn = conn,
+ .lun = lun,
+ .fn = fail_scsi_task_iter,
+ .data = &error,
+ };
+ spin_lock_bh(&session->back_lock);
+ iscsi_conn_for_each_sc(session->host, &iter_data);
spin_unlock_bh(&session->back_lock);
}
@@ -1998,14 +2025,49 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
return 0;
}
+static bool check_scsi_task_iter(struct scsi_cmnd *sc, void *data, bool rsvd)
+{
+ struct iscsi_task *task = (struct iscsi_task *)sc->SCp.ptr;
+ struct iscsi_sc_iter_data *iter_data = data;
+ struct iscsi_task *timed_out_task = iter_data->data;
+
+ /*
+ * Only check if cmds started before this one have made
+ * progress, or this could never fail
+ */
+ if (time_after(task->sc->jiffies_at_alloc,
+ timed_out_task->sc->jiffies_at_alloc))
+ return true;
+
+ if (time_after(task->last_xfer, timed_out_task->last_timeout)) {
+ /*
+ * The timed out task has not made progress, but a task
+ * started before us has transferred data since we
+ * started/last-checked. We could be queueing too many tasks
+ * or the LU is bad.
+ *
+ * If the device is bad the cmds ahead of us on other devs will
+ * complete, and this loop will eventually fail starting the
+ * scsi eh.
+ */
+ ISCSI_DBG_EH(task->conn->session,
+ "Command has not made progress but commands ahead of it have. Asking scsi-ml for more time to complete. Our last xfer vs running task last xfer %lu/%lu. Last check %lu.\n",
+ timed_out_task->last_xfer, task->last_xfer,
+ timed_out_task->last_timeout);
+ iter_data->rc = BLK_EH_RESET_TIMER;
+ return false;
+ }
+ return true;
+}
+
enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
{
enum blk_eh_timer_return rc = BLK_EH_DONE;
- struct iscsi_task *task = NULL, *running_task;
+ struct iscsi_task *task;
struct iscsi_cls_session *cls_session;
+ struct iscsi_sc_iter_data iter_data;
struct iscsi_session *session;
struct iscsi_conn *conn;
- int i;
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;
@@ -2084,45 +2146,19 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
goto done;
}
- spin_lock(&session->back_lock);
- for (i = 0; i < conn->session->cmds_max; i++) {
- running_task = conn->session->cmds[i];
- if (!running_task->sc || running_task == task ||
- running_task->state != ISCSI_TASK_RUNNING)
- continue;
-
- /*
- * Only check if cmds started before this one have made
- * progress, or this could never fail
- */
- if (time_after(running_task->sc->jiffies_at_alloc,
- task->sc->jiffies_at_alloc))
- continue;
+ iter_data.conn = conn;
+ iter_data.data = task;
+ iter_data.rc = BLK_EH_DONE;
+ iter_data.fn = check_scsi_task_iter;
+ iter_data.lun = -1;
- if (time_after(running_task->last_xfer, task->last_timeout)) {
- /*
- * This task has not made progress, but a task
- * started before us has transferred data since
- * we started/last-checked. We could be queueing
- * too many tasks or the LU is bad.
- *
- * If the device is bad the cmds ahead of us on
- * other devs will complete, and this loop will
- * eventually fail starting the scsi eh.
- */
- ISCSI_DBG_EH(session, "Command has not made progress "
- "but commands ahead of it have. "
- "Asking scsi-ml for more time to "
- "complete. Our last xfer vs running task "
- "last xfer %lu/%lu. Last check %lu.\n",
- task->last_xfer, running_task->last_xfer,
- task->last_timeout);
- spin_unlock(&session->back_lock);
- rc = BLK_EH_RESET_TIMER;
- goto done;
- }
- }
+ spin_lock(&session->back_lock);
+ iscsi_conn_for_each_sc(conn->session->host, &iter_data);
spin_unlock(&session->back_lock);
+ if (iter_data.rc != BLK_EH_DONE) {
+ rc = iter_data.rc;
+ goto done;
+ }
/* Assumes nop timeout is shorter than scsi cmd timeout */
if (task->have_checked_conn)
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 4f6ca2d..96aaf4b 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -460,6 +460,18 @@ extern void iscsi_complete_scsi_task(struct iscsi_task *task,
uint32_t exp_cmdsn, uint32_t max_cmdsn);
extern int iscsi_init_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd);
+struct iscsi_sc_iter_data {
+ struct iscsi_conn *conn;
+ /* optional: if set to -1. It will be ignored */
+ u64 lun;
+ void *data;
+ int rc;
+ bool (*fn)(struct scsi_cmnd *sc, void *data, bool rsvd);
+};
+
+extern void iscsi_conn_for_each_sc(struct Scsi_Host *shost,
+ struct iscsi_sc_iter_data *iter_data);
+
/*
* generic helpers
*/
--
1.8.3.1
next prev parent reply other threads:[~2020-12-17 6:43 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-17 6:41 [RFC PATCH 00/22 V3] iscsi: lock clean ups Mike Christie
2020-12-17 6:41 ` [PATCH 01/22] libiscsi: fix iscsi_prep_scsi_cmd_pdu error handling Mike Christie
2020-12-17 6:41 ` [PATCH 02/22] libiscsi: drop taskqueuelock Mike Christie
2020-12-17 6:41 ` [PATCH 03/22] libiscsi: fix iscsi_task use after free Mike Christie
2020-12-17 6:41 ` [PATCH 04/22] qla4xxx: use iscsi_is_session_online Mike Christie
2020-12-17 6:41 ` [PATCH 05/22] iscsi class: drop session lock in iscsi_session_chkready Mike Christie
2020-12-17 6:41 ` [PATCH 06/22] libiscsi: remove queued_cmdsn Mike Christie
2020-12-17 6:41 ` [PATCH 07/22] libiscsi: drop frwd lock for session state Mike Christie
2020-12-17 6:41 ` [PATCH 08/22] libiscsi: add task prealloc/free callouts Mike Christie
2020-12-17 6:41 ` [PATCH 09/22] qedi: implement alloc_task_priv/free_task_priv Mike Christie
2020-12-17 6:42 ` [PATCH 10/22] bnx2i: " Mike Christie
2020-12-17 6:42 ` [PATCH 11/22] iser, be2iscsi, qla4xxx: set scsi_host_template cmd_size Mike Christie
2020-12-17 6:42 ` [PATCH 12/22] bnx2i: " Mike Christie
2020-12-17 6:42 ` [PATCH 13/22] qedi: " Mike Christie
2020-12-17 6:42 ` [PATCH 14/22] iscsi_tcp, libcxgbi: " Mike Christie
2020-12-17 6:42 ` Mike Christie [this message]
2020-12-17 6:42 ` [PATCH 16/22] be2iscsi: use scsi_host_busy_iter Mike Christie
2020-12-17 6:42 ` [PATCH 17/22] bnx2i: prep driver for switch to blk tags Mike Christie
2020-12-17 6:42 ` [PATCH 18/22] qedi: " Mike Christie
2020-12-17 6:42 ` [PATCH 19/22] libiscsi: use blk/scsi-ml mq cmd pre-allocator Mike Christie
2020-12-17 6:42 ` [PATCH 20/22] libiscsi: rm iscsi_put_task back_lock requirement Mike Christie
2020-12-17 6:42 ` [PATCH 21/22] libiscsi: drop back_lock from xmit path Mike Christie
2020-12-17 6:42 ` [PATCH 22/22] libiscsi: fix conn_send_pdu API Mike Christie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1608187332-4434-16-git-send-email-michael.christie@oracle.com \
--to=michael.christie@oracle.com \
--cc=GR-QLogic-Storage-Upstream@marvell.com \
--cc=cleech@redhat.com \
--cc=jejb@linux.ibm.com \
--cc=lduncan@suse.com \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=mrangankar@marvell.com \
--cc=njavali@marvell.com \
--cc=varun@chelsio.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).