aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.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/libiscsi.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/libiscsi.c')
-rw-r--r--drivers/scsi/libiscsi.c90
1 files changed, 38 insertions, 52 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 7e6e031cc41b..1a8cd20f484f 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -189,6 +189,7 @@ static void iscsi_complete_command(struct iscsi_session *session,
189{ 189{
190 struct scsi_cmnd *sc = ctask->sc; 190 struct scsi_cmnd *sc = ctask->sc;
191 191
192 ctask->state = ISCSI_TASK_COMPLETED;
192 ctask->sc = NULL; 193 ctask->sc = NULL;
193 list_del_init(&ctask->running); 194 list_del_init(&ctask->running);
194 __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); 195 __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
@@ -568,20 +569,24 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
568 } 569 }
569 570
570 /* process command queue */ 571 /* process command queue */
571 while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, 572 spin_lock_bh(&conn->session->lock);
572 sizeof(void*))) { 573 while (!list_empty(&conn->xmitqueue)) {
573 /* 574 /*
574 * iscsi tcp may readd the task to the xmitqueue to send 575 * iscsi tcp may readd the task to the xmitqueue to send
575 * write data 576 * write data
576 */ 577 */
577 spin_lock_bh(&conn->session->lock); 578 conn->ctask = list_entry(conn->xmitqueue.next,
578 if (list_empty(&conn->ctask->running)) 579 struct iscsi_cmd_task, running);
579 list_add_tail(&conn->ctask->running, &conn->run_list); 580 conn->ctask->state = ISCSI_TASK_RUNNING;
581 list_move_tail(conn->xmitqueue.next, &conn->run_list);
580 spin_unlock_bh(&conn->session->lock); 582 spin_unlock_bh(&conn->session->lock);
583
581 rc = tt->xmit_cmd_task(conn, conn->ctask); 584 rc = tt->xmit_cmd_task(conn, conn->ctask);
582 if (rc) 585 if (rc)
583 goto again; 586 goto again;
587 spin_lock_bh(&conn->session->lock);
584 } 588 }
589 spin_unlock_bh(&conn->session->lock);
585 /* done with this ctask */ 590 /* done with this ctask */
586 conn->ctask = NULL; 591 conn->ctask = NULL;
587 592
@@ -691,6 +696,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
691 sc->SCp.phase = session->age; 696 sc->SCp.phase = session->age;
692 sc->SCp.ptr = (char *)ctask; 697 sc->SCp.ptr = (char *)ctask;
693 698
699 ctask->state = ISCSI_TASK_PENDING;
694 ctask->mtask = NULL; 700 ctask->mtask = NULL;
695 ctask->conn = conn; 701 ctask->conn = conn;
696 ctask->sc = sc; 702 ctask->sc = sc;
@@ -700,7 +706,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
700 706
701 session->tt->init_cmd_task(ctask); 707 session->tt->init_cmd_task(ctask);
702 708
703 __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); 709 list_add_tail(&ctask->running, &conn->xmitqueue);
704 debug_scsi( 710 debug_scsi(
705 "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", 711 "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n",
706 sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", 712 sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
@@ -977,31 +983,27 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
977/* 983/*
978 * xmit mutex and session lock must be held 984 * xmit mutex and session lock must be held
979 */ 985 */
980#define iscsi_remove_task(tasktype) \ 986static struct iscsi_mgmt_task *
981static struct iscsi_##tasktype * \ 987iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt)
982iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt) \ 988{
983{ \ 989 int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*);
984 int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); \ 990 struct iscsi_mgmt_task *task;
985 struct iscsi_##tasktype *task; \ 991
986 \ 992 debug_scsi("searching %d tasks\n", nr_tasks);
987 debug_scsi("searching %d tasks\n", nr_tasks); \ 993
988 \ 994 for (i = 0; i < nr_tasks; i++) {
989 for (i = 0; i < nr_tasks; i++) { \ 995 __kfifo_get(fifo, (void*)&task, sizeof(void*));
990 __kfifo_get(fifo, (void*)&task, sizeof(void*)); \ 996 debug_scsi("check task %u\n", task->itt);
991 debug_scsi("check task %u\n", task->itt); \ 997
992 \ 998 if (task->itt == itt) {
993 if (task->itt == itt) { \ 999 debug_scsi("matched task\n");
994 debug_scsi("matched task\n"); \ 1000 return task;
995 return task; \ 1001 }
996 } \
997 \
998 __kfifo_put(fifo, (void*)&task, sizeof(void*)); \
999 } \
1000 return NULL; \
1001}
1002 1002
1003iscsi_remove_task(mgmt_task); 1003 __kfifo_put(fifo, (void*)&task, sizeof(void*));
1004iscsi_remove_task(cmd_task); 1004 }
1005 return NULL;
1006}
1005 1007
1006static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) 1008static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
1007{ 1009{
@@ -1043,7 +1045,6 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
1043 struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; 1045 struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
1044 struct iscsi_conn *conn = ctask->conn; 1046 struct iscsi_conn *conn = ctask->conn;
1045 struct iscsi_session *session = conn->session; 1047 struct iscsi_session *session = conn->session;
1046 struct iscsi_cmd_task *pending_ctask;
1047 int rc; 1048 int rc;
1048 1049
1049 conn->eh_abort_cnt++; 1050 conn->eh_abort_cnt++;
@@ -1071,17 +1072,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
1071 goto failed; 1072 goto failed;
1072 } 1073 }
1073 1074
1074 /* check for the easy pending cmd abort */ 1075 if (ctask->state == ISCSI_TASK_PENDING)
1075 pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt); 1076 goto success;
1076 if (pending_ctask) {
1077 /* iscsi_tcp queues write transfers on the xmitqueue */
1078 if (list_empty(&pending_ctask->running)) {
1079 debug_scsi("found pending task\n");
1080 goto success;
1081 } else
1082 __kfifo_put(conn->xmitqueue, (void*)&pending_ctask,
1083 sizeof(void*));
1084 }
1085 1077
1086 conn->tmabort_state = TMABORT_INITIAL; 1078 conn->tmabort_state = TMABORT_INITIAL;
1087 1079
@@ -1263,6 +1255,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
1263 if (cmd_task_size) 1255 if (cmd_task_size)
1264 ctask->dd_data = &ctask[1]; 1256 ctask->dd_data = &ctask[1];
1265 ctask->itt = cmd_i; 1257 ctask->itt = cmd_i;
1258 INIT_LIST_HEAD(&ctask->running);
1266 } 1259 }
1267 1260
1268 spin_lock_init(&session->lock); 1261 spin_lock_init(&session->lock);
@@ -1282,6 +1275,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
1282 if (mgmt_task_size) 1275 if (mgmt_task_size)
1283 mtask->dd_data = &mtask[1]; 1276 mtask->dd_data = &mtask[1];
1284 mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; 1277 mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i;
1278 INIT_LIST_HEAD(&mtask->running);
1285 } 1279 }
1286 1280
1287 if (scsi_add_host(shost, NULL)) 1281 if (scsi_add_host(shost, NULL))
@@ -1361,12 +1355,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
1361 conn->tmabort_state = TMABORT_INITIAL; 1355 conn->tmabort_state = TMABORT_INITIAL;
1362 INIT_LIST_HEAD(&conn->run_list); 1356 INIT_LIST_HEAD(&conn->run_list);
1363 INIT_LIST_HEAD(&conn->mgmt_run_list); 1357 INIT_LIST_HEAD(&conn->mgmt_run_list);
1364 1358 INIT_LIST_HEAD(&conn->xmitqueue);
1365 /* initialize general xmit PDU commands queue */
1366 conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
1367 GFP_KERNEL, NULL);
1368 if (conn->xmitqueue == ERR_PTR(-ENOMEM))
1369 goto xmitqueue_alloc_fail;
1370 1359
1371 /* initialize general immediate & non-immediate PDU commands queue */ 1360 /* initialize general immediate & non-immediate PDU commands queue */
1372 conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), 1361 conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
@@ -1410,8 +1399,6 @@ login_mtask_alloc_fail:
1410mgmtqueue_alloc_fail: 1399mgmtqueue_alloc_fail:
1411 kfifo_free(conn->immqueue); 1400 kfifo_free(conn->immqueue);
1412immqueue_alloc_fail: 1401immqueue_alloc_fail:
1413 kfifo_free(conn->xmitqueue);
1414xmitqueue_alloc_fail:
1415 iscsi_destroy_conn(cls_conn); 1402 iscsi_destroy_conn(cls_conn);
1416 return NULL; 1403 return NULL;
1417} 1404}
@@ -1489,7 +1476,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
1489 session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; 1476 session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
1490 spin_unlock_bh(&session->lock); 1477 spin_unlock_bh(&session->lock);
1491 1478
1492 kfifo_free(conn->xmitqueue);
1493 kfifo_free(conn->immqueue); 1479 kfifo_free(conn->immqueue);
1494 kfifo_free(conn->mgmtqueue); 1480 kfifo_free(conn->mgmtqueue);
1495 1481
@@ -1572,7 +1558,7 @@ static void fail_all_commands(struct iscsi_conn *conn)
1572 struct iscsi_cmd_task *ctask, *tmp; 1558 struct iscsi_cmd_task *ctask, *tmp;
1573 1559
1574 /* flush pending */ 1560 /* flush pending */
1575 while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) { 1561 list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) {
1576 debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, 1562 debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc,
1577 ctask->itt); 1563 ctask->itt);
1578 fail_command(conn, ctask, DID_BUS_BUSY << 16); 1564 fail_command(conn, ctask, DID_BUS_BUSY << 16);