From: Mike Christie <micha...@cs.wisc.edu>

bnx2i currently has a check for if a ep is properly bound, so if
iscsi_queuecommand/xmit_task is called while there is no ep
we will not queue IO.

be2iscsi sends IO from queuecommand/xmit_task like how bnx2i does
and needs a similar test. This patch has us just use the suspend_bit
test for this.

When ep_poll has succeeed iscsid will call conn_bind, the LLD will
then call iscsi_conn_bind which will clear the suspend bit.
When ep_disconnect is called (or if there is a conn error) we set
the suspend bit. For the ep_disconnect case I am adding a helper
in this patch that will take the session lock to make sure
iscsi_queuecommand/xmit_task is not running and it will set
the suspend bit.

Signed-off-by: Mike Christie <micha...@cs.wisc.edu>
---
 drivers/scsi/bnx2i/bnx2i.h       |    1 -
 drivers/scsi/bnx2i/bnx2i_iscsi.c |    8 +-------
 drivers/scsi/libiscsi.c          |   33 +++++++++++++++++++++++++++++++++
 include/scsi/libiscsi.h          |    1 +
 4 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index d7576f2..03052c8 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -230,7 +230,6 @@ struct bnx2i_conn {
        struct iscsi_cls_conn *cls_conn;
        struct bnx2i_hba *hba;
        struct completion cmd_cleanup_cmpl;
-       int is_bound;
 
        u32 iscsi_conn_cid;
 #define BNX2I_CID_RESERVED     0x5AFF
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 9a7ba71..cae8370 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1161,9 +1161,6 @@ static int bnx2i_task_xmit(struct iscsi_task *task)
        struct bnx2i_cmd *cmd = task->dd_data;
        struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr;
 
-       if (!bnx2i_conn->is_bound)
-               return -ENOTCONN;
-
        /*
         * If there is no scsi_cmnd this must be a mgmt task
         */
@@ -1371,7 +1368,6 @@ static int bnx2i_conn_bind(struct iscsi_cls_session 
*cls_session,
        bnx2i_conn->ep = bnx2i_ep;
        bnx2i_conn->iscsi_conn_cid = bnx2i_ep->ep_iscsi_cid;
        bnx2i_conn->fw_cid = bnx2i_ep->ep_cid;
-       bnx2i_conn->is_bound = 1;
 
        ret_code = bnx2i_bind_conn_to_iscsi_cid(hba, bnx2i_conn,
                                                bnx2i_ep->ep_iscsi_cid);
@@ -1896,9 +1892,7 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep)
                conn = bnx2i_conn->cls_conn->dd_data;
                session = conn->session;
 
-               spin_lock_bh(&session->lock);
-               bnx2i_conn->is_bound = 0;
-               spin_unlock_bh(&session->lock);
+               iscsi_suspend_queue(conn);
        }
 
        hba = bnx2i_ep->hba;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index ef985d2..248636f 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1580,6 +1580,12 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void 
(*done)(struct scsi_cmnd *))
                goto fault;
        }
 
+       if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
+               reason = FAILURE_SESSION_IN_RECOVERY;
+               sc->result = DID_REQUEUE;
+               goto fault;
+       }
+
        if (iscsi_check_cmdsn_window_closed(conn)) {
                reason = FAILURE_WINDOW_CLOSED;
                goto reject;
@@ -1819,6 +1825,33 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, 
unsigned lun,
        }
 }
 
+/**
+ * iscsi_suspend_queue - suspend iscsi_queuecommand
+ * @conn: iscsi conn to stop queueing IO on
+ *
+ * This grabs the session lock to make sure no one is in
+ * xmit_task/queuecommand, and then sets suspend to prevent
+ * new commands from being queued. This only needs to be called
+ * by offload drivers that need to sync a path like ep disconnect
+ * with the iscsi_queuecommand/xmit_task. To start IO again libiscsi
+ * will call iscsi_start_tx and iscsi_unblock_session when in FFP.
+ */
+void iscsi_suspend_queue(struct iscsi_conn *conn)
+{
+       spin_lock_bh(&conn->session->lock);
+       set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+       spin_unlock_bh(&conn->session->lock);
+}
+EXPORT_SYMBOL_GPL(iscsi_suspend_queue);
+
+/**
+ * iscsi_suspend_tx - suspend iscsi_data_xmit
+ * @conn: iscsi conn tp stop processing IO on.
+ *
+ * This function sets the suspend bit to prevent iscsi_data_xmit
+ * from sending new IO, and if work is queued on the xmit thread
+ * it will wait for it to be completed.
+ */
 void iscsi_suspend_tx(struct iscsi_conn *conn)
 {
        struct Scsi_Host *shost = conn->session->host;
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 439c8b7..887e57e 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -390,6 +390,7 @@ extern void iscsi_session_failure(struct iscsi_session 
*session,
 extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
                                enum iscsi_param param, char *buf);
 extern void iscsi_suspend_tx(struct iscsi_conn *conn);
+extern void iscsi_suspend_queue(struct iscsi_conn *conn);
 extern void iscsi_conn_queue_work(struct iscsi_conn *conn);
 
 #define iscsi_conn_printk(prefix, _c, fmt, a...) \
-- 
1.6.2.2


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-iscsi@googlegroups.com
To unsubscribe from this group, send email to 
open-iscsi+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---

Reply via email to