diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
| -rw-r--r-- | drivers/scsi/libiscsi.c | 214 |
1 files changed, 116 insertions, 98 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 7e6e031cc41b..5884cd26d53a 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*)); |
| @@ -275,6 +276,25 @@ out: | |||
| 275 | return rc; | 276 | return rc; |
| 276 | } | 277 | } |
| 277 | 278 | ||
| 279 | static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | ||
| 280 | { | ||
| 281 | struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr; | ||
| 282 | |||
| 283 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | ||
| 284 | conn->tmfrsp_pdus_cnt++; | ||
| 285 | |||
| 286 | if (conn->tmabort_state != TMABORT_INITIAL) | ||
| 287 | return; | ||
| 288 | |||
| 289 | if (tmf->response == ISCSI_TMF_RSP_COMPLETE) | ||
| 290 | conn->tmabort_state = TMABORT_SUCCESS; | ||
| 291 | else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) | ||
| 292 | conn->tmabort_state = TMABORT_NOT_FOUND; | ||
| 293 | else | ||
| 294 | conn->tmabort_state = TMABORT_FAILED; | ||
| 295 | wake_up(&conn->ehwait); | ||
| 296 | } | ||
| 297 | |||
| 278 | /** | 298 | /** |
| 279 | * __iscsi_complete_pdu - complete pdu | 299 | * __iscsi_complete_pdu - complete pdu |
| 280 | * @conn: iscsi conn | 300 | * @conn: iscsi conn |
| @@ -340,6 +360,10 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
| 340 | 360 | ||
| 341 | switch(opcode) { | 361 | switch(opcode) { |
| 342 | case ISCSI_OP_LOGOUT_RSP: | 362 | case ISCSI_OP_LOGOUT_RSP: |
| 363 | if (datalen) { | ||
| 364 | rc = ISCSI_ERR_PROTO; | ||
| 365 | break; | ||
| 366 | } | ||
| 343 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | 367 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; |
| 344 | /* fall through */ | 368 | /* fall through */ |
| 345 | case ISCSI_OP_LOGIN_RSP: | 369 | case ISCSI_OP_LOGIN_RSP: |
| @@ -348,7 +372,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
| 348 | * login related PDU's exp_statsn is handled in | 372 | * login related PDU's exp_statsn is handled in |
| 349 | * userspace | 373 | * userspace |
| 350 | */ | 374 | */ |
| 351 | rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen); | 375 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) |
| 376 | rc = ISCSI_ERR_CONN_FAILED; | ||
| 352 | list_del(&mtask->running); | 377 | list_del(&mtask->running); |
| 353 | if (conn->login_mtask != mtask) | 378 | if (conn->login_mtask != mtask) |
| 354 | __kfifo_put(session->mgmtpool.queue, | 379 | __kfifo_put(session->mgmtpool.queue, |
| @@ -360,25 +385,17 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
| 360 | break; | 385 | break; |
| 361 | } | 386 | } |
| 362 | 387 | ||
| 363 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | 388 | iscsi_tmf_rsp(conn, hdr); |
| 364 | conn->tmfrsp_pdus_cnt++; | ||
| 365 | if (conn->tmabort_state == TMABORT_INITIAL) { | ||
| 366 | conn->tmabort_state = | ||
| 367 | ((struct iscsi_tm_rsp *)hdr)-> | ||
| 368 | response == ISCSI_TMF_RSP_COMPLETE ? | ||
| 369 | TMABORT_SUCCESS:TMABORT_FAILED; | ||
| 370 | /* unblock eh_abort() */ | ||
| 371 | wake_up(&conn->ehwait); | ||
| 372 | } | ||
| 373 | break; | 389 | break; |
| 374 | case ISCSI_OP_NOOP_IN: | 390 | case ISCSI_OP_NOOP_IN: |
| 375 | if (hdr->ttt != ISCSI_RESERVED_TAG) { | 391 | if (hdr->ttt != ISCSI_RESERVED_TAG || datalen) { |
| 376 | rc = ISCSI_ERR_PROTO; | 392 | rc = ISCSI_ERR_PROTO; |
| 377 | break; | 393 | break; |
| 378 | } | 394 | } |
| 379 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | 395 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; |
| 380 | 396 | ||
| 381 | rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen); | 397 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) |
| 398 | rc = ISCSI_ERR_CONN_FAILED; | ||
| 382 | list_del(&mtask->running); | 399 | list_del(&mtask->running); |
| 383 | if (conn->login_mtask != mtask) | 400 | if (conn->login_mtask != mtask) |
| 384 | __kfifo_put(session->mgmtpool.queue, | 401 | __kfifo_put(session->mgmtpool.queue, |
| @@ -391,14 +408,21 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
| 391 | } else if (itt == ISCSI_RESERVED_TAG) { | 408 | } else if (itt == ISCSI_RESERVED_TAG) { |
| 392 | switch(opcode) { | 409 | switch(opcode) { |
| 393 | case ISCSI_OP_NOOP_IN: | 410 | case ISCSI_OP_NOOP_IN: |
| 394 | if (!datalen) { | 411 | if (datalen) { |
| 395 | rc = iscsi_check_assign_cmdsn(session, | ||
| 396 | (struct iscsi_nopin*)hdr); | ||
| 397 | if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) | ||
| 398 | rc = iscsi_recv_pdu(conn->cls_conn, | ||
| 399 | hdr, NULL, 0); | ||
| 400 | } else | ||
| 401 | rc = ISCSI_ERR_PROTO; | 412 | rc = ISCSI_ERR_PROTO; |
| 413 | break; | ||
| 414 | } | ||
| 415 | |||
| 416 | rc = iscsi_check_assign_cmdsn(session, | ||
| 417 | (struct iscsi_nopin*)hdr); | ||
| 418 | if (rc) | ||
| 419 | break; | ||
| 420 | |||
| 421 | if (hdr->ttt == ISCSI_RESERVED_TAG) | ||
| 422 | break; | ||
| 423 | |||
| 424 | if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0)) | ||
| 425 | rc = ISCSI_ERR_CONN_FAILED; | ||
| 402 | break; | 426 | break; |
| 403 | case ISCSI_OP_REJECT: | 427 | case ISCSI_OP_REJECT: |
| 404 | /* we need sth like iscsi_reject_rsp()*/ | 428 | /* we need sth like iscsi_reject_rsp()*/ |
| @@ -568,20 +592,24 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
| 568 | } | 592 | } |
| 569 | 593 | ||
| 570 | /* process command queue */ | 594 | /* process command queue */ |
| 571 | while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, | 595 | spin_lock_bh(&conn->session->lock); |
| 572 | sizeof(void*))) { | 596 | while (!list_empty(&conn->xmitqueue)) { |
| 573 | /* | 597 | /* |
| 574 | * iscsi tcp may readd the task to the xmitqueue to send | 598 | * iscsi tcp may readd the task to the xmitqueue to send |
| 575 | * write data | 599 | * write data |
| 576 | */ | 600 | */ |
| 577 | spin_lock_bh(&conn->session->lock); | 601 | conn->ctask = list_entry(conn->xmitqueue.next, |
| 578 | if (list_empty(&conn->ctask->running)) | 602 | struct iscsi_cmd_task, running); |
| 579 | list_add_tail(&conn->ctask->running, &conn->run_list); | 603 | conn->ctask->state = ISCSI_TASK_RUNNING; |
| 604 | list_move_tail(conn->xmitqueue.next, &conn->run_list); | ||
| 580 | spin_unlock_bh(&conn->session->lock); | 605 | spin_unlock_bh(&conn->session->lock); |
| 606 | |||
| 581 | rc = tt->xmit_cmd_task(conn, conn->ctask); | 607 | rc = tt->xmit_cmd_task(conn, conn->ctask); |
| 582 | if (rc) | 608 | if (rc) |
| 583 | goto again; | 609 | goto again; |
| 610 | spin_lock_bh(&conn->session->lock); | ||
| 584 | } | 611 | } |
| 612 | spin_unlock_bh(&conn->session->lock); | ||
| 585 | /* done with this ctask */ | 613 | /* done with this ctask */ |
| 586 | conn->ctask = NULL; | 614 | conn->ctask = NULL; |
| 587 | 615 | ||
| @@ -691,6 +719,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
| 691 | sc->SCp.phase = session->age; | 719 | sc->SCp.phase = session->age; |
| 692 | sc->SCp.ptr = (char *)ctask; | 720 | sc->SCp.ptr = (char *)ctask; |
| 693 | 721 | ||
| 722 | ctask->state = ISCSI_TASK_PENDING; | ||
| 694 | ctask->mtask = NULL; | 723 | ctask->mtask = NULL; |
| 695 | ctask->conn = conn; | 724 | ctask->conn = conn; |
| 696 | ctask->sc = sc; | 725 | ctask->sc = sc; |
| @@ -700,7 +729,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
| 700 | 729 | ||
| 701 | session->tt->init_cmd_task(ctask); | 730 | session->tt->init_cmd_task(ctask); |
| 702 | 731 | ||
| 703 | __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); | 732 | list_add_tail(&ctask->running, &conn->xmitqueue); |
| 704 | debug_scsi( | 733 | debug_scsi( |
| 705 | "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", | 734 | "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", | 735 | sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", |
| @@ -977,31 +1006,27 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, | |||
| 977 | /* | 1006 | /* |
| 978 | * xmit mutex and session lock must be held | 1007 | * xmit mutex and session lock must be held |
| 979 | */ | 1008 | */ |
| 980 | #define iscsi_remove_task(tasktype) \ | 1009 | static struct iscsi_mgmt_task * |
| 981 | static struct iscsi_##tasktype * \ | 1010 | iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt) |
| 982 | iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt) \ | 1011 | { |
| 983 | { \ | 1012 | int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); |
| 984 | int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); \ | 1013 | struct iscsi_mgmt_task *task; |
| 985 | struct iscsi_##tasktype *task; \ | ||
| 986 | \ | ||
| 987 | debug_scsi("searching %d tasks\n", nr_tasks); \ | ||
| 988 | \ | ||
| 989 | for (i = 0; i < nr_tasks; i++) { \ | ||
| 990 | __kfifo_get(fifo, (void*)&task, sizeof(void*)); \ | ||
| 991 | debug_scsi("check task %u\n", task->itt); \ | ||
| 992 | \ | ||
| 993 | if (task->itt == itt) { \ | ||
| 994 | debug_scsi("matched task\n"); \ | ||
| 995 | return task; \ | ||
| 996 | } \ | ||
| 997 | \ | ||
| 998 | __kfifo_put(fifo, (void*)&task, sizeof(void*)); \ | ||
| 999 | } \ | ||
| 1000 | return NULL; \ | ||
| 1001 | } | ||
| 1002 | 1014 | ||
| 1003 | iscsi_remove_task(mgmt_task); | 1015 | debug_scsi("searching %d tasks\n", nr_tasks); |
| 1004 | iscsi_remove_task(cmd_task); | 1016 | |
| 1017 | for (i = 0; i < nr_tasks; i++) { | ||
| 1018 | __kfifo_get(fifo, (void*)&task, sizeof(void*)); | ||
| 1019 | debug_scsi("check task %u\n", task->itt); | ||
| 1020 | |||
| 1021 | if (task->itt == itt) { | ||
| 1022 | debug_scsi("matched task\n"); | ||
| 1023 | return task; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | __kfifo_put(fifo, (void*)&task, sizeof(void*)); | ||
| 1027 | } | ||
| 1028 | return NULL; | ||
| 1029 | } | ||
| 1005 | 1030 | ||
| 1006 | static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) | 1031 | static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) |
| 1007 | { | 1032 | { |
| @@ -1027,12 +1052,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
| 1027 | { | 1052 | { |
| 1028 | struct scsi_cmnd *sc; | 1053 | struct scsi_cmnd *sc; |
| 1029 | 1054 | ||
| 1030 | conn->session->tt->cleanup_cmd_task(conn, ctask); | ||
| 1031 | iscsi_ctask_mtask_cleanup(ctask); | ||
| 1032 | |||
| 1033 | sc = ctask->sc; | 1055 | sc = ctask->sc; |
| 1034 | if (!sc) | 1056 | if (!sc) |
| 1035 | return; | 1057 | return; |
| 1058 | |||
| 1059 | conn->session->tt->cleanup_cmd_task(conn, ctask); | ||
| 1060 | iscsi_ctask_mtask_cleanup(ctask); | ||
| 1061 | |||
| 1036 | sc->result = err; | 1062 | sc->result = err; |
| 1037 | sc->resid = sc->request_bufflen; | 1063 | sc->resid = sc->request_bufflen; |
| 1038 | iscsi_complete_command(conn->session, ctask); | 1064 | iscsi_complete_command(conn->session, ctask); |
| @@ -1043,7 +1069,6 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
| 1043 | struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; | 1069 | struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; |
| 1044 | struct iscsi_conn *conn = ctask->conn; | 1070 | struct iscsi_conn *conn = ctask->conn; |
| 1045 | struct iscsi_session *session = conn->session; | 1071 | struct iscsi_session *session = conn->session; |
| 1046 | struct iscsi_cmd_task *pending_ctask; | ||
| 1047 | int rc; | 1072 | int rc; |
| 1048 | 1073 | ||
| 1049 | conn->eh_abort_cnt++; | 1074 | conn->eh_abort_cnt++; |
| @@ -1061,8 +1086,11 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
| 1061 | goto failed; | 1086 | goto failed; |
| 1062 | 1087 | ||
| 1063 | /* ctask completed before time out */ | 1088 | /* ctask completed before time out */ |
| 1064 | if (!ctask->sc) | 1089 | if (!ctask->sc) { |
| 1065 | goto success; | 1090 | spin_unlock_bh(&session->lock); |
| 1091 | debug_scsi("sc completed while abort in progress\n"); | ||
| 1092 | goto success_rel_mutex; | ||
| 1093 | } | ||
| 1066 | 1094 | ||
| 1067 | /* what should we do here ? */ | 1095 | /* what should we do here ? */ |
| 1068 | if (conn->ctask == ctask) { | 1096 | if (conn->ctask == ctask) { |
| @@ -1071,17 +1099,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
| 1071 | goto failed; | 1099 | goto failed; |
| 1072 | } | 1100 | } |
| 1073 | 1101 | ||
| 1074 | /* check for the easy pending cmd abort */ | 1102 | if (ctask->state == ISCSI_TASK_PENDING) |
| 1075 | pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt); | 1103 | goto success_cleanup; |
| 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 | 1104 | ||
| 1086 | conn->tmabort_state = TMABORT_INITIAL; | 1105 | conn->tmabort_state = TMABORT_INITIAL; |
| 1087 | 1106 | ||
| @@ -1089,25 +1108,31 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
| 1089 | rc = iscsi_exec_abort_task(sc, ctask); | 1108 | rc = iscsi_exec_abort_task(sc, ctask); |
| 1090 | spin_lock_bh(&session->lock); | 1109 | spin_lock_bh(&session->lock); |
| 1091 | 1110 | ||
| 1092 | iscsi_ctask_mtask_cleanup(ctask); | ||
| 1093 | if (rc || sc->SCp.phase != session->age || | 1111 | if (rc || sc->SCp.phase != session->age || |
| 1094 | session->state != ISCSI_STATE_LOGGED_IN) | 1112 | session->state != ISCSI_STATE_LOGGED_IN) |
| 1095 | goto failed; | 1113 | goto failed; |
| 1114 | iscsi_ctask_mtask_cleanup(ctask); | ||
| 1096 | 1115 | ||
| 1097 | /* ctask completed before tmf abort response */ | 1116 | switch (conn->tmabort_state) { |
| 1098 | if (!ctask->sc) { | 1117 | case TMABORT_SUCCESS: |
| 1099 | debug_scsi("sc completed while abort in progress\n"); | 1118 | goto success_cleanup; |
| 1100 | goto success; | 1119 | case TMABORT_NOT_FOUND: |
| 1101 | } | 1120 | if (!ctask->sc) { |
| 1102 | 1121 | /* ctask completed before tmf abort response */ | |
| 1103 | if (conn->tmabort_state != TMABORT_SUCCESS) { | 1122 | spin_unlock_bh(&session->lock); |
| 1123 | debug_scsi("sc completed while abort in progress\n"); | ||
| 1124 | goto success_rel_mutex; | ||
| 1125 | } | ||
| 1126 | /* fall through */ | ||
| 1127 | default: | ||
| 1128 | /* timedout or failed */ | ||
| 1104 | spin_unlock_bh(&session->lock); | 1129 | spin_unlock_bh(&session->lock); |
| 1105 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 1130 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
| 1106 | spin_lock_bh(&session->lock); | 1131 | spin_lock_bh(&session->lock); |
| 1107 | goto failed; | 1132 | goto failed; |
| 1108 | } | 1133 | } |
| 1109 | 1134 | ||
| 1110 | success: | 1135 | success_cleanup: |
| 1111 | debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); | 1136 | debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); |
| 1112 | spin_unlock_bh(&session->lock); | 1137 | spin_unlock_bh(&session->lock); |
| 1113 | 1138 | ||
| @@ -1121,6 +1146,7 @@ success: | |||
| 1121 | spin_unlock(&session->lock); | 1146 | spin_unlock(&session->lock); |
| 1122 | write_unlock_bh(conn->recv_lock); | 1147 | write_unlock_bh(conn->recv_lock); |
| 1123 | 1148 | ||
| 1149 | success_rel_mutex: | ||
| 1124 | mutex_unlock(&conn->xmitmutex); | 1150 | mutex_unlock(&conn->xmitmutex); |
| 1125 | return SUCCESS; | 1151 | return SUCCESS; |
| 1126 | 1152 | ||
| @@ -1263,6 +1289,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, | |||
| 1263 | if (cmd_task_size) | 1289 | if (cmd_task_size) |
| 1264 | ctask->dd_data = &ctask[1]; | 1290 | ctask->dd_data = &ctask[1]; |
| 1265 | ctask->itt = cmd_i; | 1291 | ctask->itt = cmd_i; |
| 1292 | INIT_LIST_HEAD(&ctask->running); | ||
| 1266 | } | 1293 | } |
| 1267 | 1294 | ||
| 1268 | spin_lock_init(&session->lock); | 1295 | spin_lock_init(&session->lock); |
| @@ -1282,6 +1309,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, | |||
| 1282 | if (mgmt_task_size) | 1309 | if (mgmt_task_size) |
| 1283 | mtask->dd_data = &mtask[1]; | 1310 | mtask->dd_data = &mtask[1]; |
| 1284 | mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; | 1311 | mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; |
| 1312 | INIT_LIST_HEAD(&mtask->running); | ||
| 1285 | } | 1313 | } |
| 1286 | 1314 | ||
| 1287 | if (scsi_add_host(shost, NULL)) | 1315 | if (scsi_add_host(shost, NULL)) |
| @@ -1322,15 +1350,18 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) | |||
| 1322 | { | 1350 | { |
| 1323 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | 1351 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); |
| 1324 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); | 1352 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); |
| 1353 | struct module *owner = cls_session->transport->owner; | ||
| 1325 | 1354 | ||
| 1326 | scsi_remove_host(shost); | 1355 | scsi_remove_host(shost); |
| 1327 | 1356 | ||
| 1328 | iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); | 1357 | iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); |
| 1329 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); | 1358 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); |
| 1330 | 1359 | ||
| 1360 | kfree(session->targetname); | ||
| 1361 | |||
| 1331 | iscsi_destroy_session(cls_session); | 1362 | iscsi_destroy_session(cls_session); |
| 1332 | scsi_host_put(shost); | 1363 | scsi_host_put(shost); |
| 1333 | module_put(cls_session->transport->owner); | 1364 | module_put(owner); |
| 1334 | } | 1365 | } |
| 1335 | EXPORT_SYMBOL_GPL(iscsi_session_teardown); | 1366 | EXPORT_SYMBOL_GPL(iscsi_session_teardown); |
| 1336 | 1367 | ||
| @@ -1361,12 +1392,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
| 1361 | conn->tmabort_state = TMABORT_INITIAL; | 1392 | conn->tmabort_state = TMABORT_INITIAL; |
| 1362 | INIT_LIST_HEAD(&conn->run_list); | 1393 | INIT_LIST_HEAD(&conn->run_list); |
| 1363 | INIT_LIST_HEAD(&conn->mgmt_run_list); | 1394 | INIT_LIST_HEAD(&conn->mgmt_run_list); |
| 1364 | 1395 | 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 | 1396 | ||
| 1371 | /* initialize general immediate & non-immediate PDU commands queue */ | 1397 | /* initialize general immediate & non-immediate PDU commands queue */ |
| 1372 | conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), | 1398 | conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), |
| @@ -1394,7 +1420,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
| 1394 | data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); | 1420 | data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); |
| 1395 | if (!data) | 1421 | if (!data) |
| 1396 | goto login_mtask_data_alloc_fail; | 1422 | goto login_mtask_data_alloc_fail; |
| 1397 | conn->login_mtask->data = data; | 1423 | conn->login_mtask->data = conn->data = data; |
| 1398 | 1424 | ||
| 1399 | init_timer(&conn->tmabort_timer); | 1425 | init_timer(&conn->tmabort_timer); |
| 1400 | mutex_init(&conn->xmitmutex); | 1426 | mutex_init(&conn->xmitmutex); |
| @@ -1410,8 +1436,6 @@ login_mtask_alloc_fail: | |||
| 1410 | mgmtqueue_alloc_fail: | 1436 | mgmtqueue_alloc_fail: |
| 1411 | kfifo_free(conn->immqueue); | 1437 | kfifo_free(conn->immqueue); |
| 1412 | immqueue_alloc_fail: | 1438 | immqueue_alloc_fail: |
| 1413 | kfifo_free(conn->xmitqueue); | ||
| 1414 | xmitqueue_alloc_fail: | ||
| 1415 | iscsi_destroy_conn(cls_conn); | 1439 | iscsi_destroy_conn(cls_conn); |
| 1416 | return NULL; | 1440 | return NULL; |
| 1417 | } | 1441 | } |
| @@ -1432,12 +1456,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
| 1432 | 1456 | ||
| 1433 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1457 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
| 1434 | mutex_lock(&conn->xmitmutex); | 1458 | mutex_lock(&conn->xmitmutex); |
| 1435 | if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) { | ||
| 1436 | if (session->tt->suspend_conn_recv) | ||
| 1437 | session->tt->suspend_conn_recv(conn); | ||
| 1438 | |||
| 1439 | session->tt->terminate_conn(conn); | ||
| 1440 | } | ||
| 1441 | 1459 | ||
| 1442 | spin_lock_bh(&session->lock); | 1460 | spin_lock_bh(&session->lock); |
| 1443 | conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; | 1461 | conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; |
| @@ -1474,7 +1492,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
| 1474 | } | 1492 | } |
| 1475 | 1493 | ||
| 1476 | spin_lock_bh(&session->lock); | 1494 | spin_lock_bh(&session->lock); |
| 1477 | kfree(conn->login_mtask->data); | 1495 | kfree(conn->data); |
| 1496 | kfree(conn->persistent_address); | ||
| 1478 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, | 1497 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, |
| 1479 | sizeof(void*)); | 1498 | sizeof(void*)); |
| 1480 | list_del(&conn->item); | 1499 | list_del(&conn->item); |
| @@ -1489,7 +1508,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
| 1489 | session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; | 1508 | session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; |
| 1490 | spin_unlock_bh(&session->lock); | 1509 | spin_unlock_bh(&session->lock); |
| 1491 | 1510 | ||
| 1492 | kfifo_free(conn->xmitqueue); | ||
| 1493 | kfifo_free(conn->immqueue); | 1511 | kfifo_free(conn->immqueue); |
| 1494 | kfifo_free(conn->mgmtqueue); | 1512 | kfifo_free(conn->mgmtqueue); |
| 1495 | 1513 | ||
| @@ -1572,7 +1590,7 @@ static void fail_all_commands(struct iscsi_conn *conn) | |||
| 1572 | struct iscsi_cmd_task *ctask, *tmp; | 1590 | struct iscsi_cmd_task *ctask, *tmp; |
| 1573 | 1591 | ||
| 1574 | /* flush pending */ | 1592 | /* flush pending */ |
| 1575 | while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) { | 1593 | list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { |
| 1576 | debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, | 1594 | debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, |
| 1577 | ctask->itt); | 1595 | ctask->itt); |
| 1578 | fail_command(conn, ctask, DID_BUS_BUSY << 16); | 1596 | fail_command(conn, ctask, DID_BUS_BUSY << 16); |
| @@ -1615,8 +1633,9 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
| 1615 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1633 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
| 1616 | spin_unlock_bh(&session->lock); | 1634 | spin_unlock_bh(&session->lock); |
| 1617 | 1635 | ||
| 1618 | if (session->tt->suspend_conn_recv) | 1636 | write_lock_bh(conn->recv_lock); |
| 1619 | session->tt->suspend_conn_recv(conn); | 1637 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); |
| 1638 | write_unlock_bh(conn->recv_lock); | ||
| 1620 | 1639 | ||
| 1621 | mutex_lock(&conn->xmitmutex); | 1640 | mutex_lock(&conn->xmitmutex); |
| 1622 | /* | 1641 | /* |
| @@ -1635,7 +1654,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
| 1635 | } | 1654 | } |
| 1636 | } | 1655 | } |
| 1637 | 1656 | ||
| 1638 | session->tt->terminate_conn(conn); | ||
| 1639 | /* | 1657 | /* |
| 1640 | * flush queues. | 1658 | * flush queues. |
| 1641 | */ | 1659 | */ |
