linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mike Christie <michael.christie@oracle.com>
To: subbu.seetharaman@broadcom.com, ketan.mukadam@broadcom.com,
	jitendra.bhivare@broadcom.com, 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,
	james.bottomley@hansenpartnership.com
Subject: [PATCH 15/15] libiscsi: convert ping_task to refcount handler
Date: Tue,  1 Dec 2020 15:29:56 -0600	[thread overview]
Message-ID: <1606858196-5421-16-git-send-email-michael.christie@oracle.com> (raw)
In-Reply-To: <1606858196-5421-1-git-send-email-michael.christie@oracle.com>

The conn_send_pdu API is evil in that it returns a pointer to a
iscsi_task, but that task might have been freed already. This
would happen with the ping_task code. To fix up the API so the
caller can access the task if it needs to like in the ping_task
case, this has conn_send_pdu grab a ref to the task for the
caller. We then move the ping_task clearing to when all the
refcounts are dropped, so we know the caller and a completion
do not race.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
---
 drivers/scsi/libiscsi.c | 39 +++++++++++++++++++++------------------
 include/scsi/libiscsi.h |  3 ---
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index e020fba..79cec93 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -546,13 +546,16 @@ static void iscsi_free_task(struct iscsi_task *task)
 		return;
 
 	iscsi_free_itt(session, task);
-
+ 
 	if (session->win_opened && !work_pending(&conn->xmitwork)) {
 		session->win_opened = false;
 		iscsi_conn_queue_work(conn);
 	}
 
 	if (!sc) {
+		if (READ_ONCE(conn->ping_task) == task)
+			WRITE_ONCE(conn->ping_task, NULL);
+
 		spin_lock_bh(&session->mgmt_lock);
 		kfifo_in(&session->mgmt_pool.queue, (void*)&task, sizeof(void*));
 		spin_unlock_bh(&session->mgmt_lock);
@@ -603,9 +606,6 @@ static void iscsi_complete_task(struct iscsi_task *task, int state)
 	WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
 	task->state = state;
 
-	if (READ_ONCE(conn->ping_task) == task)
-		WRITE_ONCE(conn->ping_task, NULL);
-
 	/* release get from queueing */
 	iscsi_put_task(task);
 }
@@ -819,6 +819,8 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
 	task->sc = NULL;
 	INIT_LIST_HEAD(&task->running);
 	task->state = ISCSI_TASK_PENDING;
+	/* Take an extra ref so the caller can access the task */
+	iscsi_get_task(task);
 
 	if (data_size) {
 		memcpy(task->data, data, data_size);
@@ -846,9 +848,6 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
 						   task->conn->session->age);
 	}
 
-	if (unlikely(READ_ONCE(conn->ping_task) == INVALID_SCSI_TASK))
-		WRITE_ONCE(conn->ping_task, task);
-
 	if (!ihost->workq) {
 		if (iscsi_prep_mgmt_task(conn, task))
 			goto free_task;
@@ -863,6 +862,8 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
 	return task;
 
 free_task:
+	/* drop extra count taken for caller and count from allocation */
+	iscsi_put_task(task);
 	iscsi_put_task(task);
 	return NULL;
 }
@@ -872,11 +873,15 @@ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
 	struct iscsi_session *session = conn->session;
+	struct iscsi_task *task;
 	int err = 0;
 
 	spin_lock_bh(&session->frwd_lock);
-	if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
+	task = __iscsi_conn_send_pdu(conn, hdr, data, data_size);
+	if (!task)
 		err = -EPERM;
+	else
+		iscsi_put_task(task);
 	spin_unlock_bh(&session->frwd_lock);
 	return err;
 }
@@ -1047,12 +1052,6 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
         struct iscsi_nopout hdr;
 	struct iscsi_task *task;
 
-	if (!rhdr) {
-		if (READ_ONCE(conn->ping_task))
-			return -EINVAL;
-		WRITE_ONCE(conn->ping_task, INVALID_SCSI_TASK);
-	}
-
 	memset(&hdr, 0, sizeof(struct iscsi_nopout));
 	hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
 	hdr.flags = ISCSI_FLAG_CMD_FINAL;
