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
next prev 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).