From: michaelc@cs.wisc.edu
To: linux-scsi@vger.kernel.org
Cc: Mike Christie <michaelc@cs.wisc.edu>
Subject: [PATCH 1/3] libiscsi: fix nop xmit failure handling
Date: Thu, 14 Jun 2012 23:15:45 -0500 [thread overview]
Message-ID: <1339733747-14731-2-git-send-email-michaelc@cs.wisc.edu> (raw)
In-Reply-To: <1339733747-14731-1-git-send-email-michaelc@cs.wisc.edu>
From: Mike Christie <michaelc@cs.wisc.edu>
If we cannot queue a nop, because we cannot allocate
resources then retry in recv timeout seconds.
Without this patch, last_ping does not get updated, so
we end up retrying right away.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
---
drivers/scsi/libiscsi.c | 68 +++++++++++++++++++++++++++++++----------------
1 files changed, 45 insertions(+), 23 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 82c3fd4..5b4adc4 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -701,9 +701,10 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
uint8_t opcode = hdr->opcode & ISCSI_OPCODE_MASK;
struct iscsi_task *task;
itt_t itt;
+ int err;
if (session->state == ISCSI_STATE_TERMINATE)
- return NULL;
+ return ERR_PTR(-ENOTCONN);
if (opcode == ISCSI_OP_LOGIN || opcode == ISCSI_OP_TEXT) {
/*
@@ -715,20 +716,20 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
if (conn->login_task->state != ISCSI_TASK_FREE) {
iscsi_conn_printk(KERN_ERR, conn, "Login/Text in "
"progress. Cannot start new task.\n");
- return NULL;
+ return ERR_PTR(-EBUSY);
}
task = conn->login_task;
} else {
if (session->state != ISCSI_STATE_LOGGED_IN)
- return NULL;
+ return ERR_PTR(-ENOTCONN);
BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
if (!kfifo_out(&session->cmdpool.queue,
(void*)&task, sizeof(void*)))
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
/*
* released in complete pdu for task we expect a response for, and
@@ -748,7 +749,8 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
task->data_count = 0;
if (conn->session->tt->alloc_pdu) {
- if (conn->session->tt->alloc_pdu(task, hdr->opcode)) {
+ err = conn->session->tt->alloc_pdu(task, hdr->opcode);
+ if (err) {
iscsi_conn_printk(KERN_ERR, conn, "Could not allocate "
"pdu for mgmt task.\n");
goto free_task;
@@ -768,10 +770,12 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
}
if (!ihost->workq) {
- if (iscsi_prep_mgmt_task(conn, task))
+ err = iscsi_prep_mgmt_task(conn, task);
+ if (err)
goto free_task;
- if (session->tt->xmit_task(task))
+ err = session->tt->xmit_task(task);
+ if (err)
goto free_task;
} else {
list_add_tail(&task->running, &conn->mgmtqueue);
@@ -782,7 +786,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
free_task:
__iscsi_put_task(task);
- return NULL;
+ return ERR_PTR(err);
}
int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
@@ -790,13 +794,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;
- int err = 0;
+ struct iscsi_task *task;
spin_lock_bh(&session->lock);
- if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
- err = -EPERM;
+ task = __iscsi_conn_send_pdu(conn, hdr, data, data_size);
spin_unlock_bh(&session->lock);
- return err;
+
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+ return 0;
}
EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
@@ -940,13 +946,14 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
wake_up(&conn->ehwait);
}
-static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
+static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
{
struct iscsi_nopout hdr;
struct iscsi_task *task;
+ int err;
if (!rhdr && conn->ping_task)
- return;
+ return -EEXIST;
memset(&hdr, 0, sizeof(struct iscsi_nopout));
hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
@@ -960,13 +967,19 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
hdr.ttt = RESERVED_ITT;
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
- if (!task)
- iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
- else if (!rhdr) {
+ if (IS_ERR(task)) {
+ err = PTR_ERR(task);
+
+ iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout. "
+ "Error %d.\n", err);
+ return err;
+ } else if (!rhdr) {
/* only track our nops */
conn->ping_task = task;
conn->last_ping = jiffies;
}
+
+ return 0;
}
static int iscsi_nop_out_rsp(struct iscsi_task *task,
@@ -1766,14 +1779,13 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
struct iscsi_session *session = conn->session;
struct iscsi_task *task;
- task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
- NULL, 0);
- if (!task) {
+ task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
+ if (IS_ERR(task)) {
spin_unlock_bh(&session->lock);
iscsi_conn_printk(KERN_ERR, conn, "Could not send TMF.\n");
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
spin_lock_bh(&session->lock);
- return -EPERM;
+ return PTR_ERR(task);
}
conn->tmfcmd_pdus_cnt++;
conn->tmf_timer.expires = timeout * HZ + jiffies;
@@ -2033,6 +2045,7 @@ static void iscsi_check_transport_timeouts(unsigned long data)
struct iscsi_conn *conn = (struct iscsi_conn *)data;
struct iscsi_session *session = conn->session;
unsigned long recv_timeout, next_timeout = 0, last_recv;
+ int err;
spin_lock(&session->lock);
if (session->state != ISCSI_STATE_LOGGED_IN)
@@ -2059,8 +2072,17 @@ static void iscsi_check_transport_timeouts(unsigned long data)
if (time_before_eq(last_recv + recv_timeout, jiffies)) {
/* send a ping to try to provoke some traffic */
ISCSI_DBG_CONN(conn, "Sending nopout as ping\n");
- iscsi_send_nopout(conn, NULL);
- next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
+ err = iscsi_send_nopout(conn, NULL);
+ if (!err || err == -EEXIST)
+ next_timeout = conn->last_ping +
+ (conn->ping_timeout * HZ);
+ else
+ /*
+ * If we could not send due to resource error or slow
+ * conn not taking things off of queue quick enough
+ * then we do not want to drop the session.
+ */
+ next_timeout = jiffies + recv_timeout;
} else
next_timeout = last_recv + recv_timeout;
--
1.7.7.6
next prev parent reply other threads:[~2012-06-15 5:05 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-15 4:15 iscsi changes for scsi misc michaelc
2012-06-15 4:15 ` michaelc [this message]
2012-06-15 4:15 ` [PATCH 2/3] libiscsi: update nop stats michaelc
2012-06-15 4:15 ` [PATCH 3/3] iscsi drivers: use libiscsi get stats fn michaelc
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=1339733747-14731-2-git-send-email-michaelc@cs.wisc.edu \
--to=michaelc@cs.wisc.edu \
--cc=linux-scsi@vger.kernel.org \
/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).