diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-03-20 18:29:15 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-04-25 04:05:27 -0400 |
commit | 2ec5a8c118139e756d4d39844550ba77ec3543cc (patch) | |
tree | 70302ecc6412cfd5f979b1d8515373fcbc5b9c92 | |
parent | 3e1c81a95f0d776cea68a36cfc78a0ce8f6d3a77 (diff) |
iscsi-target: Refactor TX queue logic + export response PDU creation
This patch refactors TX immediate + response queue handling to use
the new iscsit_transport API callers, and exports the necessary
traditional iscsi PDU response creation functions for iser-target
to utilize.
This includes:
- Add iscsit_build_datain_pdu() for DATAIN PDU init + convert
iscsit_build_datain_pdu()
- Add iscsit_build_logout_rsp() for LOGOUT_RSP PDU init + convert
iscsit_send_logout()
- Add iscsit_build_nopin_rsp() for NOPIN_RSP PDU init + convert
iscsit_send_nopin()
- Add iscsit_build_rsp_pdu() for SCSI_RSP PDU init + convert
iscsit_send_response()
- Add iscsit_build_task_mgt_rsp for TM_RSP PDU init + convert
iscsit_send_task_mgt_rsp()
- Refactor immediate queue state switch into iscsit_immediate_queue()
- Convert handle_immediate_queue() to use iscsit_transport caller
- Refactor response queue state switch into iscsit_response_queue()
- Convert handle_response_queue to use iscsit_transport caller
- Export iscsit_logout_post_handler(), iscsit_increment_maxcmdsn()
and iscsit_tmr_post_handler() for external transport module usage
v5 changes:
- Fix solicited NopIN handling with RDMAExtensions=No (nab)
v3 changes:
- Add iscsit_build_reject for REJECT PDU init + convert
iscsit_send_reject()
v2 changes:
- Add iscsit_queue_rsp() for iscsit_transport->iscsit_queue_data_in()
and iscsit_transport->iscsit_queue_status()
- Update lio_queue_data_in() to use ->iscsit_queue_data_in()
- Update lio_queue_status() to use ->iscsit_queue_status()
- Use mutex_trylock() in iscsit_increment_maxcmdsn()
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 659 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_configfs.c | 7 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_device.c | 7 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_tmr.c | 1 |
4 files changed, 370 insertions, 304 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 40bb916f57ff..ffbc6a94be52 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -70,8 +70,7 @@ struct kmem_cache *lio_ooo_cache; | |||
70 | struct kmem_cache *lio_r2t_cache; | 70 | struct kmem_cache *lio_r2t_cache; |
71 | 71 | ||
72 | static int iscsit_handle_immediate_data(struct iscsi_cmd *, | 72 | static int iscsit_handle_immediate_data(struct iscsi_cmd *, |
73 | unsigned char *buf, u32); | 73 | struct iscsi_scsi_req *, u32); |
74 | static int iscsit_logout_post_handler(struct iscsi_cmd *, struct iscsi_conn *); | ||
75 | 74 | ||
76 | struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *buf) | 75 | struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *buf) |
77 | { | 76 | { |
@@ -482,6 +481,15 @@ int iscsit_del_np(struct iscsi_np *np) | |||
482 | return 0; | 481 | return 0; |
483 | } | 482 | } |
484 | 483 | ||
484 | static int iscsit_immediate_queue(struct iscsi_conn *, struct iscsi_cmd *, int); | ||
485 | static int iscsit_response_queue(struct iscsi_conn *, struct iscsi_cmd *, int); | ||
486 | |||
487 | static int iscsit_queue_rsp(struct iscsi_conn *conn, struct iscsi_cmd *cmd) | ||
488 | { | ||
489 | iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); | ||
490 | return 0; | ||
491 | } | ||
492 | |||
485 | static struct iscsit_transport iscsi_target_transport = { | 493 | static struct iscsit_transport iscsi_target_transport = { |
486 | .name = "iSCSI/TCP", | 494 | .name = "iSCSI/TCP", |
487 | .transport_type = ISCSI_TCP, | 495 | .transport_type = ISCSI_TCP, |
@@ -493,6 +501,10 @@ static struct iscsit_transport iscsi_target_transport = { | |||
493 | .iscsit_get_login_rx = iscsit_get_login_rx, | 501 | .iscsit_get_login_rx = iscsit_get_login_rx, |
494 | .iscsit_put_login_tx = iscsit_put_login_tx, | 502 | .iscsit_put_login_tx = iscsit_put_login_tx, |
495 | .iscsit_get_dataout = iscsit_build_r2ts_for_cmd, | 503 | .iscsit_get_dataout = iscsit_build_r2ts_for_cmd, |
504 | .iscsit_immediate_queue = iscsit_immediate_queue, | ||
505 | .iscsit_response_queue = iscsit_response_queue, | ||
506 | .iscsit_queue_data_in = iscsit_queue_rsp, | ||
507 | .iscsit_queue_status = iscsit_queue_rsp, | ||
496 | }; | 508 | }; |
497 | 509 | ||
498 | static int __init iscsi_target_init_module(void) | 510 | static int __init iscsi_target_init_module(void) |
@@ -651,14 +663,6 @@ static int iscsit_add_reject( | |||
651 | iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); | 663 | iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); |
652 | 664 | ||
653 | ret = wait_for_completion_interruptible(&cmd->reject_comp); | 665 | ret = wait_for_completion_interruptible(&cmd->reject_comp); |
654 | /* | ||
655 | * Perform the kref_put now if se_cmd has been setup by | ||
656 | * iscsit_setup_scsi_cmd() | ||
657 | */ | ||
658 | if (cmd->se_cmd.se_tfo != NULL) { | ||
659 | pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n"); | ||
660 | target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | ||
661 | } | ||
662 | if (ret != 0) | 666 | if (ret != 0) |
663 | return -1; | 667 | return -1; |
664 | 668 | ||
@@ -2549,18 +2553,60 @@ static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *conn) | |||
2549 | } | 2553 | } |
2550 | } | 2554 | } |
2551 | 2555 | ||
2552 | static int iscsit_send_data_in( | 2556 | static void |
2553 | struct iscsi_cmd *cmd, | 2557 | iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn, |
2554 | struct iscsi_conn *conn) | 2558 | struct iscsi_datain *datain, struct iscsi_data_rsp *hdr, |
2559 | bool set_statsn) | ||
2555 | { | 2560 | { |
2556 | int iov_ret = 0, set_statsn = 0; | 2561 | hdr->opcode = ISCSI_OP_SCSI_DATA_IN; |
2557 | u32 iov_count = 0, tx_size = 0; | 2562 | hdr->flags = datain->flags; |
2563 | if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { | ||
2564 | if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) { | ||
2565 | hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW; | ||
2566 | hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count); | ||
2567 | } else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) { | ||
2568 | hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW; | ||
2569 | hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count); | ||
2570 | } | ||
2571 | } | ||
2572 | hton24(hdr->dlength, datain->length); | ||
2573 | if (hdr->flags & ISCSI_FLAG_DATA_ACK) | ||
2574 | int_to_scsilun(cmd->se_cmd.orig_fe_lun, | ||
2575 | (struct scsi_lun *)&hdr->lun); | ||
2576 | else | ||
2577 | put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun); | ||
2578 | |||
2579 | hdr->itt = cmd->init_task_tag; | ||
2580 | |||
2581 | if (hdr->flags & ISCSI_FLAG_DATA_ACK) | ||
2582 | hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag); | ||
2583 | else | ||
2584 | hdr->ttt = cpu_to_be32(0xFFFFFFFF); | ||
2585 | if (set_statsn) | ||
2586 | hdr->statsn = cpu_to_be32(cmd->stat_sn); | ||
2587 | else | ||
2588 | hdr->statsn = cpu_to_be32(0xFFFFFFFF); | ||
2589 | |||
2590 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | ||
2591 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | ||
2592 | hdr->datasn = cpu_to_be32(datain->data_sn); | ||
2593 | hdr->offset = cpu_to_be32(datain->offset); | ||
2594 | |||
2595 | pr_debug("Built DataIN ITT: 0x%08x, StatSN: 0x%08x," | ||
2596 | " DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n", | ||
2597 | cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn), | ||
2598 | ntohl(hdr->offset), datain->length, conn->cid); | ||
2599 | } | ||
2600 | |||
2601 | static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | ||
2602 | { | ||
2603 | struct iscsi_data_rsp *hdr = (struct iscsi_data_rsp *)&cmd->pdu[0]; | ||
2558 | struct iscsi_datain datain; | 2604 | struct iscsi_datain datain; |
2559 | struct iscsi_datain_req *dr; | 2605 | struct iscsi_datain_req *dr; |
2560 | struct iscsi_data_rsp *hdr; | ||
2561 | struct kvec *iov; | 2606 | struct kvec *iov; |
2562 | int eodr = 0; | 2607 | u32 iov_count = 0, tx_size = 0; |
2563 | int ret; | 2608 | int eodr = 0, ret, iov_ret; |
2609 | bool set_statsn = false; | ||
2564 | 2610 | ||
2565 | memset(&datain, 0, sizeof(struct iscsi_datain)); | 2611 | memset(&datain, 0, sizeof(struct iscsi_datain)); |
2566 | dr = iscsit_get_datain_values(cmd, &datain); | 2612 | dr = iscsit_get_datain_values(cmd, &datain); |
@@ -2569,7 +2615,6 @@ static int iscsit_send_data_in( | |||
2569 | cmd->init_task_tag); | 2615 | cmd->init_task_tag); |
2570 | return -1; | 2616 | return -1; |
2571 | } | 2617 | } |
2572 | |||
2573 | /* | 2618 | /* |
2574 | * Be paranoid and double check the logic for now. | 2619 | * Be paranoid and double check the logic for now. |
2575 | */ | 2620 | */ |
@@ -2577,7 +2622,7 @@ static int iscsit_send_data_in( | |||
2577 | pr_err("Command ITT: 0x%08x, datain.offset: %u and" | 2622 | pr_err("Command ITT: 0x%08x, datain.offset: %u and" |
2578 | " datain.length: %u exceeds cmd->data_length: %u\n", | 2623 | " datain.length: %u exceeds cmd->data_length: %u\n", |
2579 | cmd->init_task_tag, datain.offset, datain.length, | 2624 | cmd->init_task_tag, datain.offset, datain.length, |
2580 | cmd->se_cmd.data_length); | 2625 | cmd->se_cmd.data_length); |
2581 | return -1; | 2626 | return -1; |
2582 | } | 2627 | } |
2583 | 2628 | ||
@@ -2601,47 +2646,13 @@ static int iscsit_send_data_in( | |||
2601 | (dr->dr_complete == DATAIN_COMPLETE_CONNECTION_RECOVERY)) { | 2646 | (dr->dr_complete == DATAIN_COMPLETE_CONNECTION_RECOVERY)) { |
2602 | iscsit_increment_maxcmdsn(cmd, conn->sess); | 2647 | iscsit_increment_maxcmdsn(cmd, conn->sess); |
2603 | cmd->stat_sn = conn->stat_sn++; | 2648 | cmd->stat_sn = conn->stat_sn++; |
2604 | set_statsn = 1; | 2649 | set_statsn = true; |
2605 | } else if (dr->dr_complete == | 2650 | } else if (dr->dr_complete == |
2606 | DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY) | 2651 | DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY) |
2607 | set_statsn = 1; | 2652 | set_statsn = true; |
2608 | } | 2653 | } |
2609 | 2654 | ||
2610 | hdr = (struct iscsi_data_rsp *) cmd->pdu; | 2655 | iscsit_build_datain_pdu(cmd, conn, &datain, hdr, set_statsn); |
2611 | memset(hdr, 0, ISCSI_HDR_LEN); | ||
2612 | hdr->opcode = ISCSI_OP_SCSI_DATA_IN; | ||
2613 | hdr->flags = datain.flags; | ||
2614 | if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { | ||
2615 | if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) { | ||
2616 | hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW; | ||
2617 | hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count); | ||
2618 | } else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) { | ||
2619 | hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW; | ||
2620 | hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count); | ||
2621 | } | ||
2622 | } | ||
2623 | hton24(hdr->dlength, datain.length); | ||
2624 | if (hdr->flags & ISCSI_FLAG_DATA_ACK) | ||
2625 | int_to_scsilun(cmd->se_cmd.orig_fe_lun, | ||
2626 | (struct scsi_lun *)&hdr->lun); | ||
2627 | else | ||
2628 | put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun); | ||
2629 | |||
2630 | hdr->itt = cmd->init_task_tag; | ||
2631 | |||
2632 | if (hdr->flags & ISCSI_FLAG_DATA_ACK) | ||
2633 | hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag); | ||
2634 | else | ||
2635 | hdr->ttt = cpu_to_be32(0xFFFFFFFF); | ||
2636 | if (set_statsn) | ||
2637 | hdr->statsn = cpu_to_be32(cmd->stat_sn); | ||
2638 | else | ||
2639 | hdr->statsn = cpu_to_be32(0xFFFFFFFF); | ||
2640 | |||
2641 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | ||
2642 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | ||
2643 | hdr->datasn = cpu_to_be32(datain.data_sn); | ||
2644 | hdr->offset = cpu_to_be32(datain.offset); | ||
2645 | 2656 | ||
2646 | iov = &cmd->iov_data[0]; | 2657 | iov = &cmd->iov_data[0]; |
2647 | iov[iov_count].iov_base = cmd->pdu; | 2658 | iov[iov_count].iov_base = cmd->pdu; |
@@ -2652,7 +2663,7 @@ static int iscsit_send_data_in( | |||
2652 | u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; | 2663 | u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; |
2653 | 2664 | ||
2654 | iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, | 2665 | iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, |
2655 | (unsigned char *)hdr, ISCSI_HDR_LEN, | 2666 | (unsigned char *)cmd->pdu, ISCSI_HDR_LEN, |
2656 | 0, NULL, (u8 *)header_digest); | 2667 | 0, NULL, (u8 *)header_digest); |
2657 | 2668 | ||
2658 | iov[0].iov_len += ISCSI_CRC_LEN; | 2669 | iov[0].iov_len += ISCSI_CRC_LEN; |
@@ -2662,7 +2673,8 @@ static int iscsit_send_data_in( | |||
2662 | " for DataIN PDU 0x%08x\n", *header_digest); | 2673 | " for DataIN PDU 0x%08x\n", *header_digest); |
2663 | } | 2674 | } |
2664 | 2675 | ||
2665 | iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[1], datain.offset, datain.length); | 2676 | iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[1], |
2677 | datain.offset, datain.length); | ||
2666 | if (iov_ret < 0) | 2678 | if (iov_ret < 0) |
2667 | return -1; | 2679 | return -1; |
2668 | 2680 | ||
@@ -2693,11 +2705,6 @@ static int iscsit_send_data_in( | |||
2693 | cmd->iov_data_count = iov_count; | 2705 | cmd->iov_data_count = iov_count; |
2694 | cmd->tx_size = tx_size; | 2706 | cmd->tx_size = tx_size; |
2695 | 2707 | ||
2696 | pr_debug("Built DataIN ITT: 0x%08x, StatSN: 0x%08x," | ||
2697 | " DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n", | ||
2698 | cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn), | ||
2699 | ntohl(hdr->offset), datain.length, conn->cid); | ||
2700 | |||
2701 | /* sendpage is preferred but can't insert markers */ | 2708 | /* sendpage is preferred but can't insert markers */ |
2702 | if (!conn->conn_ops->IFMarker) | 2709 | if (!conn->conn_ops->IFMarker) |
2703 | ret = iscsit_fe_sendpage_sg(cmd, conn); | 2710 | ret = iscsit_fe_sendpage_sg(cmd, conn); |
@@ -2720,16 +2727,13 @@ static int iscsit_send_data_in( | |||
2720 | return eodr; | 2727 | return eodr; |
2721 | } | 2728 | } |
2722 | 2729 | ||
2723 | static int iscsit_send_logout_response( | 2730 | int |
2724 | struct iscsi_cmd *cmd, | 2731 | iscsit_build_logout_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, |
2725 | struct iscsi_conn *conn) | 2732 | struct iscsi_logout_rsp *hdr) |
2726 | { | 2733 | { |
2727 | int niov = 0, tx_size; | ||
2728 | struct iscsi_conn *logout_conn = NULL; | 2734 | struct iscsi_conn *logout_conn = NULL; |
2729 | struct iscsi_conn_recovery *cr = NULL; | 2735 | struct iscsi_conn_recovery *cr = NULL; |
2730 | struct iscsi_session *sess = conn->sess; | 2736 | struct iscsi_session *sess = conn->sess; |
2731 | struct kvec *iov; | ||
2732 | struct iscsi_logout_rsp *hdr; | ||
2733 | /* | 2737 | /* |
2734 | * The actual shutting down of Sessions and/or Connections | 2738 | * The actual shutting down of Sessions and/or Connections |
2735 | * for CLOSESESSION and CLOSECONNECTION Logout Requests | 2739 | * for CLOSESESSION and CLOSECONNECTION Logout Requests |
@@ -2798,9 +2802,6 @@ static int iscsit_send_logout_response( | |||
2798 | return -1; | 2802 | return -1; |
2799 | } | 2803 | } |
2800 | 2804 | ||
2801 | tx_size = ISCSI_HDR_LEN; | ||
2802 | hdr = (struct iscsi_logout_rsp *)cmd->pdu; | ||
2803 | memset(hdr, 0, ISCSI_HDR_LEN); | ||
2804 | hdr->opcode = ISCSI_OP_LOGOUT_RSP; | 2805 | hdr->opcode = ISCSI_OP_LOGOUT_RSP; |
2805 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | 2806 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; |
2806 | hdr->response = cmd->logout_response; | 2807 | hdr->response = cmd->logout_response; |
@@ -2812,6 +2813,27 @@ static int iscsit_send_logout_response( | |||
2812 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | 2813 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); |
2813 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | 2814 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); |
2814 | 2815 | ||
2816 | pr_debug("Built Logout Response ITT: 0x%08x StatSN:" | ||
2817 | " 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n", | ||
2818 | cmd->init_task_tag, cmd->stat_sn, hdr->response, | ||
2819 | cmd->logout_cid, conn->cid); | ||
2820 | |||
2821 | return 0; | ||
2822 | } | ||
2823 | EXPORT_SYMBOL(iscsit_build_logout_rsp); | ||
2824 | |||
2825 | static int | ||
2826 | iscsit_send_logout(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | ||
2827 | { | ||
2828 | struct kvec *iov; | ||
2829 | int niov = 0, tx_size, rc; | ||
2830 | |||
2831 | rc = iscsit_build_logout_rsp(cmd, conn, | ||
2832 | (struct iscsi_logout_rsp *)&cmd->pdu[0]); | ||
2833 | if (rc < 0) | ||
2834 | return rc; | ||
2835 | |||
2836 | tx_size = ISCSI_HDR_LEN; | ||
2815 | iov = &cmd->iov_misc[0]; | 2837 | iov = &cmd->iov_misc[0]; |
2816 | iov[niov].iov_base = cmd->pdu; | 2838 | iov[niov].iov_base = cmd->pdu; |
2817 | iov[niov++].iov_len = ISCSI_HDR_LEN; | 2839 | iov[niov++].iov_len = ISCSI_HDR_LEN; |
@@ -2820,7 +2842,7 @@ static int iscsit_send_logout_response( | |||
2820 | u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; | 2842 | u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; |
2821 | 2843 | ||
2822 | iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, | 2844 | iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, |
2823 | (unsigned char *)hdr, ISCSI_HDR_LEN, | 2845 | (unsigned char *)&cmd->pdu[0], ISCSI_HDR_LEN, |
2824 | 0, NULL, (u8 *)header_digest); | 2846 | 0, NULL, (u8 *)header_digest); |
2825 | 2847 | ||
2826 | iov[0].iov_len += ISCSI_CRC_LEN; | 2848 | iov[0].iov_len += ISCSI_CRC_LEN; |
@@ -2831,14 +2853,37 @@ static int iscsit_send_logout_response( | |||
2831 | cmd->iov_misc_count = niov; | 2853 | cmd->iov_misc_count = niov; |
2832 | cmd->tx_size = tx_size; | 2854 | cmd->tx_size = tx_size; |
2833 | 2855 | ||
2834 | pr_debug("Sending Logout Response ITT: 0x%08x StatSN:" | ||
2835 | " 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n", | ||
2836 | cmd->init_task_tag, cmd->stat_sn, hdr->response, | ||
2837 | cmd->logout_cid, conn->cid); | ||
2838 | |||
2839 | return 0; | 2856 | return 0; |
2840 | } | 2857 | } |
2841 | 2858 | ||
2859 | void | ||
2860 | iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, | ||
2861 | struct iscsi_nopin *hdr, bool nopout_response) | ||
2862 | { | ||
2863 | hdr->opcode = ISCSI_OP_NOOP_IN; | ||
2864 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | ||
2865 | hton24(hdr->dlength, cmd->buf_ptr_size); | ||
2866 | if (nopout_response) | ||
2867 | put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun); | ||
2868 | hdr->itt = cmd->init_task_tag; | ||
2869 | hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag); | ||
2870 | cmd->stat_sn = (nopout_response) ? conn->stat_sn++ : | ||
2871 | conn->stat_sn; | ||
2872 | hdr->statsn = cpu_to_be32(cmd->stat_sn); | ||
2873 | |||
2874 | if (nopout_response) | ||
2875 | iscsit_increment_maxcmdsn(cmd, conn->sess); | ||
2876 | |||
2877 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | ||
2878 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | ||
2879 | |||
2880 | pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x," | ||
2881 | " StatSN: 0x%08x, Length %u\n", (nopout_response) ? | ||
2882 | "Solicitied" : "Unsolicitied", cmd->init_task_tag, | ||
2883 | cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size); | ||
2884 | } | ||
2885 | EXPORT_SYMBOL(iscsit_build_nopin_rsp); | ||
2886 | |||
2842 | /* | 2887 | /* |
2843 | * Unsolicited NOPIN, either requesting a response or not. | 2888 | * Unsolicited NOPIN, either requesting a response or not. |
2844 | */ | 2889 | */ |
@@ -2847,20 +2892,10 @@ static int iscsit_send_unsolicited_nopin( | |||
2847 | struct iscsi_conn *conn, | 2892 | struct iscsi_conn *conn, |
2848 | int want_response) | 2893 | int want_response) |
2849 | { | 2894 | { |
2850 | int tx_size = ISCSI_HDR_LEN; | 2895 | struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0]; |
2851 | struct iscsi_nopin *hdr; | 2896 | int tx_size = ISCSI_HDR_LEN, ret; |
2852 | int ret; | ||
2853 | 2897 | ||
2854 | hdr = (struct iscsi_nopin *) cmd->pdu; | 2898 | iscsit_build_nopin_rsp(cmd, conn, hdr, false); |
2855 | memset(hdr, 0, ISCSI_HDR_LEN); | ||
2856 | hdr->opcode = ISCSI_OP_NOOP_IN; | ||
2857 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | ||
2858 | hdr->itt = cmd->init_task_tag; | ||
2859 | hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag); | ||
2860 | cmd->stat_sn = conn->stat_sn; | ||
2861 | hdr->statsn = cpu_to_be32(cmd->stat_sn); | ||
2862 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | ||
2863 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | ||
2864 | 2899 | ||
2865 | if (conn->conn_ops->HeaderDigest) { | 2900 | if (conn->conn_ops->HeaderDigest) { |
2866 | u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; | 2901 | u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; |
@@ -2896,31 +2931,17 @@ static int iscsit_send_unsolicited_nopin( | |||
2896 | return 0; | 2931 | return 0; |
2897 | } | 2932 | } |
2898 | 2933 | ||
2899 | static int iscsit_send_nopin_response( | 2934 | static int |
2900 | struct iscsi_cmd *cmd, | 2935 | iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn) |
2901 | struct iscsi_conn *conn) | ||
2902 | { | 2936 | { |
2903 | int niov = 0, tx_size; | 2937 | struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0]; |
2904 | u32 padding = 0; | ||
2905 | struct kvec *iov; | 2938 | struct kvec *iov; |
2906 | struct iscsi_nopin *hdr; | 2939 | u32 padding = 0; |
2907 | 2940 | int niov = 0, tx_size; | |
2908 | tx_size = ISCSI_HDR_LEN; | ||
2909 | hdr = (struct iscsi_nopin *) cmd->pdu; | ||
2910 | memset(hdr, 0, ISCSI_HDR_LEN); | ||
2911 | hdr->opcode = ISCSI_OP_NOOP_IN; | ||
2912 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | ||
2913 | hton24(hdr->dlength, cmd->buf_ptr_size); | ||
2914 | put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun); | ||
2915 | hdr->itt = cmd->init_task_tag; | ||
2916 | hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag); | ||
2917 | cmd->stat_sn = conn->stat_sn++; | ||
2918 | hdr->statsn = cpu_to_be32(cmd->stat_sn); | ||
2919 | 2941 | ||
2920 | iscsit_increment_maxcmdsn(cmd, conn->sess); | 2942 | iscsit_build_nopin_rsp(cmd, conn, hdr, true); |
2921 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | ||
2922 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | ||
2923 | 2943 | ||
2944 | tx_size = ISCSI_HDR_LEN; | ||
2924 | iov = &cmd->iov_misc[0]; | 2945 | iov = &cmd->iov_misc[0]; |
2925 | iov[niov].iov_base = cmd->pdu; | 2946 | iov[niov].iov_base = cmd->pdu; |
2926 | iov[niov++].iov_len = ISCSI_HDR_LEN; | 2947 | iov[niov++].iov_len = ISCSI_HDR_LEN; |
@@ -2976,10 +2997,6 @@ static int iscsit_send_nopin_response( | |||
2976 | cmd->iov_misc_count = niov; | 2997 | cmd->iov_misc_count = niov; |
2977 | cmd->tx_size = tx_size; | 2998 | cmd->tx_size = tx_size; |
2978 | 2999 | ||
2979 | pr_debug("Sending NOPIN Response ITT: 0x%08x, TTT:" | ||
2980 | " 0x%08x, StatSN: 0x%08x, Length %u\n", cmd->init_task_tag, | ||
2981 | cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size); | ||
2982 | |||
2983 | return 0; | 3000 | return 0; |
2984 | } | 3001 | } |
2985 | 3002 | ||
@@ -3140,24 +3157,16 @@ int iscsit_build_r2ts_for_cmd( | |||
3140 | return 0; | 3157 | return 0; |
3141 | } | 3158 | } |
3142 | 3159 | ||
3143 | static int iscsit_send_status( | 3160 | void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn, |
3144 | struct iscsi_cmd *cmd, | 3161 | bool inc_stat_sn, struct iscsi_scsi_rsp *hdr) |
3145 | struct iscsi_conn *conn) | ||
3146 | { | 3162 | { |
3147 | u8 iov_count = 0, recovery; | 3163 | if (inc_stat_sn) |
3148 | u32 padding = 0, tx_size = 0; | ||
3149 | struct iscsi_scsi_rsp *hdr; | ||
3150 | struct kvec *iov; | ||
3151 | |||
3152 | recovery = (cmd->i_state != ISTATE_SEND_STATUS); | ||
3153 | if (!recovery) | ||
3154 | cmd->stat_sn = conn->stat_sn++; | 3164 | cmd->stat_sn = conn->stat_sn++; |
3155 | 3165 | ||
3156 | spin_lock_bh(&conn->sess->session_stats_lock); | 3166 | spin_lock_bh(&conn->sess->session_stats_lock); |
3157 | conn->sess->rsp_pdus++; | 3167 | conn->sess->rsp_pdus++; |
3158 | spin_unlock_bh(&conn->sess->session_stats_lock); | 3168 | spin_unlock_bh(&conn->sess->session_stats_lock); |
3159 | 3169 | ||
3160 | hdr = (struct iscsi_scsi_rsp *) cmd->pdu; | ||
3161 | memset(hdr, 0, ISCSI_HDR_LEN); | 3170 | memset(hdr, 0, ISCSI_HDR_LEN); |
3162 | hdr->opcode = ISCSI_OP_SCSI_CMD_RSP; | 3171 | hdr->opcode = ISCSI_OP_SCSI_CMD_RSP; |
3163 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | 3172 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; |
@@ -3177,6 +3186,23 @@ static int iscsit_send_status( | |||
3177 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | 3186 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); |
3178 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | 3187 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); |
3179 | 3188 | ||
3189 | pr_debug("Built SCSI Response, ITT: 0x%08x, StatSN: 0x%08x," | ||
3190 | " Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n", | ||
3191 | cmd->init_task_tag, cmd->stat_sn, cmd->se_cmd.scsi_status, | ||
3192 | cmd->se_cmd.scsi_status, conn->cid); | ||
3193 | } | ||
3194 | EXPORT_SYMBOL(iscsit_build_rsp_pdu); | ||
3195 | |||
3196 | static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | ||
3197 | { | ||
3198 | struct iscsi_scsi_rsp *hdr = (struct iscsi_scsi_rsp *)&cmd->pdu[0]; | ||
3199 | struct kvec *iov; | ||
3200 | u32 padding = 0, tx_size = 0; | ||
3201 | int iov_count = 0; | ||
3202 | bool inc_stat_sn = (cmd->i_state == ISTATE_SEND_STATUS); | ||
3203 | |||
3204 | iscsit_build_rsp_pdu(cmd, conn, inc_stat_sn, hdr); | ||
3205 | |||
3180 | iov = &cmd->iov_misc[0]; | 3206 | iov = &cmd->iov_misc[0]; |
3181 | iov[iov_count].iov_base = cmd->pdu; | 3207 | iov[iov_count].iov_base = cmd->pdu; |
3182 | iov[iov_count++].iov_len = ISCSI_HDR_LEN; | 3208 | iov[iov_count++].iov_len = ISCSI_HDR_LEN; |
@@ -3231,7 +3257,7 @@ static int iscsit_send_status( | |||
3231 | u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; | 3257 | u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; |
3232 | 3258 | ||
3233 | iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, | 3259 | iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, |
3234 | (unsigned char *)hdr, ISCSI_HDR_LEN, | 3260 | (unsigned char *)cmd->pdu, ISCSI_HDR_LEN, |
3235 | 0, NULL, (u8 *)header_digest); | 3261 | 0, NULL, (u8 *)header_digest); |
3236 | 3262 | ||
3237 | iov[0].iov_len += ISCSI_CRC_LEN; | 3263 | iov[0].iov_len += ISCSI_CRC_LEN; |
@@ -3243,11 +3269,6 @@ static int iscsit_send_status( | |||
3243 | cmd->iov_misc_count = iov_count; | 3269 | cmd->iov_misc_count = iov_count; |
3244 | cmd->tx_size = tx_size; | 3270 | cmd->tx_size = tx_size; |
3245 | 3271 | ||
3246 | pr_debug("Built %sSCSI Response, ITT: 0x%08x, StatSN: 0x%08x," | ||
3247 | " Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n", | ||
3248 | (!recovery) ? "" : "Recovery ", cmd->init_task_tag, | ||
3249 | cmd->stat_sn, 0x00, cmd->se_cmd.scsi_status, conn->cid); | ||
3250 | |||
3251 | return 0; | 3272 | return 0; |
3252 | } | 3273 | } |
3253 | 3274 | ||
@@ -3270,16 +3291,12 @@ static u8 iscsit_convert_tcm_tmr_rsp(struct se_tmr_req *se_tmr) | |||
3270 | } | 3291 | } |
3271 | } | 3292 | } |
3272 | 3293 | ||
3273 | static int iscsit_send_task_mgt_rsp( | 3294 | void |
3274 | struct iscsi_cmd *cmd, | 3295 | iscsit_build_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, |
3275 | struct iscsi_conn *conn) | 3296 | struct iscsi_tm_rsp *hdr) |
3276 | { | 3297 | { |
3277 | struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req; | 3298 | struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req; |
3278 | struct iscsi_tm_rsp *hdr; | ||
3279 | u32 tx_size = 0; | ||
3280 | 3299 | ||
3281 | hdr = (struct iscsi_tm_rsp *) cmd->pdu; | ||
3282 | memset(hdr, 0, ISCSI_HDR_LEN); | ||
3283 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP; | 3300 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP; |
3284 | hdr->flags = ISCSI_FLAG_CMD_FINAL; | 3301 | hdr->flags = ISCSI_FLAG_CMD_FINAL; |
3285 | hdr->response = iscsit_convert_tcm_tmr_rsp(se_tmr); | 3302 | hdr->response = iscsit_convert_tcm_tmr_rsp(se_tmr); |
@@ -3291,6 +3308,20 @@ static int iscsit_send_task_mgt_rsp( | |||
3291 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | 3308 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); |
3292 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | 3309 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); |
3293 | 3310 | ||
3311 | pr_debug("Built Task Management Response ITT: 0x%08x," | ||
3312 | " StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n", | ||
3313 | cmd->init_task_tag, cmd->stat_sn, hdr->response, conn->cid); | ||
3314 | } | ||
3315 | EXPORT_SYMBOL(iscsit_build_task_mgt_rsp); | ||
3316 | |||
3317 | static int | ||
3318 | iscsit_send_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | ||
3319 | { | ||
3320 | struct iscsi_tm_rsp *hdr = (struct iscsi_tm_rsp *)&cmd->pdu[0]; | ||
3321 | u32 tx_size = 0; | ||
3322 | |||
3323 | iscsit_build_task_mgt_rsp(cmd, conn, hdr); | ||
3324 | |||
3294 | cmd->iov_misc[0].iov_base = cmd->pdu; | 3325 | cmd->iov_misc[0].iov_base = cmd->pdu; |
3295 | cmd->iov_misc[0].iov_len = ISCSI_HDR_LEN; | 3326 | cmd->iov_misc[0].iov_len = ISCSI_HDR_LEN; |
3296 | tx_size += ISCSI_HDR_LEN; | 3327 | tx_size += ISCSI_HDR_LEN; |
@@ -3311,10 +3342,6 @@ static int iscsit_send_task_mgt_rsp( | |||
3311 | cmd->iov_misc_count = 1; | 3342 | cmd->iov_misc_count = 1; |
3312 | cmd->tx_size = tx_size; | 3343 | cmd->tx_size = tx_size; |
3313 | 3344 | ||
3314 | pr_debug("Built Task Management Response ITT: 0x%08x," | ||
3315 | " StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n", | ||
3316 | cmd->init_task_tag, cmd->stat_sn, hdr->response, conn->cid); | ||
3317 | |||
3318 | return 0; | 3345 | return 0; |
3319 | } | 3346 | } |
3320 | 3347 | ||
@@ -3510,6 +3537,22 @@ static int iscsit_send_text_rsp( | |||
3510 | return 0; | 3537 | return 0; |
3511 | } | 3538 | } |
3512 | 3539 | ||
3540 | void | ||
3541 | iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn, | ||
3542 | struct iscsi_reject *hdr) | ||
3543 | { | ||
3544 | hdr->opcode = ISCSI_OP_REJECT; | ||
3545 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | ||
3546 | hton24(hdr->dlength, ISCSI_HDR_LEN); | ||
3547 | hdr->ffffffff = cpu_to_be32(0xffffffff); | ||
3548 | cmd->stat_sn = conn->stat_sn++; | ||
3549 | hdr->statsn = cpu_to_be32(cmd->stat_sn); | ||
3550 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | ||
3551 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | ||
3552 | |||
3553 | } | ||
3554 | EXPORT_SYMBOL(iscsit_build_reject); | ||
3555 | |||
3513 | static int iscsit_send_reject( | 3556 | static int iscsit_send_reject( |
3514 | struct iscsi_cmd *cmd, | 3557 | struct iscsi_cmd *cmd, |
3515 | struct iscsi_conn *conn) | 3558 | struct iscsi_conn *conn) |
@@ -3518,18 +3561,9 @@ static int iscsit_send_reject( | |||
3518 | struct iscsi_reject *hdr; | 3561 | struct iscsi_reject *hdr; |
3519 | struct kvec *iov; | 3562 | struct kvec *iov; |
3520 | 3563 | ||
3521 | hdr = (struct iscsi_reject *) cmd->pdu; | 3564 | iscsit_build_reject(cmd, conn, (struct iscsi_reject *)&cmd->pdu[0]); |
3522 | hdr->opcode = ISCSI_OP_REJECT; | ||
3523 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | ||
3524 | hton24(hdr->dlength, ISCSI_HDR_LEN); | ||
3525 | hdr->ffffffff = cpu_to_be32(0xffffffff); | ||
3526 | cmd->stat_sn = conn->stat_sn++; | ||
3527 | hdr->statsn = cpu_to_be32(cmd->stat_sn); | ||
3528 | hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | ||
3529 | hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | ||
3530 | 3565 | ||
3531 | iov = &cmd->iov_misc[0]; | 3566 | iov = &cmd->iov_misc[0]; |
3532 | |||
3533 | iov[iov_count].iov_base = cmd->pdu; | 3567 | iov[iov_count].iov_base = cmd->pdu; |
3534 | iov[iov_count++].iov_len = ISCSI_HDR_LEN; | 3568 | iov[iov_count++].iov_len = ISCSI_HDR_LEN; |
3535 | iov[iov_count].iov_base = cmd->buf_ptr; | 3569 | iov[iov_count].iov_base = cmd->buf_ptr; |
@@ -3626,55 +3660,41 @@ static inline void iscsit_thread_check_cpumask( | |||
3626 | set_cpus_allowed_ptr(p, conn->conn_cpumask); | 3660 | set_cpus_allowed_ptr(p, conn->conn_cpumask); |
3627 | } | 3661 | } |
3628 | 3662 | ||
3629 | static int handle_immediate_queue(struct iscsi_conn *conn) | 3663 | static int |
3664 | iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) | ||
3630 | { | 3665 | { |
3631 | struct iscsi_queue_req *qr; | ||
3632 | struct iscsi_cmd *cmd; | ||
3633 | u8 state; | ||
3634 | int ret; | 3666 | int ret; |
3635 | 3667 | ||
3636 | while ((qr = iscsit_get_cmd_from_immediate_queue(conn))) { | 3668 | switch (state) { |
3637 | atomic_set(&conn->check_immediate_queue, 0); | 3669 | case ISTATE_SEND_R2T: |
3638 | cmd = qr->cmd; | 3670 | ret = iscsit_send_r2t(cmd, conn); |
3639 | state = qr->state; | 3671 | if (ret < 0) |
3640 | kmem_cache_free(lio_qr_cache, qr); | 3672 | goto err; |
3641 | 3673 | break; | |
3642 | switch (state) { | 3674 | case ISTATE_REMOVE: |
3643 | case ISTATE_SEND_R2T: | 3675 | spin_lock_bh(&conn->cmd_lock); |
3644 | ret = iscsit_send_r2t(cmd, conn); | 3676 | list_del(&cmd->i_conn_node); |
3645 | if (ret < 0) | 3677 | spin_unlock_bh(&conn->cmd_lock); |
3646 | goto err; | ||
3647 | break; | ||
3648 | case ISTATE_REMOVE: | ||
3649 | if (cmd->data_direction == DMA_TO_DEVICE) | ||
3650 | iscsit_stop_dataout_timer(cmd); | ||
3651 | |||
3652 | spin_lock_bh(&conn->cmd_lock); | ||
3653 | list_del(&cmd->i_conn_node); | ||
3654 | spin_unlock_bh(&conn->cmd_lock); | ||
3655 | 3678 | ||
3656 | iscsit_free_cmd(cmd); | 3679 | iscsit_free_cmd(cmd); |
3657 | continue; | 3680 | break; |
3658 | case ISTATE_SEND_NOPIN_WANT_RESPONSE: | 3681 | case ISTATE_SEND_NOPIN_WANT_RESPONSE: |
3659 | iscsit_mod_nopin_response_timer(conn); | 3682 | iscsit_mod_nopin_response_timer(conn); |
3660 | ret = iscsit_send_unsolicited_nopin(cmd, | 3683 | ret = iscsit_send_unsolicited_nopin(cmd, conn, 1); |
3661 | conn, 1); | 3684 | if (ret < 0) |
3662 | if (ret < 0) | ||
3663 | goto err; | ||
3664 | break; | ||
3665 | case ISTATE_SEND_NOPIN_NO_RESPONSE: | ||
3666 | ret = iscsit_send_unsolicited_nopin(cmd, | ||
3667 | conn, 0); | ||
3668 | if (ret < 0) | ||
3669 | goto err; | ||
3670 | break; | ||
3671 | default: | ||
3672 | pr_err("Unknown Opcode: 0x%02x ITT:" | ||
3673 | " 0x%08x, i_state: %d on CID: %hu\n", | ||
3674 | cmd->iscsi_opcode, cmd->init_task_tag, state, | ||
3675 | conn->cid); | ||
3676 | goto err; | 3685 | goto err; |
3677 | } | 3686 | break; |
3687 | case ISTATE_SEND_NOPIN_NO_RESPONSE: | ||
3688 | ret = iscsit_send_unsolicited_nopin(cmd, conn, 0); | ||
3689 | if (ret < 0) | ||
3690 | goto err; | ||
3691 | break; | ||
3692 | default: | ||
3693 | pr_err("Unknown Opcode: 0x%02x ITT:" | ||
3694 | " 0x%08x, i_state: %d on CID: %hu\n", | ||
3695 | cmd->iscsi_opcode, cmd->init_task_tag, state, | ||
3696 | conn->cid); | ||
3697 | goto err; | ||
3678 | } | 3698 | } |
3679 | 3699 | ||
3680 | return 0; | 3700 | return 0; |
@@ -3683,128 +3703,143 @@ err: | |||
3683 | return -1; | 3703 | return -1; |
3684 | } | 3704 | } |
3685 | 3705 | ||
3686 | static int handle_response_queue(struct iscsi_conn *conn) | 3706 | static int |
3707 | iscsit_handle_immediate_queue(struct iscsi_conn *conn) | ||
3687 | { | 3708 | { |
3709 | struct iscsit_transport *t = conn->conn_transport; | ||
3688 | struct iscsi_queue_req *qr; | 3710 | struct iscsi_queue_req *qr; |
3689 | struct iscsi_cmd *cmd; | 3711 | struct iscsi_cmd *cmd; |
3690 | u8 state; | 3712 | u8 state; |
3691 | int ret; | 3713 | int ret; |
3692 | 3714 | ||
3693 | while ((qr = iscsit_get_cmd_from_response_queue(conn))) { | 3715 | while ((qr = iscsit_get_cmd_from_immediate_queue(conn))) { |
3716 | atomic_set(&conn->check_immediate_queue, 0); | ||
3694 | cmd = qr->cmd; | 3717 | cmd = qr->cmd; |
3695 | state = qr->state; | 3718 | state = qr->state; |
3696 | kmem_cache_free(lio_qr_cache, qr); | 3719 | kmem_cache_free(lio_qr_cache, qr); |
3697 | 3720 | ||
3698 | check_rsp_state: | 3721 | ret = t->iscsit_immediate_queue(conn, cmd, state); |
3699 | switch (state) { | 3722 | if (ret < 0) |
3700 | case ISTATE_SEND_DATAIN: | 3723 | return ret; |
3701 | ret = iscsit_send_data_in(cmd, conn); | 3724 | } |
3702 | if (ret < 0) | ||
3703 | goto err; | ||
3704 | else if (!ret) | ||
3705 | /* more drs */ | ||
3706 | goto check_rsp_state; | ||
3707 | else if (ret == 1) { | ||
3708 | /* all done */ | ||
3709 | spin_lock_bh(&cmd->istate_lock); | ||
3710 | cmd->i_state = ISTATE_SENT_STATUS; | ||
3711 | spin_unlock_bh(&cmd->istate_lock); | ||
3712 | |||
3713 | if (atomic_read(&conn->check_immediate_queue)) | ||
3714 | return 1; | ||
3715 | 3725 | ||
3716 | continue; | 3726 | return 0; |
3717 | } else if (ret == 2) { | 3727 | } |
3718 | /* Still must send status, | ||
3719 | SCF_TRANSPORT_TASK_SENSE was set */ | ||
3720 | spin_lock_bh(&cmd->istate_lock); | ||
3721 | cmd->i_state = ISTATE_SEND_STATUS; | ||
3722 | spin_unlock_bh(&cmd->istate_lock); | ||
3723 | state = ISTATE_SEND_STATUS; | ||
3724 | goto check_rsp_state; | ||
3725 | } | ||
3726 | 3728 | ||
3727 | break; | 3729 | static int |
3728 | case ISTATE_SEND_STATUS: | 3730 | iscsit_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) |
3729 | case ISTATE_SEND_STATUS_RECOVERY: | 3731 | { |
3730 | ret = iscsit_send_status(cmd, conn); | 3732 | int ret; |
3731 | break; | 3733 | |
3732 | case ISTATE_SEND_LOGOUTRSP: | 3734 | check_rsp_state: |
3733 | ret = iscsit_send_logout_response(cmd, conn); | 3735 | switch (state) { |
3734 | break; | 3736 | case ISTATE_SEND_DATAIN: |
3735 | case ISTATE_SEND_ASYNCMSG: | 3737 | ret = iscsit_send_datain(cmd, conn); |
3736 | ret = iscsit_send_conn_drop_async_message( | ||
3737 | cmd, conn); | ||
3738 | break; | ||
3739 | case ISTATE_SEND_NOPIN: | ||
3740 | ret = iscsit_send_nopin_response(cmd, conn); | ||
3741 | break; | ||
3742 | case ISTATE_SEND_REJECT: | ||
3743 | ret = iscsit_send_reject(cmd, conn); | ||
3744 | break; | ||
3745 | case ISTATE_SEND_TASKMGTRSP: | ||
3746 | ret = iscsit_send_task_mgt_rsp(cmd, conn); | ||
3747 | if (ret != 0) | ||
3748 | break; | ||
3749 | ret = iscsit_tmr_post_handler(cmd, conn); | ||
3750 | if (ret != 0) | ||
3751 | iscsit_fall_back_to_erl0(conn->sess); | ||
3752 | break; | ||
3753 | case ISTATE_SEND_TEXTRSP: | ||
3754 | ret = iscsit_send_text_rsp(cmd, conn); | ||
3755 | break; | ||
3756 | default: | ||
3757 | pr_err("Unknown Opcode: 0x%02x ITT:" | ||
3758 | " 0x%08x, i_state: %d on CID: %hu\n", | ||
3759 | cmd->iscsi_opcode, cmd->init_task_tag, | ||
3760 | state, conn->cid); | ||
3761 | goto err; | ||
3762 | } | ||
3763 | if (ret < 0) | 3738 | if (ret < 0) |
3764 | goto err; | 3739 | goto err; |
3740 | else if (!ret) | ||
3741 | /* more drs */ | ||
3742 | goto check_rsp_state; | ||
3743 | else if (ret == 1) { | ||
3744 | /* all done */ | ||
3745 | spin_lock_bh(&cmd->istate_lock); | ||
3746 | cmd->i_state = ISTATE_SENT_STATUS; | ||
3747 | spin_unlock_bh(&cmd->istate_lock); | ||
3765 | 3748 | ||
3766 | if (iscsit_send_tx_data(cmd, conn, 1) < 0) { | 3749 | if (atomic_read(&conn->check_immediate_queue)) |
3767 | iscsit_tx_thread_wait_for_tcp(conn); | 3750 | return 1; |
3768 | iscsit_unmap_iovec(cmd); | ||
3769 | goto err; | ||
3770 | } | ||
3771 | iscsit_unmap_iovec(cmd); | ||
3772 | 3751 | ||
3773 | switch (state) { | 3752 | return 0; |
3774 | case ISTATE_SEND_LOGOUTRSP: | 3753 | } else if (ret == 2) { |
3775 | if (!iscsit_logout_post_handler(cmd, conn)) | 3754 | /* Still must send status, |
3776 | goto restart; | 3755 | SCF_TRANSPORT_TASK_SENSE was set */ |
3777 | /* fall through */ | ||
3778 | case ISTATE_SEND_STATUS: | ||
3779 | case ISTATE_SEND_ASYNCMSG: | ||
3780 | case ISTATE_SEND_NOPIN: | ||
3781 | case ISTATE_SEND_STATUS_RECOVERY: | ||
3782 | case ISTATE_SEND_TEXTRSP: | ||
3783 | case ISTATE_SEND_TASKMGTRSP: | ||
3784 | spin_lock_bh(&cmd->istate_lock); | 3756 | spin_lock_bh(&cmd->istate_lock); |
3785 | cmd->i_state = ISTATE_SENT_STATUS; | 3757 | cmd->i_state = ISTATE_SEND_STATUS; |
3786 | spin_unlock_bh(&cmd->istate_lock); | 3758 | spin_unlock_bh(&cmd->istate_lock); |
3759 | state = ISTATE_SEND_STATUS; | ||
3760 | goto check_rsp_state; | ||
3761 | } | ||
3762 | |||
3763 | break; | ||
3764 | case ISTATE_SEND_STATUS: | ||
3765 | case ISTATE_SEND_STATUS_RECOVERY: | ||
3766 | ret = iscsit_send_response(cmd, conn); | ||
3767 | break; | ||
3768 | case ISTATE_SEND_LOGOUTRSP: | ||
3769 | ret = iscsit_send_logout(cmd, conn); | ||
3770 | break; | ||
3771 | case ISTATE_SEND_ASYNCMSG: | ||
3772 | ret = iscsit_send_conn_drop_async_message( | ||
3773 | cmd, conn); | ||
3774 | break; | ||
3775 | case ISTATE_SEND_NOPIN: | ||
3776 | ret = iscsit_send_nopin(cmd, conn); | ||
3777 | break; | ||
3778 | case ISTATE_SEND_REJECT: | ||
3779 | ret = iscsit_send_reject(cmd, conn); | ||
3780 | break; | ||
3781 | case ISTATE_SEND_TASKMGTRSP: | ||
3782 | ret = iscsit_send_task_mgt_rsp(cmd, conn); | ||
3783 | if (ret != 0) | ||
3787 | break; | 3784 | break; |
3788 | case ISTATE_SEND_REJECT: | 3785 | ret = iscsit_tmr_post_handler(cmd, conn); |
3789 | if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) { | 3786 | if (ret != 0) |
3790 | cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN; | 3787 | iscsit_fall_back_to_erl0(conn->sess); |
3791 | complete(&cmd->reject_comp); | 3788 | break; |
3792 | goto err; | 3789 | case ISTATE_SEND_TEXTRSP: |
3793 | } | 3790 | ret = iscsit_send_text_rsp(cmd, conn); |
3791 | break; | ||
3792 | default: | ||
3793 | pr_err("Unknown Opcode: 0x%02x ITT:" | ||
3794 | " 0x%08x, i_state: %d on CID: %hu\n", | ||
3795 | cmd->iscsi_opcode, cmd->init_task_tag, | ||
3796 | state, conn->cid); | ||
3797 | goto err; | ||
3798 | } | ||
3799 | if (ret < 0) | ||
3800 | goto err; | ||
3801 | |||
3802 | if (iscsit_send_tx_data(cmd, conn, 1) < 0) { | ||
3803 | iscsit_tx_thread_wait_for_tcp(conn); | ||
3804 | iscsit_unmap_iovec(cmd); | ||
3805 | goto err; | ||
3806 | } | ||
3807 | iscsit_unmap_iovec(cmd); | ||
3808 | |||
3809 | switch (state) { | ||
3810 | case ISTATE_SEND_LOGOUTRSP: | ||
3811 | if (!iscsit_logout_post_handler(cmd, conn)) | ||
3812 | goto restart; | ||
3813 | /* fall through */ | ||
3814 | case ISTATE_SEND_STATUS: | ||
3815 | case ISTATE_SEND_ASYNCMSG: | ||
3816 | case ISTATE_SEND_NOPIN: | ||
3817 | case ISTATE_SEND_STATUS_RECOVERY: | ||
3818 | case ISTATE_SEND_TEXTRSP: | ||
3819 | case ISTATE_SEND_TASKMGTRSP: | ||
3820 | spin_lock_bh(&cmd->istate_lock); | ||
3821 | cmd->i_state = ISTATE_SENT_STATUS; | ||
3822 | spin_unlock_bh(&cmd->istate_lock); | ||
3823 | break; | ||
3824 | case ISTATE_SEND_REJECT: | ||
3825 | if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) { | ||
3826 | cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN; | ||
3794 | complete(&cmd->reject_comp); | 3827 | complete(&cmd->reject_comp); |
3795 | break; | ||
3796 | default: | ||
3797 | pr_err("Unknown Opcode: 0x%02x ITT:" | ||
3798 | " 0x%08x, i_state: %d on CID: %hu\n", | ||
3799 | cmd->iscsi_opcode, cmd->init_task_tag, | ||
3800 | cmd->i_state, conn->cid); | ||
3801 | goto err; | 3828 | goto err; |
3802 | } | 3829 | } |
3803 | 3830 | complete(&cmd->reject_comp); | |
3804 | if (atomic_read(&conn->check_immediate_queue)) | 3831 | break; |
3805 | return 1; | 3832 | default: |
3833 | pr_err("Unknown Opcode: 0x%02x ITT:" | ||
3834 | " 0x%08x, i_state: %d on CID: %hu\n", | ||
3835 | cmd->iscsi_opcode, cmd->init_task_tag, | ||
3836 | cmd->i_state, conn->cid); | ||
3837 | goto err; | ||
3806 | } | 3838 | } |
3807 | 3839 | ||
3840 | if (atomic_read(&conn->check_immediate_queue)) | ||
3841 | return 1; | ||
3842 | |||
3808 | return 0; | 3843 | return 0; |
3809 | 3844 | ||
3810 | err: | 3845 | err: |
@@ -3813,6 +3848,27 @@ restart: | |||
3813 | return -EAGAIN; | 3848 | return -EAGAIN; |
3814 | } | 3849 | } |
3815 | 3850 | ||
3851 | static int iscsit_handle_response_queue(struct iscsi_conn *conn) | ||
3852 | { | ||
3853 | struct iscsit_transport *t = conn->conn_transport; | ||
3854 | struct iscsi_queue_req *qr; | ||
3855 | struct iscsi_cmd *cmd; | ||
3856 | u8 state; | ||
3857 | int ret; | ||
3858 | |||
3859 | while ((qr = iscsit_get_cmd_from_response_queue(conn))) { | ||
3860 | cmd = qr->cmd; | ||
3861 | state = qr->state; | ||
3862 | kmem_cache_free(lio_qr_cache, qr); | ||
3863 | |||
3864 | ret = t->iscsit_response_queue(conn, cmd, state); | ||
3865 | if (ret == 1 || ret < 0) | ||
3866 | return ret; | ||
3867 | } | ||
3868 | |||
3869 | return 0; | ||
3870 | } | ||
3871 | |||
3816 | int iscsi_target_tx_thread(void *arg) | 3872 | int iscsi_target_tx_thread(void *arg) |
3817 | { | 3873 | { |
3818 | int ret = 0; | 3874 | int ret = 0; |
@@ -3847,11 +3903,11 @@ restart: | |||
3847 | goto transport_err; | 3903 | goto transport_err; |
3848 | 3904 | ||
3849 | get_immediate: | 3905 | get_immediate: |
3850 | ret = handle_immediate_queue(conn); | 3906 | ret = iscsit_handle_immediate_queue(conn); |
3851 | if (ret < 0) | 3907 | if (ret < 0) |
3852 | goto transport_err; | 3908 | goto transport_err; |
3853 | 3909 | ||
3854 | ret = handle_response_queue(conn); | 3910 | ret = iscsit_handle_response_queue(conn); |
3855 | if (ret == 1) | 3911 | if (ret == 1) |
3856 | goto get_immediate; | 3912 | goto get_immediate; |
3857 | else if (ret == -EAGAIN) | 3913 | else if (ret == -EAGAIN) |
@@ -4451,7 +4507,7 @@ static void iscsit_logout_post_handler_diffcid( | |||
4451 | /* | 4507 | /* |
4452 | * Return of 0 causes the TX thread to restart. | 4508 | * Return of 0 causes the TX thread to restart. |
4453 | */ | 4509 | */ |
4454 | static int iscsit_logout_post_handler( | 4510 | int iscsit_logout_post_handler( |
4455 | struct iscsi_cmd *cmd, | 4511 | struct iscsi_cmd *cmd, |
4456 | struct iscsi_conn *conn) | 4512 | struct iscsi_conn *conn) |
4457 | { | 4513 | { |
@@ -4509,6 +4565,7 @@ static int iscsit_logout_post_handler( | |||
4509 | } | 4565 | } |
4510 | return ret; | 4566 | return ret; |
4511 | } | 4567 | } |
4568 | EXPORT_SYMBOL(iscsit_logout_post_handler); | ||
4512 | 4569 | ||
4513 | void iscsit_fail_session(struct iscsi_session *sess) | 4570 | void iscsit_fail_session(struct iscsi_session *sess) |
4514 | { | 4571 | { |
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index ce3d3210fe41..2704daf6ba74 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <target/target_core_fabric_configfs.h> | 27 | #include <target/target_core_fabric_configfs.h> |
28 | #include <target/target_core_configfs.h> | 28 | #include <target/target_core_configfs.h> |
29 | #include <target/configfs_macros.h> | 29 | #include <target/configfs_macros.h> |
30 | #include <target/iscsi/iscsi_transport.h> | ||
30 | 31 | ||
31 | #include "iscsi_target_core.h" | 32 | #include "iscsi_target_core.h" |
32 | #include "iscsi_target_parameters.h" | 33 | #include "iscsi_target_parameters.h" |
@@ -1536,7 +1537,8 @@ static int lio_queue_data_in(struct se_cmd *se_cmd) | |||
1536 | struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); | 1537 | struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); |
1537 | 1538 | ||
1538 | cmd->i_state = ISTATE_SEND_DATAIN; | 1539 | cmd->i_state = ISTATE_SEND_DATAIN; |
1539 | iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); | 1540 | cmd->conn->conn_transport->iscsit_queue_data_in(cmd->conn, cmd); |
1541 | |||
1540 | return 0; | 1542 | return 0; |
1541 | } | 1543 | } |
1542 | 1544 | ||
@@ -1568,7 +1570,8 @@ static int lio_queue_status(struct se_cmd *se_cmd) | |||
1568 | struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); | 1570 | struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); |
1569 | 1571 | ||
1570 | cmd->i_state = ISTATE_SEND_STATUS; | 1572 | cmd->i_state = ISTATE_SEND_STATUS; |
1571 | iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); | 1573 | cmd->conn->conn_transport->iscsit_queue_status(cmd->conn, cmd); |
1574 | |||
1572 | return 0; | 1575 | return 0; |
1573 | } | 1576 | } |
1574 | 1577 | ||
diff --git a/drivers/target/iscsi/iscsi_target_device.c b/drivers/target/iscsi/iscsi_target_device.c index bcc409853a67..1b74033510a0 100644 --- a/drivers/target/iscsi/iscsi_target_device.c +++ b/drivers/target/iscsi/iscsi_target_device.c | |||
@@ -60,8 +60,13 @@ void iscsit_increment_maxcmdsn(struct iscsi_cmd *cmd, struct iscsi_session *sess | |||
60 | 60 | ||
61 | cmd->maxcmdsn_inc = 1; | 61 | cmd->maxcmdsn_inc = 1; |
62 | 62 | ||
63 | mutex_lock(&sess->cmdsn_mutex); | 63 | if (!mutex_trylock(&sess->cmdsn_mutex)) { |
64 | sess->max_cmd_sn += 1; | ||
65 | pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn); | ||
66 | return; | ||
67 | } | ||
64 | sess->max_cmd_sn += 1; | 68 | sess->max_cmd_sn += 1; |
65 | pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn); | 69 | pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn); |
66 | mutex_unlock(&sess->cmdsn_mutex); | 70 | mutex_unlock(&sess->cmdsn_mutex); |
67 | } | 71 | } |
72 | EXPORT_SYMBOL(iscsit_increment_maxcmdsn); | ||
diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c index 16ca0ef9266f..b997e5da47d3 100644 --- a/drivers/target/iscsi/iscsi_target_tmr.c +++ b/drivers/target/iscsi/iscsi_target_tmr.c | |||
@@ -472,6 +472,7 @@ int iscsit_tmr_post_handler(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | |||
472 | 472 | ||
473 | return 0; | 473 | return 0; |
474 | } | 474 | } |
475 | EXPORT_SYMBOL(iscsit_tmr_post_handler); | ||
475 | 476 | ||
476 | /* | 477 | /* |
477 | * Nothing to do here, but leave it for good measure. :-) | 478 | * Nothing to do here, but leave it for good measure. :-) |