diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2006-07-24 16:47:15 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-07-28 12:47:40 -0400 |
commit | b6c395ed0387c824ddf125d3b74b576a2575c149 (patch) | |
tree | 76ca5cd982063335088384622e5033401bbc5057 | |
parent | d82967c70658a408ea6cae5dc989ba8b2c0999e1 (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>
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 45 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 90 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 10 |
3 files changed, 68 insertions, 77 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 | */ |
187 | static void | 187 | static void |
188 | __iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 188 | iscsi_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) | |||
745 | done: | 754 | done: |
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 | } |
1637 | solicit_again: | 1647 | solicit_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 | ||
2004 | static void | 2014 | static void |
2005 | iscsi_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 | |||
2018 | static void | ||
2019 | iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn) | 2015 | iscsi_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, |
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) \ | 986 | static struct iscsi_mgmt_task * |
981 | static struct iscsi_##tasktype * \ | 987 | iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt) |
982 | iscsi_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 | ||
1003 | iscsi_remove_task(mgmt_task); | 1003 | __kfifo_put(fifo, (void*)&task, sizeof(void*)); |
1004 | iscsi_remove_task(cmd_task); | 1004 | } |
1005 | return NULL; | ||
1006 | } | ||
1005 | 1007 | ||
1006 | static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) | 1008 | static 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: | |||
1410 | mgmtqueue_alloc_fail: | 1399 | mgmtqueue_alloc_fail: |
1411 | kfifo_free(conn->immqueue); | 1400 | kfifo_free(conn->immqueue); |
1412 | immqueue_alloc_fail: | 1401 | immqueue_alloc_fail: |
1413 | kfifo_free(conn->xmitqueue); | ||
1414 | xmitqueue_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); |
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index ba2760802ded..e71d6e96eca6 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h | |||
@@ -83,6 +83,12 @@ struct iscsi_mgmt_task { | |||
83 | struct list_head running; | 83 | struct list_head running; |
84 | }; | 84 | }; |
85 | 85 | ||
86 | enum { | ||
87 | ISCSI_TASK_COMPLETED, | ||
88 | ISCSI_TASK_PENDING, | ||
89 | ISCSI_TASK_RUNNING, | ||
90 | }; | ||
91 | |||
86 | struct iscsi_cmd_task { | 92 | struct iscsi_cmd_task { |
87 | /* | 93 | /* |
88 | * Becuae LLDs allocate their hdr differently, this is a pointer to | 94 | * Becuae LLDs allocate their hdr differently, this is a pointer to |
@@ -101,6 +107,8 @@ struct iscsi_cmd_task { | |||
101 | struct iscsi_conn *conn; /* used connection */ | 107 | struct iscsi_conn *conn; /* used connection */ |
102 | struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ | 108 | struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ |
103 | 109 | ||
110 | /* state set/tested under session->lock */ | ||
111 | int state; | ||
104 | struct list_head running; /* running cmd list */ | 112 | struct list_head running; /* running cmd list */ |
105 | void *dd_data; /* driver/transport data */ | 113 | void *dd_data; /* driver/transport data */ |
106 | }; | 114 | }; |
@@ -134,7 +142,7 @@ struct iscsi_conn { | |||
134 | struct kfifo *immqueue; /* immediate xmit queue */ | 142 | struct kfifo *immqueue; /* immediate xmit queue */ |
135 | struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ | 143 | struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ |
136 | struct list_head mgmt_run_list; /* list of control tasks */ | 144 | struct list_head mgmt_run_list; /* list of control tasks */ |
137 | struct kfifo *xmitqueue; /* data-path cmd queue */ | 145 | struct list_head xmitqueue; /* data-path cmd queue */ |
138 | struct list_head run_list; /* list of cmds in progress */ | 146 | struct list_head run_list; /* list of cmds in progress */ |
139 | struct work_struct xmitwork; /* per-conn. xmit workqueue */ | 147 | struct work_struct xmitwork; /* per-conn. xmit workqueue */ |
140 | /* | 148 | /* |