[SCSI] libiscsi: fix logout pdu processing
authorMike Christie <michaelc@cs.wisc.edu>
Mon, 16 Oct 2006 22:09:42 +0000 (18:09 -0400)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Wed, 25 Oct 2006 22:14:05 +0000 (15:14 -0700)
According to the iscsi RFC, we cannot send other requests if
we have sent a logout pdu. This patch enforces this requirement
by blocking the session and suspending the send thread. Userspace
decides if we restart the connection or if we just free everything.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/libiscsi.c

index f5a9560b357fb7b3fa644bad934595cbd5206c42..2865ebd557ef9d17f57dd2df72f54b2e1246658f 100644 (file)
@@ -578,6 +578,27 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_failure);
 
+static int iscsi_xmit_imm_task(struct iscsi_conn *conn)
+{
+       struct iscsi_hdr *hdr = conn->mtask->hdr;
+       int rc, was_logout = 0;
+
+       if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) {
+               conn->session->state = ISCSI_STATE_IN_RECOVERY;
+               iscsi_block_session(session_to_cls(conn->session));
+               was_logout = 1;
+       }
+       rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask);
+       if (rc)
+               return rc;
+
+       if (was_logout) {
+               set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+               return -ENODATA;
+       }
+       return 0;
+}
+
 /**
  * iscsi_data_xmit - xmit any command into the scheduled connection
  * @conn: iscsi connection
@@ -623,7 +644,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
                conn->ctask = NULL;
        }
        if (conn->mtask) {
-               rc = tt->xmit_mgmt_task(conn, conn->mtask);
+               rc = iscsi_xmit_imm_task(conn);
                if (rc)
                        goto again;
                /* done with this in-progress mtask */
@@ -638,7 +659,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
                        list_add_tail(&conn->mtask->running,
                                      &conn->mgmt_run_list);
                        spin_unlock_bh(&conn->session->lock);
-                       rc = tt->xmit_mgmt_task(conn, conn->mtask);
+                       rc = iscsi_xmit_imm_task(conn);
                        if (rc)
                                goto again;
                }