aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/iscsi_tcp.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-07-24 16:47:15 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-07-28 12:47:40 -0400
commitb6c395ed0387c824ddf125d3b74b576a2575c149 (patch)
tree76ca5cd982063335088384622e5033401bbc5057 /drivers/scsi/iscsi_tcp.c
parentd82967c70658a408ea6cae5dc989ba8b2c0999e1 (diff)
[SCSI] iscsi bugfixes: fix r2t handling
The iscsi tcp code can pluck multiple rt2s from the tasks's r2tqueue in the xmit code. This can result in the task being queued on the xmit queue but gettting completed at the same time. This patch fixes the above bug by making the fifo a list so we always remove the entry on the list del. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r--drivers/scsi/iscsi_tcp.c45
1 files changed, 21 insertions, 24 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 88dafdf45c47..ab324d984b8d 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -185,11 +185,19 @@ iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn)
185 * must be called with session lock 185 * must be called with session lock
186 */ 186 */
187static void 187static void
188__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) 188iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
189{ 189{
190 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 190 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
191 struct iscsi_r2t_info *r2t;
191 struct scsi_cmnd *sc; 192 struct scsi_cmnd *sc;
192 193
194 /* flush ctask's r2t queues */
195 while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
196 __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
197 sizeof(void*));
198 debug_scsi("iscsi_tcp_cleanup_ctask pending r2t dropped\n");
199 }
200
193 sc = ctask->sc; 201 sc = ctask->sc;
194 if (unlikely(!sc)) 202 if (unlikely(!sc))
195 return; 203 return;
@@ -374,6 +382,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
374 spin_unlock(&session->lock); 382 spin_unlock(&session->lock);
375 return 0; 383 return 0;
376 } 384 }
385
377 rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); 386 rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
378 BUG_ON(!rc); 387 BUG_ON(!rc);
379 388
@@ -399,7 +408,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
399 tcp_ctask->exp_r2tsn = r2tsn + 1; 408 tcp_ctask->exp_r2tsn = r2tsn + 1;
400 tcp_ctask->xmstate |= XMSTATE_SOL_HDR; 409 tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
401 __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); 410 __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
402 __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); 411 list_move_tail(&ctask->running, &conn->xmitqueue);
403 412
404 scsi_queue_work(session->host, &conn->xmitwork); 413 scsi_queue_work(session->host, &conn->xmitwork);
405 conn->r2t_pdus_cnt++; 414 conn->r2t_pdus_cnt++;
@@ -484,7 +493,7 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
484 goto copy_hdr; 493 goto copy_hdr;
485 494
486 spin_lock(&session->lock); 495 spin_lock(&session->lock);
487 __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); 496 iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
488 rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); 497 rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
489 spin_unlock(&session->lock); 498 spin_unlock(&session->lock);
490 break; 499 break;
@@ -745,10 +754,11 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
745done: 754done:
746 /* check for non-exceptional status */ 755 /* check for non-exceptional status */
747 if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) { 756 if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) {
748 debug_scsi("done [sc %lx res %d itt 0x%x]\n", 757 debug_scsi("done [sc %lx res %d itt 0x%x flags 0x%x]\n",
749 (long)sc, sc->result, ctask->itt); 758 (long)sc, sc->result, ctask->itt,
759 tcp_conn->in.hdr->flags);
750 spin_lock(&conn->session->lock); 760 spin_lock(&conn->session->lock);
751 __iscsi_ctask_cleanup(conn, ctask); 761 iscsi_tcp_cleanup_ctask(conn, ctask);
752 __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0); 762 __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0);
753 spin_unlock(&conn->session->lock); 763 spin_unlock(&conn->session->lock);
754 } 764 }
@@ -769,7 +779,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
769 break; 779 break;
770 case ISCSI_OP_SCSI_CMD_RSP: 780 case ISCSI_OP_SCSI_CMD_RSP:
771 spin_lock(&conn->session->lock); 781 spin_lock(&conn->session->lock);
772 __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); 782 iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
773 spin_unlock(&conn->session->lock); 783 spin_unlock(&conn->session->lock);
774 case ISCSI_OP_TEXT_RSP: 784 case ISCSI_OP_TEXT_RSP:
775 case ISCSI_OP_LOGIN_RSP: 785 case ISCSI_OP_LOGIN_RSP:
@@ -1308,7 +1318,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
1308 ctask->imm_count - 1318 ctask->imm_count -
1309 ctask->unsol_count; 1319 ctask->unsol_count;
1310 1320
1311 debug_scsi("cmd [itt %x total %d imm %d imm_data %d " 1321 debug_scsi("cmd [itt 0x%x total %d imm %d imm_data %d "
1312 "r2t_data %d]\n", 1322 "r2t_data %d]\n",
1313 ctask->itt, ctask->total_length, ctask->imm_count, 1323 ctask->itt, ctask->total_length, ctask->imm_count,
1314 ctask->unsol_count, tcp_ctask->r2t_data_count); 1324 ctask->unsol_count, tcp_ctask->r2t_data_count);
@@ -1636,7 +1646,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1636 } 1646 }
1637solicit_again: 1647solicit_again:
1638 /* 1648 /*
1639 * send Data-Out whitnin this R2T sequence. 1649 * send Data-Out within this R2T sequence.
1640 */ 1650 */
1641 if (!r2t->data_count) 1651 if (!r2t->data_count)
1642 goto data_out_done; 1652 goto data_out_done;
@@ -1731,7 +1741,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1731 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1741 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1732 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 1742 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1733 struct iscsi_data_task *dtask = tcp_ctask->dtask; 1743 struct iscsi_data_task *dtask = tcp_ctask->dtask;
1734 int sent, rc; 1744 int sent = 0, rc;
1735 1745
1736 tcp_ctask->xmstate &= ~XMSTATE_W_PAD; 1746 tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
1737 iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, 1747 iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
@@ -2002,20 +2012,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
2002} 2012}
2003 2013
2004static void 2014static void
2005iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
2006{
2007 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
2008 struct iscsi_r2t_info *r2t;
2009
2010 /* flush ctask's r2t queues */
2011 while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)))
2012 __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
2013 sizeof(void*));
2014
2015 __iscsi_ctask_cleanup(conn, ctask);
2016}
2017
2018static void
2019iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn) 2015iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn)
2020{ 2016{
2021 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 2017 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
@@ -2057,6 +2053,7 @@ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
2057 iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, 2053 iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
2058 sizeof(struct iscsi_hdr)); 2054 sizeof(struct iscsi_hdr));
2059 tcp_mtask->xmstate = XMSTATE_IMM_HDR; 2055 tcp_mtask->xmstate = XMSTATE_IMM_HDR;
2056 tcp_mtask->sent = 0;
2060 2057
2061 if (mtask->data_count) 2058 if (mtask->data_count)
2062 iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, 2059 iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,