@@ -1061,20 +1060,23 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
 		hdr.lun = rhdr->lun;
 		hdr.ttt = rhdr->ttt;
 		hdr.itt = RESERVED_ITT;
-	} else
+	} else {
+		if (READ_ONCE(conn->ping_task))
+			return -EINVAL;
+
 		hdr.ttt = RESERVED_ITT;
+	}
 
 	task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
 	if (!task) {
-		if (!rhdr)
-			WRITE_ONCE(conn->ping_task, NULL);
 		iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
 		return -EIO;
 	} else if (!rhdr) {
 		/* only track our nops */
 		conn->last_ping = jiffies;
+		WRITE_ONCE(conn->ping_task, task);
 	}
-
+	iscsi_put_task(task);
 	return 0;
 }
 
@@ -1907,6 +1909,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
 		spin_lock_bh(&session->frwd_lock);
 		return -EPERM;
 	}
+	iscsi_put_task(task);
 	conn->tmfcmd_pdus_cnt++;
 	conn->tmf_timer.expires = timeout * HZ + jiffies;
 	add_timer(&conn->tmf_timer);
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index d0a6834..a17c551 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -133,9 +133,6 @@ struct iscsi_task {
 	void			*dd_data;	/* driver/transport data */
 };
 
-/* invalid scsi_task pointer */
-#define	INVALID_SCSI_TASK	(struct iscsi_task *)-1l
-
 static inline int iscsi_task_has_unsol_data(struct iscsi_task *task)
 {
 	return task->unsol_r2t.data_length > task->unsol_r2t.sent;
-- 
1.8.3.1


  parent reply	other threads:[~2020-12-01 21:33 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-01 21:29 [RFC PATCH 00/15] libiscsi: lock clean ups Mike Christie
2020-12-01 21:29 ` [PATCH 01/15] libiscsi: fix iscsi_prep_scsi_cmd_pdu error handling Mike Christie
2020-12-02 17:04   ` Lee Duncan
2020-12-01 21:29 ` [PATCH 02/15] libiscsi: drop taskqueuelock Mike Christie
2020-12-01 21:29 ` [PATCH 03/15] qla4xxx: use iscsi_is_session_online Mike Christie
2020-12-03 21:07   ` Lee Duncan
2020-12-01 21:29 ` [PATCH 04/15] iscsi class: drop session lock in iscsi_session_chkready Mike Christie
2020-12-03 21:08   ` Lee Duncan
2020-12-01 21:29 ` [PATCH 05/15] libiscsi: remove queued_cmdsn Mike Christie
2020-12-01 21:29 ` [PATCH 06/15] libiscsi: drop frwd lock for session state Mike Christie
2020-12-01 21:29 ` [PATCH 07/15] libiscsi: separate itt from task allocation Mike Christie
2020-12-01 21:29 ` [PATCH 08/15] iser, be2iscsi, qla4xxx: set scsi_host_template cmd_size Mike Christie
2020-12-01 21:29 ` [PATCH 09/15] bnx2i: " Mike Christie
2020-12-01 21:29 ` [PATCH 10/15] qedi: " Mike Christie
2020-12-01 21:29 ` [PATCH 11/15] iscsi_tcp, libcxgbi: " Mike Christie
2020-12-01 21:29 ` [PATCH 12/15] libiscsi: use blk/scsi-ml mq cmd pre-allocator Mike Christie
2020-12-01 21:29 ` [PATCH 13/15] libiscsi: drop back_lock requirement for iscsi_put_task Mike Christie
2020-12-01 21:29 ` [PATCH 14/15] libiscsi: drop back_lock from xmit path Mike Christie
2020-12-01 21:29 ` Mike Christie [this message]
2020-12-02  1:27   ` [PATCH 15/15] libiscsi: convert ping_task to refcount handler Mike Christie
2020-12-04 12:10 ` [EXT] [RFC PATCH 00/15] libiscsi: lock clean ups Manish Rangankar

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=1606858196-5421-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=james.bottomley@hansenpartnership.com \
    --cc=jitendra.bhivare@broadcom.com \
    --cc=ketan.mukadam@broadcom.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=subbu.seetharaman@broadcom.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).