Commit 98069cdd authored by Erez Zilber's avatar Erez Zilber Committed by Chris Wright

[PATCH] IB/iser: return error code when PDUs may not be sent

iSER limits the number of outstanding PDUs to send. When this threshold is
reached, it should return an error code (-ENOBUFS) instead of setting the
suspend_tx bit (which should be used only by libiscsi). Without this fix,
during logout, open-iscsi over iSER tries to logout forever.
Signed-off-by: default avatarErez Zilber <erezz@voltaire.com>
Signed-off-by: default avatarChris Wright <chrisw@sous-sol.org>
parent 10c06e62
...@@ -177,7 +177,7 @@ iscsi_iser_mtask_xmit(struct iscsi_conn *conn, ...@@ -177,7 +177,7 @@ iscsi_iser_mtask_xmit(struct iscsi_conn *conn,
* - if yes, the mtask is recycled at iscsi_complete_pdu * - if yes, the mtask is recycled at iscsi_complete_pdu
* - if no, the mtask is recycled at iser_snd_completion * - if no, the mtask is recycled at iser_snd_completion
*/ */
if (error && error != -EAGAIN) if (error && error != -ENOBUFS)
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
return error; return error;
...@@ -241,7 +241,7 @@ iscsi_iser_ctask_xmit(struct iscsi_conn *conn, ...@@ -241,7 +241,7 @@ iscsi_iser_ctask_xmit(struct iscsi_conn *conn,
error = iscsi_iser_ctask_xmit_unsol_data(conn, ctask); error = iscsi_iser_ctask_xmit_unsol_data(conn, ctask);
iscsi_iser_ctask_xmit_exit: iscsi_iser_ctask_xmit_exit:
if (error && error != -EAGAIN) if (error && error != -ENOBUFS)
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
return error; return error;
} }
......
...@@ -304,18 +304,14 @@ int iser_conn_set_full_featured_mode(struct iscsi_conn *conn) ...@@ -304,18 +304,14 @@ int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
static int static int
iser_check_xmit(struct iscsi_conn *conn, void *task) iser_check_xmit(struct iscsi_conn *conn, void *task)
{ {
int rc = 0;
struct iscsi_iser_conn *iser_conn = conn->dd_data; struct iscsi_iser_conn *iser_conn = conn->dd_data;
write_lock_bh(conn->recv_lock);
if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) == if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
ISER_QP_MAX_REQ_DTOS) { ISER_QP_MAX_REQ_DTOS) {
iser_dbg("%ld can't xmit task %p, suspending tx\n",jiffies,task); iser_dbg("%ld can't xmit task %p\n",jiffies,task);
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); return -ENOBUFS;
rc = -EAGAIN;
} }
write_unlock_bh(conn->recv_lock); return 0;
return rc;
} }
...@@ -340,7 +336,7 @@ int iser_send_command(struct iscsi_conn *conn, ...@@ -340,7 +336,7 @@ int iser_send_command(struct iscsi_conn *conn,
return -EPERM; return -EPERM;
} }
if (iser_check_xmit(conn, ctask)) if (iser_check_xmit(conn, ctask))
return -EAGAIN; return -ENOBUFS;
edtl = ntohl(hdr->data_length); edtl = ntohl(hdr->data_length);
...@@ -426,7 +422,7 @@ int iser_send_data_out(struct iscsi_conn *conn, ...@@ -426,7 +422,7 @@ int iser_send_data_out(struct iscsi_conn *conn,
} }
if (iser_check_xmit(conn, ctask)) if (iser_check_xmit(conn, ctask))
return -EAGAIN; return -ENOBUFS;
itt = ntohl(hdr->itt); itt = ntohl(hdr->itt);
data_seg_len = ntoh24(hdr->dlength); data_seg_len = ntoh24(hdr->dlength);
...@@ -500,7 +496,7 @@ int iser_send_control(struct iscsi_conn *conn, ...@@ -500,7 +496,7 @@ int iser_send_control(struct iscsi_conn *conn,
} }
if (iser_check_xmit(conn,mtask)) if (iser_check_xmit(conn,mtask))
return -EAGAIN; return -ENOBUFS;
/* build the tx desc regd header and add it to the tx desc dto */ /* build the tx desc regd header and add it to the tx desc dto */
mdesc->type = ISCSI_TX_CONTROL; mdesc->type = ISCSI_TX_CONTROL;
...@@ -609,6 +605,7 @@ void iser_snd_completion(struct iser_desc *tx_desc) ...@@ -609,6 +605,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn; struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn;
struct iscsi_conn *conn = iser_conn->iscsi_conn; struct iscsi_conn *conn = iser_conn->iscsi_conn;
struct iscsi_mgmt_task *mtask; struct iscsi_mgmt_task *mtask;
int resume_tx = 0;
iser_dbg("Initiator, Data sent dto=0x%p\n", dto); iser_dbg("Initiator, Data sent dto=0x%p\n", dto);
...@@ -617,15 +614,16 @@ void iser_snd_completion(struct iser_desc *tx_desc) ...@@ -617,15 +614,16 @@ void iser_snd_completion(struct iser_desc *tx_desc)
if (tx_desc->type == ISCSI_TX_DATAOUT) if (tx_desc->type == ISCSI_TX_DATAOUT)
kmem_cache_free(ig.desc_cache, tx_desc); kmem_cache_free(ig.desc_cache, tx_desc);
if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
ISER_QP_MAX_REQ_DTOS)
resume_tx = 1;
atomic_dec(&ib_conn->post_send_buf_count); atomic_dec(&ib_conn->post_send_buf_count);
write_lock(conn->recv_lock); if (resume_tx) {
if (conn->suspend_tx) {
iser_dbg("%ld resuming tx\n",jiffies); iser_dbg("%ld resuming tx\n",jiffies);
clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
scsi_queue_work(conn->session->host, &conn->xmitwork); scsi_queue_work(conn->session->host, &conn->xmitwork);
} }
write_unlock(conn->recv_lock);
if (tx_desc->type == ISCSI_TX_CONTROL) { if (tx_desc->type == ISCSI_TX_CONTROL) {
/* this arithmetic is legal by libiscsi dd_data allocation */ /* this arithmetic is legal by libiscsi dd_data allocation */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment