diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 225 |
1 files changed, 116 insertions, 109 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c648bd328a21..a9d7e520e551 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -109,7 +109,7 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | |||
109 | * if the window closed with IO queued, then kick the | 109 | * if the window closed with IO queued, then kick the |
110 | * xmit thread | 110 | * xmit thread |
111 | */ | 111 | */ |
112 | if (!list_empty(&session->leadconn->xmitqueue) || | 112 | if (!list_empty(&session->leadconn->cmdqueue) || |
113 | !list_empty(&session->leadconn->mgmtqueue)) { | 113 | !list_empty(&session->leadconn->mgmtqueue)) { |
114 | if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD)) | 114 | if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD)) |
115 | iscsi_conn_queue_work(session->leadconn); | 115 | iscsi_conn_queue_work(session->leadconn); |
@@ -366,7 +366,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
366 | return -EIO; | 366 | return -EIO; |
367 | 367 | ||
368 | task->state = ISCSI_TASK_RUNNING; | 368 | task->state = ISCSI_TASK_RUNNING; |
369 | list_move_tail(&task->running, &conn->run_list); | ||
370 | 369 | ||
371 | conn->scsicmd_pdus_cnt++; | 370 | conn->scsicmd_pdus_cnt++; |
372 | ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x " | 371 | ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x " |
@@ -382,26 +381,23 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
382 | } | 381 | } |
383 | 382 | ||
384 | /** | 383 | /** |
385 | * iscsi_complete_command - finish a task | 384 | * iscsi_free_task - free a task |
386 | * @task: iscsi cmd task | 385 | * @task: iscsi cmd task |
387 | * | 386 | * |
388 | * Must be called with session lock. | 387 | * Must be called with session lock. |
389 | * This function returns the scsi command to scsi-ml or cleans | 388 | * This function returns the scsi command to scsi-ml or cleans |
390 | * up mgmt tasks then returns the task to the pool. | 389 | * up mgmt tasks then returns the task to the pool. |
391 | */ | 390 | */ |
392 | static void iscsi_complete_command(struct iscsi_task *task) | 391 | static void iscsi_free_task(struct iscsi_task *task) |
393 | { | 392 | { |
394 | struct iscsi_conn *conn = task->conn; | 393 | struct iscsi_conn *conn = task->conn; |
395 | struct iscsi_session *session = conn->session; | 394 | struct iscsi_session *session = conn->session; |
396 | struct scsi_cmnd *sc = task->sc; | 395 | struct scsi_cmnd *sc = task->sc; |
397 | 396 | ||
398 | session->tt->cleanup_task(task); | 397 | session->tt->cleanup_task(task); |
399 | list_del_init(&task->running); | 398 | task->state = ISCSI_TASK_FREE; |
400 | task->state = ISCSI_TASK_COMPLETED; | ||
401 | task->sc = NULL; | 399 | task->sc = NULL; |
402 | 400 | ||
403 | if (conn->task == task) | ||
404 | conn->task = NULL; | ||
405 | /* | 401 | /* |
406 | * login task is preallocated so do not free | 402 | * login task is preallocated so do not free |
407 | */ | 403 | */ |
@@ -410,9 +406,6 @@ static void iscsi_complete_command(struct iscsi_task *task) | |||
410 | 406 | ||
411 | __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*)); | 407 | __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*)); |
412 | 408 | ||
413 | if (conn->ping_task == task) | ||
414 | conn->ping_task = NULL; | ||
415 | |||
416 | if (sc) { | 409 | if (sc) { |
417 | task->sc = NULL; | 410 | task->sc = NULL; |
418 | /* SCSI eh reuses commands to verify us */ | 411 | /* SCSI eh reuses commands to verify us */ |
@@ -435,7 +428,7 @@ EXPORT_SYMBOL_GPL(__iscsi_get_task); | |||
435 | static void __iscsi_put_task(struct iscsi_task *task) | 428 | static void __iscsi_put_task(struct iscsi_task *task) |
436 | { | 429 | { |
437 | if (atomic_dec_and_test(&task->refcount)) | 430 | if (atomic_dec_and_test(&task->refcount)) |
438 | iscsi_complete_command(task); | 431 | iscsi_free_task(task); |
439 | } | 432 | } |
440 | 433 | ||
441 | void iscsi_put_task(struct iscsi_task *task) | 434 | void iscsi_put_task(struct iscsi_task *task) |
@@ -448,14 +441,50 @@ void iscsi_put_task(struct iscsi_task *task) | |||
448 | } | 441 | } |
449 | EXPORT_SYMBOL_GPL(iscsi_put_task); | 442 | EXPORT_SYMBOL_GPL(iscsi_put_task); |
450 | 443 | ||
444 | /** | ||
445 | * iscsi_complete_task - finish a task | ||
446 | * @task: iscsi cmd task | ||
447 | * | ||
448 | * Must be called with session lock. | ||
449 | */ | ||
450 | static void iscsi_complete_task(struct iscsi_task *task) | ||
451 | { | ||
452 | struct iscsi_conn *conn = task->conn; | ||
453 | |||
454 | if (task->state == ISCSI_TASK_COMPLETED) | ||
455 | return; | ||
456 | WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); | ||
457 | |||
458 | task->state = ISCSI_TASK_COMPLETED; | ||
459 | |||
460 | if (!list_empty(&task->running)) | ||
461 | list_del_init(&task->running); | ||
462 | |||
463 | if (conn->task == task) | ||
464 | conn->task = NULL; | ||
465 | |||
466 | if (conn->ping_task == task) | ||
467 | conn->ping_task = NULL; | ||
468 | |||
469 | /* release get from queueing */ | ||
470 | __iscsi_put_task(task); | ||
471 | } | ||
472 | |||
451 | /* | 473 | /* |
452 | * session lock must be held | 474 | * session lock must be held and if not called for a task that is |
475 | * still pending or from the xmit thread, then xmit thread must | ||
476 | * be suspended. | ||
453 | */ | 477 | */ |
454 | static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task, | 478 | static void fail_scsi_task(struct iscsi_task *task, int err) |
455 | int err) | ||
456 | { | 479 | { |
480 | struct iscsi_conn *conn = task->conn; | ||
457 | struct scsi_cmnd *sc; | 481 | struct scsi_cmnd *sc; |
458 | 482 | ||
483 | /* | ||
484 | * if a command completes and we get a successful tmf response | ||
485 | * we will hit this because the scsi eh abort code does not take | ||
486 | * a ref to the task. | ||
487 | */ | ||
459 | sc = task->sc; | 488 | sc = task->sc; |
460 | if (!sc) | 489 | if (!sc) |
461 | return; | 490 | return; |
@@ -475,10 +504,7 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task, | |||
475 | scsi_in(sc)->resid = scsi_in(sc)->length; | 504 | scsi_in(sc)->resid = scsi_in(sc)->length; |
476 | } | 505 | } |
477 | 506 | ||
478 | if (conn->task == task) | 507 | iscsi_complete_task(task); |
479 | conn->task = NULL; | ||
480 | /* release ref from queuecommand */ | ||
481 | __iscsi_put_task(task); | ||
482 | } | 508 | } |
483 | 509 | ||
484 | static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | 510 | static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, |
@@ -518,7 +544,6 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | |||
518 | session->state = ISCSI_STATE_LOGGING_OUT; | 544 | session->state = ISCSI_STATE_LOGGING_OUT; |
519 | 545 | ||
520 | task->state = ISCSI_TASK_RUNNING; | 546 | task->state = ISCSI_TASK_RUNNING; |
521 | list_move_tail(&task->running, &conn->mgmt_run_list); | ||
522 | ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x " | 547 | ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x " |
523 | "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK, | 548 | "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK, |
524 | hdr->itt, task->data_count); | 549 | hdr->itt, task->data_count); |
@@ -564,6 +589,8 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
564 | atomic_set(&task->refcount, 1); | 589 | atomic_set(&task->refcount, 1); |
565 | task->conn = conn; | 590 | task->conn = conn; |
566 | task->sc = NULL; | 591 | task->sc = NULL; |
592 | INIT_LIST_HEAD(&task->running); | ||
593 | task->state = ISCSI_TASK_PENDING; | ||
567 | 594 | ||
568 | if (data_size) { | 595 | if (data_size) { |
569 | memcpy(task->data, data, data_size); | 596 | memcpy(task->data, data, data_size); |
@@ -575,7 +602,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
575 | if (conn->session->tt->alloc_pdu(task, hdr->opcode)) { | 602 | if (conn->session->tt->alloc_pdu(task, hdr->opcode)) { |
576 | iscsi_conn_printk(KERN_ERR, conn, "Could not allocate " | 603 | iscsi_conn_printk(KERN_ERR, conn, "Could not allocate " |
577 | "pdu for mgmt task.\n"); | 604 | "pdu for mgmt task.\n"); |
578 | goto requeue_task; | 605 | goto free_task; |
579 | } | 606 | } |
580 | } | 607 | } |
581 | 608 | ||
@@ -591,30 +618,22 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
591 | task->conn->session->age); | 618 | task->conn->session->age); |
592 | } | 619 | } |
593 | 620 | ||
594 | INIT_LIST_HEAD(&task->running); | ||
595 | list_add_tail(&task->running, &conn->mgmtqueue); | ||
596 | |||
597 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | 621 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { |
598 | if (iscsi_prep_mgmt_task(conn, task)) | 622 | if (iscsi_prep_mgmt_task(conn, task)) |
599 | goto free_task; | 623 | goto free_task; |
600 | 624 | ||
601 | if (session->tt->xmit_task(task)) | 625 | if (session->tt->xmit_task(task)) |
602 | goto free_task; | 626 | goto free_task; |
603 | 627 | } else { | |
604 | } else | 628 | list_add_tail(&task->running, &conn->mgmtqueue); |
605 | iscsi_conn_queue_work(conn); | 629 | iscsi_conn_queue_work(conn); |
630 | } | ||
606 | 631 | ||
607 | return task; | 632 | return task; |
608 | 633 | ||
609 | free_task: | 634 | free_task: |
610 | __iscsi_put_task(task); | 635 | __iscsi_put_task(task); |
611 | return NULL; | 636 | return NULL; |
612 | |||
613 | requeue_task: | ||
614 | if (task != conn->login_task) | ||
615 | __kfifo_put(session->cmdpool.queue, (void*)&task, | ||
616 | sizeof(void*)); | ||
617 | return NULL; | ||
618 | } | 637 | } |
619 | 638 | ||
620 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, | 639 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, |
@@ -709,11 +728,10 @@ invalid_datalen: | |||
709 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; | 728 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; |
710 | } | 729 | } |
711 | out: | 730 | out: |
712 | ISCSI_DBG_SESSION(session, "done [sc %p res %d itt 0x%x]\n", | 731 | ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]\n", |
713 | sc, sc->result, task->itt); | 732 | sc, sc->result, task->itt); |
714 | conn->scsirsp_pdus_cnt++; | 733 | conn->scsirsp_pdus_cnt++; |
715 | 734 | iscsi_complete_task(task); | |
716 | __iscsi_put_task(task); | ||
717 | } | 735 | } |
718 | 736 | ||
719 | /** | 737 | /** |
@@ -747,8 +765,11 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
747 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; | 765 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; |
748 | } | 766 | } |
749 | 767 | ||
768 | ISCSI_DBG_SESSION(conn->session, "data in with status done " | ||
769 | "[sc %p res %d itt 0x%x]\n", | ||
770 | sc, sc->result, task->itt); | ||
750 | conn->scsirsp_pdus_cnt++; | 771 | conn->scsirsp_pdus_cnt++; |
751 | __iscsi_put_task(task); | 772 | iscsi_complete_task(task); |
752 | } | 773 | } |
753 | 774 | ||
754 | static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | 775 | static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) |
@@ -969,7 +990,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
969 | } | 990 | } |
970 | 991 | ||
971 | iscsi_tmf_rsp(conn, hdr); | 992 | iscsi_tmf_rsp(conn, hdr); |
972 | __iscsi_put_task(task); | 993 | iscsi_complete_task(task); |
973 | break; | 994 | break; |
974 | case ISCSI_OP_NOOP_IN: | 995 | case ISCSI_OP_NOOP_IN: |
975 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | 996 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); |
@@ -987,7 +1008,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
987 | goto recv_pdu; | 1008 | goto recv_pdu; |
988 | 1009 | ||
989 | mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); | 1010 | mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); |
990 | __iscsi_put_task(task); | 1011 | iscsi_complete_task(task); |
991 | break; | 1012 | break; |
992 | default: | 1013 | default: |
993 | rc = ISCSI_ERR_BAD_OPCODE; | 1014 | rc = ISCSI_ERR_BAD_OPCODE; |
@@ -999,7 +1020,7 @@ out: | |||
999 | recv_pdu: | 1020 | recv_pdu: |
1000 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) | 1021 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) |
1001 | rc = ISCSI_ERR_CONN_FAILED; | 1022 | rc = ISCSI_ERR_CONN_FAILED; |
1002 | __iscsi_put_task(task); | 1023 | iscsi_complete_task(task); |
1003 | return rc; | 1024 | return rc; |
1004 | } | 1025 | } |
1005 | EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); | 1026 | EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); |
@@ -1176,7 +1197,12 @@ void iscsi_requeue_task(struct iscsi_task *task) | |||
1176 | { | 1197 | { |
1177 | struct iscsi_conn *conn = task->conn; | 1198 | struct iscsi_conn *conn = task->conn; |
1178 | 1199 | ||
1179 | list_move_tail(&task->running, &conn->requeue); | 1200 | /* |
1201 | * this may be on the requeue list already if the xmit_task callout | ||
1202 | * is handling the r2ts while we are adding new ones | ||
1203 | */ | ||
1204 | if (list_empty(&task->running)) | ||
1205 | list_add_tail(&task->running, &conn->requeue); | ||
1180 | iscsi_conn_queue_work(conn); | 1206 | iscsi_conn_queue_work(conn); |
1181 | } | 1207 | } |
1182 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); | 1208 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); |
@@ -1216,6 +1242,7 @@ check_mgmt: | |||
1216 | while (!list_empty(&conn->mgmtqueue)) { | 1242 | while (!list_empty(&conn->mgmtqueue)) { |
1217 | conn->task = list_entry(conn->mgmtqueue.next, | 1243 | conn->task = list_entry(conn->mgmtqueue.next, |
1218 | struct iscsi_task, running); | 1244 | struct iscsi_task, running); |
1245 | list_del_init(&conn->task->running); | ||
1219 | if (iscsi_prep_mgmt_task(conn, conn->task)) { | 1246 | if (iscsi_prep_mgmt_task(conn, conn->task)) { |
1220 | __iscsi_put_task(conn->task); | 1247 | __iscsi_put_task(conn->task); |
1221 | conn->task = NULL; | 1248 | conn->task = NULL; |
@@ -1227,23 +1254,26 @@ check_mgmt: | |||
1227 | } | 1254 | } |
1228 | 1255 | ||
1229 | /* process pending command queue */ | 1256 | /* process pending command queue */ |
1230 | while (!list_empty(&conn->xmitqueue)) { | 1257 | while (!list_empty(&conn->cmdqueue)) { |
1231 | if (conn->tmf_state == TMF_QUEUED) | 1258 | if (conn->tmf_state == TMF_QUEUED) |
1232 | break; | 1259 | break; |
1233 | 1260 | ||
1234 | conn->task = list_entry(conn->xmitqueue.next, | 1261 | conn->task = list_entry(conn->cmdqueue.next, |
1235 | struct iscsi_task, running); | 1262 | struct iscsi_task, running); |
1263 | list_del_init(&conn->task->running); | ||
1236 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { | 1264 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { |
1237 | fail_command(conn, conn->task, DID_IMM_RETRY << 16); | 1265 | fail_scsi_task(conn->task, DID_IMM_RETRY << 16); |
1238 | continue; | 1266 | continue; |
1239 | } | 1267 | } |
1240 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); | 1268 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); |
1241 | if (rc) { | 1269 | if (rc) { |
1242 | if (rc == -ENOMEM) { | 1270 | if (rc == -ENOMEM) { |
1271 | list_add_tail(&conn->task->running, | ||
1272 | &conn->cmdqueue); | ||
1243 | conn->task = NULL; | 1273 | conn->task = NULL; |
1244 | goto again; | 1274 | goto again; |
1245 | } else | 1275 | } else |
1246 | fail_command(conn, conn->task, DID_ABORT << 16); | 1276 | fail_scsi_task(conn->task, DID_ABORT << 16); |
1247 | continue; | 1277 | continue; |
1248 | } | 1278 | } |
1249 | rc = iscsi_xmit_task(conn); | 1279 | rc = iscsi_xmit_task(conn); |
@@ -1270,8 +1300,8 @@ check_mgmt: | |||
1270 | 1300 | ||
1271 | conn->task = list_entry(conn->requeue.next, | 1301 | conn->task = list_entry(conn->requeue.next, |
1272 | struct iscsi_task, running); | 1302 | struct iscsi_task, running); |
1303 | list_del_init(&conn->task->running); | ||
1273 | conn->task->state = ISCSI_TASK_RUNNING; | 1304 | conn->task->state = ISCSI_TASK_RUNNING; |
1274 | list_move_tail(conn->requeue.next, &conn->run_list); | ||
1275 | rc = iscsi_xmit_task(conn); | 1305 | rc = iscsi_xmit_task(conn); |
1276 | if (rc) | 1306 | if (rc) |
1277 | goto again; | 1307 | goto again; |
@@ -1412,7 +1442,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1412 | reason = FAILURE_OOM; | 1442 | reason = FAILURE_OOM; |
1413 | goto reject; | 1443 | goto reject; |
1414 | } | 1444 | } |
1415 | list_add_tail(&task->running, &conn->xmitqueue); | ||
1416 | 1445 | ||
1417 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | 1446 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { |
1418 | reason = iscsi_prep_scsi_cmd_pdu(task); | 1447 | reason = iscsi_prep_scsi_cmd_pdu(task); |
@@ -1429,8 +1458,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1429 | reason = FAILURE_SESSION_NOT_READY; | 1458 | reason = FAILURE_SESSION_NOT_READY; |
1430 | goto prepd_reject; | 1459 | goto prepd_reject; |
1431 | } | 1460 | } |
1432 | } else | 1461 | } else { |
1462 | list_add_tail(&task->running, &conn->cmdqueue); | ||
1433 | iscsi_conn_queue_work(conn); | 1463 | iscsi_conn_queue_work(conn); |
1464 | } | ||
1434 | 1465 | ||
1435 | session->queued_cmdsn++; | 1466 | session->queued_cmdsn++; |
1436 | spin_unlock(&session->lock); | 1467 | spin_unlock(&session->lock); |
@@ -1439,7 +1470,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1439 | 1470 | ||
1440 | prepd_reject: | 1471 | prepd_reject: |
1441 | sc->scsi_done = NULL; | 1472 | sc->scsi_done = NULL; |
1442 | iscsi_complete_command(task); | 1473 | iscsi_complete_task(task); |
1443 | reject: | 1474 | reject: |
1444 | spin_unlock(&session->lock); | 1475 | spin_unlock(&session->lock); |
1445 | ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", | 1476 | ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", |
@@ -1449,7 +1480,7 @@ reject: | |||
1449 | 1480 | ||
1450 | prepd_fault: | 1481 | prepd_fault: |
1451 | sc->scsi_done = NULL; | 1482 | sc->scsi_done = NULL; |
1452 | iscsi_complete_command(task); | 1483 | iscsi_complete_task(task); |
1453 | fault: | 1484 | fault: |
1454 | spin_unlock(&session->lock); | 1485 | spin_unlock(&session->lock); |
1455 | ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", | 1486 | ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", |
@@ -1618,44 +1649,24 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1618 | * Fail commands. session lock held and recv side suspended and xmit | 1649 | * Fail commands. session lock held and recv side suspended and xmit |
1619 | * thread flushed | 1650 | * thread flushed |
1620 | */ | 1651 | */ |
1621 | static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, | 1652 | static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun, |
1622 | int error) | 1653 | int error) |
1623 | { | 1654 | { |
1624 | struct iscsi_task *task, *tmp; | 1655 | struct iscsi_task *task; |
1625 | 1656 | int i; | |
1626 | if (conn->task) { | ||
1627 | if (lun == -1 || | ||
1628 | (conn->task->sc && conn->task->sc->device->lun == lun)) | ||
1629 | conn->task = NULL; | ||
1630 | } | ||
1631 | 1657 | ||
1632 | /* flush pending */ | 1658 | for (i = 0; i < conn->session->cmds_max; i++) { |
1633 | list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) { | 1659 | task = conn->session->cmds[i]; |
1634 | if (lun == task->sc->device->lun || lun == -1) { | 1660 | if (!task->sc || task->state == ISCSI_TASK_FREE) |
1635 | ISCSI_DBG_SESSION(conn->session, | 1661 | continue; |
1636 | "failing pending sc %p itt 0x%x\n", | ||
1637 | task->sc, task->itt); | ||
1638 | fail_command(conn, task, error << 16); | ||
1639 | } | ||
1640 | } | ||
1641 | 1662 | ||
1642 | list_for_each_entry_safe(task, tmp, &conn->requeue, running) { | 1663 | if (lun != -1 && lun != task->sc->device->lun) |
1643 | if (lun == task->sc->device->lun || lun == -1) { | 1664 | continue; |
1644 | ISCSI_DBG_SESSION(conn->session, | ||
1645 | "failing requeued sc %p itt 0x%x\n", | ||
1646 | task->sc, task->itt); | ||
1647 | fail_command(conn, task, error << 16); | ||
1648 | } | ||
1649 | } | ||
1650 | 1665 | ||
1651 | /* fail all other running */ | 1666 | ISCSI_DBG_SESSION(conn->session, |
1652 | list_for_each_entry_safe(task, tmp, &conn->run_list, running) { | 1667 | "failing sc %p itt 0x%x state %d\n", |
1653 | if (lun == task->sc->device->lun || lun == -1) { | 1668 | task->sc, task->itt, task->state); |
1654 | ISCSI_DBG_SESSION(conn->session, | 1669 | fail_scsi_task(task, error << 16); |
1655 | "failing in progress sc %p itt 0x%x\n", | ||
1656 | task->sc, task->itt); | ||
1657 | fail_command(conn, task, error << 16); | ||
1658 | } | ||
1659 | } | 1670 | } |
1660 | } | 1671 | } |
1661 | 1672 | ||
@@ -1859,7 +1870,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1859 | } | 1870 | } |
1860 | 1871 | ||
1861 | if (task->state == ISCSI_TASK_PENDING) { | 1872 | if (task->state == ISCSI_TASK_PENDING) { |
1862 | fail_command(conn, task, DID_ABORT << 16); | 1873 | fail_scsi_task(task, DID_ABORT << 16); |
1863 | goto success; | 1874 | goto success; |
1864 | } | 1875 | } |
1865 | 1876 | ||
@@ -1890,7 +1901,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1890 | * then sent more data for the cmd. | 1901 | * then sent more data for the cmd. |
1891 | */ | 1902 | */ |
1892 | spin_lock(&session->lock); | 1903 | spin_lock(&session->lock); |
1893 | fail_command(conn, task, DID_ABORT << 16); | 1904 | fail_scsi_task(task, DID_ABORT << 16); |
1894 | conn->tmf_state = TMF_INITIAL; | 1905 | conn->tmf_state = TMF_INITIAL; |
1895 | spin_unlock(&session->lock); | 1906 | spin_unlock(&session->lock); |
1896 | iscsi_start_tx(conn); | 1907 | iscsi_start_tx(conn); |
@@ -1997,7 +2008,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) | |||
1997 | iscsi_suspend_tx(conn); | 2008 | iscsi_suspend_tx(conn); |
1998 | 2009 | ||
1999 | spin_lock_bh(&session->lock); | 2010 | spin_lock_bh(&session->lock); |
2000 | fail_all_commands(conn, sc->device->lun, DID_ERROR); | 2011 | fail_scsi_tasks(conn, sc->device->lun, DID_ERROR); |
2001 | conn->tmf_state = TMF_INITIAL; | 2012 | conn->tmf_state = TMF_INITIAL; |
2002 | spin_unlock_bh(&session->lock); | 2013 | spin_unlock_bh(&session->lock); |
2003 | 2014 | ||
@@ -2304,6 +2315,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
2304 | if (cmd_task_size) | 2315 | if (cmd_task_size) |
2305 | task->dd_data = &task[1]; | 2316 | task->dd_data = &task[1]; |
2306 | task->itt = cmd_i; | 2317 | task->itt = cmd_i; |
2318 | task->state = ISCSI_TASK_FREE; | ||
2307 | INIT_LIST_HEAD(&task->running); | 2319 | INIT_LIST_HEAD(&task->running); |
2308 | } | 2320 | } |
2309 | 2321 | ||
@@ -2390,10 +2402,8 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, | |||
2390 | conn->transport_timer.data = (unsigned long)conn; | 2402 | conn->transport_timer.data = (unsigned long)conn; |
2391 | conn->transport_timer.function = iscsi_check_transport_timeouts; | 2403 | conn->transport_timer.function = iscsi_check_transport_timeouts; |
2392 | 2404 | ||
2393 | INIT_LIST_HEAD(&conn->run_list); | ||
2394 | INIT_LIST_HEAD(&conn->mgmt_run_list); | ||
2395 | INIT_LIST_HEAD(&conn->mgmtqueue); | 2405 | INIT_LIST_HEAD(&conn->mgmtqueue); |
2396 | INIT_LIST_HEAD(&conn->xmitqueue); | 2406 | INIT_LIST_HEAD(&conn->cmdqueue); |
2397 | INIT_LIST_HEAD(&conn->requeue); | 2407 | INIT_LIST_HEAD(&conn->requeue); |
2398 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); | 2408 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); |
2399 | 2409 | ||
@@ -2561,27 +2571,24 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
2561 | EXPORT_SYMBOL_GPL(iscsi_conn_start); | 2571 | EXPORT_SYMBOL_GPL(iscsi_conn_start); |
2562 | 2572 | ||
2563 | static void | 2573 | static void |
2564 | flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) | 2574 | fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) |
2565 | { | 2575 | { |
2566 | struct iscsi_task *task, *tmp; | 2576 | struct iscsi_task *task; |
2577 | int i; | ||
2567 | 2578 | ||
2568 | /* handle pending */ | 2579 | for (i = 0; i < conn->session->cmds_max; i++) { |
2569 | list_for_each_entry_safe(task, tmp, &conn->mgmtqueue, running) { | 2580 | task = conn->session->cmds[i]; |
2570 | ISCSI_DBG_SESSION(session, "flushing pending mgmt task " | 2581 | if (task->sc) |
2571 | "itt 0x%x\n", task->itt); | 2582 | continue; |
2572 | /* release ref from prep task */ | ||
2573 | __iscsi_put_task(task); | ||
2574 | } | ||
2575 | 2583 | ||
2576 | /* handle running */ | 2584 | if (task->state == ISCSI_TASK_FREE) |
2577 | list_for_each_entry_safe(task, tmp, &conn->mgmt_run_list, running) { | 2585 | continue; |
2578 | ISCSI_DBG_SESSION(session, "flushing running mgmt task " | ||
2579 | "itt 0x%x\n", task->itt); | ||
2580 | /* release ref from prep task */ | ||
2581 | __iscsi_put_task(task); | ||
2582 | } | ||
2583 | 2586 | ||
2584 | conn->task = NULL; | 2587 | ISCSI_DBG_SESSION(conn->session, |
2588 | "failing mgmt itt 0x%x state %d\n", | ||
2589 | task->itt, task->state); | ||
2590 | iscsi_complete_task(task); | ||
2591 | } | ||
2585 | } | 2592 | } |
2586 | 2593 | ||
2587 | static void iscsi_start_session_recovery(struct iscsi_session *session, | 2594 | static void iscsi_start_session_recovery(struct iscsi_session *session, |
@@ -2638,10 +2645,10 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2638 | */ | 2645 | */ |
2639 | spin_lock_bh(&session->lock); | 2646 | spin_lock_bh(&session->lock); |
2640 | if (flag == STOP_CONN_RECOVER) | 2647 | if (flag == STOP_CONN_RECOVER) |
2641 | fail_all_commands(conn, -1, DID_TRANSPORT_DISRUPTED); | 2648 | fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED); |
2642 | else | 2649 | else |
2643 | fail_all_commands(conn, -1, DID_ERROR); | 2650 | fail_scsi_tasks(conn, -1, DID_ERROR); |
2644 | flush_control_queues(session, conn); | 2651 | fail_mgmt_tasks(session, conn); |
2645 | spin_unlock_bh(&session->lock); | 2652 | spin_unlock_bh(&session->lock); |
2646 | mutex_unlock(&session->eh_mutex); | 2653 | mutex_unlock(&session->eh_mutex); |
2647 | } | 2654 | } |