[SCSI] cxgb3i: fix cpu use abuse during writes
authorMike Christie <michaelc@cs.wisc.edu>
Tue, 21 Apr 2009 20:32:34 +0000 (15:32 -0500)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Mon, 27 Apr 2009 15:10:06 +0000 (10:10 -0500)
When doing a lot (128) of large writes (256K) we can hit the cxgb3_snd_win
check pretty easily. The driver's xmit thread then takes 100% of the cpu.

The driver should not be returning -EAGAIN for this problem. It should
be returing -ENOBUFS, then when the window is opened again it should
queue the xmit thread (it already wakes the xmit thread).

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/scsi/cxgb3i/cxgb3i_offload.c
drivers/scsi/cxgb3i/cxgb3i_pdu.c

index 4d8654c..e11c9c1 100644 (file)
@@ -1737,7 +1737,7 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb)
                c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n",
                                c3cn, c3cn->write_seq, c3cn->snd_una,
                                cxgb3_snd_win);
-               err = -EAGAIN;
+               err = -ENOBUFS;
                goto out_err;
        }
 
@@ -1775,6 +1775,8 @@ done:
 out_err:
        if (copied == 0 && err == -EPIPE)
                copied = c3cn->err ? c3cn->err : -EPIPE;
+       else
+               copied = err;
        goto done;
 }
 
index 7eebc9a..7091050 100644 (file)
@@ -400,17 +400,18 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
                return 0;
        }
 
-       if (err < 0 && err != -EAGAIN) {
-               kfree_skb(skb);
-               cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
-                               task->itt, skb, skb->len, skb->data_len, err);
-               iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
-               iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+       if (err == -EAGAIN || err == -ENOBUFS) {
+               /* reset skb to send when we are called again */
+               tdata->skb = skb;
                return err;
        }
-       /* reset skb to send when we are called again */
-       tdata->skb = skb;
-       return -EAGAIN;
+
+       kfree_skb(skb);
+       cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
+                       task->itt, skb, skb->len, skb->data_len, err);
+       iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
+       iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+       return err;
 }
 
 int cxgb3i_pdu_init(void)