[SCSI] iscsi: fix writepsace race

We can race and misset the suspend bit if iscsi_write_space is
called then iscsi_send returns with a failure indicating
there is no space.

To handle this this patch returns a error upwards allowing xmitworker
to decide if we need to try and transmit again. For the no
write space case xmitworker will not retry, and instead
let iscsi_write_space queue it back up if needed (this relies
on the work queue code to properly requeue us if needed).

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 256b87a..2673a11 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -513,10 +513,11 @@
 static int iscsi_data_xmit(struct iscsi_conn *conn)
 {
 	struct iscsi_transport *tt;
+	int rc = 0;
 
 	if (unlikely(conn->suspend_tx)) {
 		debug_scsi("conn %d Tx suspended!\n", conn->id);
-		return 0;
+		return -ENODATA;
 	}
 	tt = conn->session->tt;
 
@@ -536,13 +537,15 @@
 	BUG_ON(conn->ctask && conn->mtask);
 
 	if (conn->ctask) {
-		if (tt->xmit_cmd_task(conn, conn->ctask))
+		rc = tt->xmit_cmd_task(conn, conn->ctask);
+		if (rc)
 			goto again;
 		/* done with this in-progress ctask */
 		conn->ctask = NULL;
 	}
 	if (conn->mtask) {
-	        if (tt->xmit_mgmt_task(conn, conn->mtask))
+		rc = tt->xmit_mgmt_task(conn, conn->mtask);
+	        if (rc)
 		        goto again;
 		/* done with this in-progress mtask */
 		conn->mtask = NULL;
@@ -556,7 +559,8 @@
 			list_add_tail(&conn->mtask->running,
 				      &conn->mgmt_run_list);
 			spin_unlock_bh(&conn->session->lock);
-		        if (tt->xmit_mgmt_task(conn, conn->mtask))
+			rc = tt->xmit_mgmt_task(conn, conn->mtask);
+		        if (rc)
 			        goto again;
 	        }
 		/* done with this mtask */
@@ -574,7 +578,8 @@
 		if (list_empty(&conn->ctask->running))
 			list_add_tail(&conn->ctask->running, &conn->run_list);
 		spin_unlock_bh(&conn->session->lock);
-		if (tt->xmit_cmd_task(conn, conn->ctask))
+		rc = tt->xmit_cmd_task(conn, conn->ctask);
+		if (rc)
 			goto again;
 	}
 	/* done with this ctask */
@@ -588,32 +593,34 @@
 			list_add_tail(&conn->mtask->running,
 				      &conn->mgmt_run_list);
 			spin_unlock_bh(&conn->session->lock);
-		        if (tt->xmit_mgmt_task(conn, conn->mtask))
+		        rc = tt->xmit_mgmt_task(conn, conn->mtask);
+			if (rc)
 			        goto again;
 	        }
 		/* done with this mtask */
 		conn->mtask = NULL;
 	}
 
-	return 0;
+	return -ENODATA;
 
 again:
 	if (unlikely(conn->suspend_tx))
-		return 0;
+		return -ENODATA;
 
-	return -EAGAIN;
+	return rc;
 }
 
 static void iscsi_xmitworker(void *data)
 {
 	struct iscsi_conn *conn = data;
-
+	int rc;
 	/*
 	 * serialize Xmit worker on a per-connection basis.
 	 */
 	mutex_lock(&conn->xmitmutex);
-	if (iscsi_data_xmit(conn))
-		scsi_queue_work(conn->session->host, &conn->xmitwork);
+	do {
+		rc = iscsi_data_xmit(conn);
+	} while (rc >= 0 || rc == -EAGAIN);
 	mutex_unlock(&conn->xmitmutex);
 }