diff options
| -rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 12 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_erl2.c | 12 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 50 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_util.h | 2 |
4 files changed, 50 insertions, 26 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 262ef1f23b38..d7705e5824fb 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
| @@ -651,7 +651,7 @@ static int iscsit_add_reject( | |||
| 651 | cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); | 651 | cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); |
| 652 | if (!cmd->buf_ptr) { | 652 | if (!cmd->buf_ptr) { |
| 653 | pr_err("Unable to allocate memory for cmd->buf_ptr\n"); | 653 | pr_err("Unable to allocate memory for cmd->buf_ptr\n"); |
| 654 | iscsit_release_cmd(cmd); | 654 | iscsit_free_cmd(cmd, false); |
| 655 | return -1; | 655 | return -1; |
| 656 | } | 656 | } |
| 657 | 657 | ||
| @@ -697,7 +697,7 @@ int iscsit_add_reject_from_cmd( | |||
| 697 | cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); | 697 | cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); |
| 698 | if (!cmd->buf_ptr) { | 698 | if (!cmd->buf_ptr) { |
| 699 | pr_err("Unable to allocate memory for cmd->buf_ptr\n"); | 699 | pr_err("Unable to allocate memory for cmd->buf_ptr\n"); |
| 700 | iscsit_release_cmd(cmd); | 700 | iscsit_free_cmd(cmd, false); |
| 701 | return -1; | 701 | return -1; |
| 702 | } | 702 | } |
| 703 | 703 | ||
| @@ -1743,7 +1743,7 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
| 1743 | return 0; | 1743 | return 0; |
| 1744 | out: | 1744 | out: |
| 1745 | if (cmd) | 1745 | if (cmd) |
| 1746 | iscsit_release_cmd(cmd); | 1746 | iscsit_free_cmd(cmd, false); |
| 1747 | ping_out: | 1747 | ping_out: |
| 1748 | kfree(ping_data); | 1748 | kfree(ping_data); |
| 1749 | return ret; | 1749 | return ret; |
| @@ -2251,7 +2251,7 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
| 2251 | if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) { | 2251 | if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) { |
| 2252 | pr_err("Received logout request on connection that" | 2252 | pr_err("Received logout request on connection that" |
| 2253 | " is not in logged in state, ignoring request.\n"); | 2253 | " is not in logged in state, ignoring request.\n"); |
| 2254 | iscsit_release_cmd(cmd); | 2254 | iscsit_free_cmd(cmd, false); |
| 2255 | return 0; | 2255 | return 0; |
| 2256 | } | 2256 | } |
| 2257 | 2257 | ||
| @@ -3665,7 +3665,7 @@ iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state | |||
| 3665 | list_del(&cmd->i_conn_node); | 3665 | list_del(&cmd->i_conn_node); |
| 3666 | spin_unlock_bh(&conn->cmd_lock); | 3666 | spin_unlock_bh(&conn->cmd_lock); |
| 3667 | 3667 | ||
| 3668 | iscsit_free_cmd(cmd); | 3668 | iscsit_free_cmd(cmd, false); |
| 3669 | break; | 3669 | break; |
| 3670 | case ISTATE_SEND_NOPIN_WANT_RESPONSE: | 3670 | case ISTATE_SEND_NOPIN_WANT_RESPONSE: |
| 3671 | iscsit_mod_nopin_response_timer(conn); | 3671 | iscsit_mod_nopin_response_timer(conn); |
| @@ -4122,7 +4122,7 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn) | |||
| 4122 | 4122 | ||
| 4123 | iscsit_increment_maxcmdsn(cmd, sess); | 4123 | iscsit_increment_maxcmdsn(cmd, sess); |
| 4124 | 4124 | ||
| 4125 | iscsit_free_cmd(cmd); | 4125 | iscsit_free_cmd(cmd, true); |
| 4126 | 4126 | ||
| 4127 | spin_lock_bh(&conn->cmd_lock); | 4127 | spin_lock_bh(&conn->cmd_lock); |
| 4128 | } | 4128 | } |
diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c index ba6091bf93fc..45a5afd5ea13 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.c +++ b/drivers/target/iscsi/iscsi_target_erl2.c | |||
| @@ -143,7 +143,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess) | |||
| 143 | list_del(&cmd->i_conn_node); | 143 | list_del(&cmd->i_conn_node); |
| 144 | cmd->conn = NULL; | 144 | cmd->conn = NULL; |
| 145 | spin_unlock(&cr->conn_recovery_cmd_lock); | 145 | spin_unlock(&cr->conn_recovery_cmd_lock); |
| 146 | iscsit_free_cmd(cmd); | 146 | iscsit_free_cmd(cmd, true); |
| 147 | spin_lock(&cr->conn_recovery_cmd_lock); | 147 | spin_lock(&cr->conn_recovery_cmd_lock); |
| 148 | } | 148 | } |
| 149 | spin_unlock(&cr->conn_recovery_cmd_lock); | 149 | spin_unlock(&cr->conn_recovery_cmd_lock); |
| @@ -165,7 +165,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess) | |||
| 165 | list_del(&cmd->i_conn_node); | 165 | list_del(&cmd->i_conn_node); |
| 166 | cmd->conn = NULL; | 166 | cmd->conn = NULL; |
| 167 | spin_unlock(&cr->conn_recovery_cmd_lock); | 167 | spin_unlock(&cr->conn_recovery_cmd_lock); |
| 168 | iscsit_free_cmd(cmd); | 168 | iscsit_free_cmd(cmd, true); |
| 169 | spin_lock(&cr->conn_recovery_cmd_lock); | 169 | spin_lock(&cr->conn_recovery_cmd_lock); |
| 170 | } | 170 | } |
| 171 | spin_unlock(&cr->conn_recovery_cmd_lock); | 171 | spin_unlock(&cr->conn_recovery_cmd_lock); |
| @@ -248,7 +248,7 @@ void iscsit_discard_cr_cmds_by_expstatsn( | |||
| 248 | iscsit_remove_cmd_from_connection_recovery(cmd, sess); | 248 | iscsit_remove_cmd_from_connection_recovery(cmd, sess); |
| 249 | 249 | ||
| 250 | spin_unlock(&cr->conn_recovery_cmd_lock); | 250 | spin_unlock(&cr->conn_recovery_cmd_lock); |
| 251 | iscsit_free_cmd(cmd); | 251 | iscsit_free_cmd(cmd, true); |
| 252 | spin_lock(&cr->conn_recovery_cmd_lock); | 252 | spin_lock(&cr->conn_recovery_cmd_lock); |
| 253 | } | 253 | } |
| 254 | spin_unlock(&cr->conn_recovery_cmd_lock); | 254 | spin_unlock(&cr->conn_recovery_cmd_lock); |
| @@ -302,7 +302,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn) | |||
| 302 | list_del(&cmd->i_conn_node); | 302 | list_del(&cmd->i_conn_node); |
| 303 | 303 | ||
| 304 | spin_unlock_bh(&conn->cmd_lock); | 304 | spin_unlock_bh(&conn->cmd_lock); |
| 305 | iscsit_free_cmd(cmd); | 305 | iscsit_free_cmd(cmd, true); |
| 306 | spin_lock_bh(&conn->cmd_lock); | 306 | spin_lock_bh(&conn->cmd_lock); |
| 307 | } | 307 | } |
| 308 | spin_unlock_bh(&conn->cmd_lock); | 308 | spin_unlock_bh(&conn->cmd_lock); |
| @@ -355,7 +355,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) | |||
| 355 | 355 | ||
| 356 | list_del(&cmd->i_conn_node); | 356 | list_del(&cmd->i_conn_node); |
| 357 | spin_unlock_bh(&conn->cmd_lock); | 357 | spin_unlock_bh(&conn->cmd_lock); |
| 358 | iscsit_free_cmd(cmd); | 358 | iscsit_free_cmd(cmd, true); |
| 359 | spin_lock_bh(&conn->cmd_lock); | 359 | spin_lock_bh(&conn->cmd_lock); |
| 360 | continue; | 360 | continue; |
| 361 | } | 361 | } |
| @@ -375,7 +375,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) | |||
| 375 | iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) { | 375 | iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) { |
| 376 | list_del(&cmd->i_conn_node); | 376 | list_del(&cmd->i_conn_node); |
| 377 | spin_unlock_bh(&conn->cmd_lock); | 377 | spin_unlock_bh(&conn->cmd_lock); |
| 378 | iscsit_free_cmd(cmd); | 378 | iscsit_free_cmd(cmd, true); |
| 379 | spin_lock_bh(&conn->cmd_lock); | 379 | spin_lock_bh(&conn->cmd_lock); |
| 380 | continue; | 380 | continue; |
| 381 | } | 381 | } |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 2cc6c9a3ffb8..08a3bacef0c5 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
| @@ -676,40 +676,56 @@ void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn) | |||
| 676 | 676 | ||
| 677 | void iscsit_release_cmd(struct iscsi_cmd *cmd) | 677 | void iscsit_release_cmd(struct iscsi_cmd *cmd) |
| 678 | { | 678 | { |
| 679 | struct iscsi_conn *conn = cmd->conn; | ||
| 680 | |||
| 681 | iscsit_free_r2ts_from_list(cmd); | ||
| 682 | iscsit_free_all_datain_reqs(cmd); | ||
| 683 | |||
| 684 | kfree(cmd->buf_ptr); | 679 | kfree(cmd->buf_ptr); |
| 685 | kfree(cmd->pdu_list); | 680 | kfree(cmd->pdu_list); |
| 686 | kfree(cmd->seq_list); | 681 | kfree(cmd->seq_list); |
| 687 | kfree(cmd->tmr_req); | 682 | kfree(cmd->tmr_req); |
| 688 | kfree(cmd->iov_data); | 683 | kfree(cmd->iov_data); |
| 689 | 684 | ||
| 690 | if (conn) { | 685 | kmem_cache_free(lio_cmd_cache, cmd); |
| 686 | } | ||
| 687 | |||
| 688 | static void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool scsi_cmd, | ||
| 689 | bool check_queues) | ||
| 690 | { | ||
| 691 | struct iscsi_conn *conn = cmd->conn; | ||
| 692 | |||
| 693 | if (scsi_cmd) { | ||
| 694 | if (cmd->data_direction == DMA_TO_DEVICE) { | ||
| 695 | iscsit_stop_dataout_timer(cmd); | ||
| 696 | iscsit_free_r2ts_from_list(cmd); | ||
| 697 | } | ||
| 698 | if (cmd->data_direction == DMA_FROM_DEVICE) | ||
| 699 | iscsit_free_all_datain_reqs(cmd); | ||
| 700 | } | ||
| 701 | |||
| 702 | if (conn && check_queues) { | ||
| 691 | iscsit_remove_cmd_from_immediate_queue(cmd, conn); | 703 | iscsit_remove_cmd_from_immediate_queue(cmd, conn); |
| 692 | iscsit_remove_cmd_from_response_queue(cmd, conn); | 704 | iscsit_remove_cmd_from_response_queue(cmd, conn); |
| 693 | } | 705 | } |
| 694 | |||
| 695 | kmem_cache_free(lio_cmd_cache, cmd); | ||
| 696 | } | 706 | } |
| 697 | 707 | ||
| 698 | void iscsit_free_cmd(struct iscsi_cmd *cmd) | 708 | void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown) |
| 699 | { | 709 | { |
| 710 | struct se_cmd *se_cmd = NULL; | ||
| 711 | int rc; | ||
| 700 | /* | 712 | /* |
| 701 | * Determine if a struct se_cmd is associated with | 713 | * Determine if a struct se_cmd is associated with |
| 702 | * this struct iscsi_cmd. | 714 | * this struct iscsi_cmd. |
| 703 | */ | 715 | */ |
| 704 | switch (cmd->iscsi_opcode) { | 716 | switch (cmd->iscsi_opcode) { |
| 705 | case ISCSI_OP_SCSI_CMD: | 717 | case ISCSI_OP_SCSI_CMD: |
| 706 | if (cmd->data_direction == DMA_TO_DEVICE) | 718 | se_cmd = &cmd->se_cmd; |
| 707 | iscsit_stop_dataout_timer(cmd); | 719 | __iscsit_free_cmd(cmd, true, shutdown); |
| 708 | /* | 720 | /* |
| 709 | * Fallthrough | 721 | * Fallthrough |
| 710 | */ | 722 | */ |
| 711 | case ISCSI_OP_SCSI_TMFUNC: | 723 | case ISCSI_OP_SCSI_TMFUNC: |
| 712 | transport_generic_free_cmd(&cmd->se_cmd, 1); | 724 | rc = transport_generic_free_cmd(&cmd->se_cmd, 1); |
| 725 | if (!rc && shutdown && se_cmd && se_cmd->se_sess) { | ||
| 726 | __iscsit_free_cmd(cmd, true, shutdown); | ||
| 727 | target_put_sess_cmd(se_cmd->se_sess, se_cmd); | ||
| 728 | } | ||
| 713 | break; | 729 | break; |
| 714 | case ISCSI_OP_REJECT: | 730 | case ISCSI_OP_REJECT: |
| 715 | /* | 731 | /* |
| @@ -718,11 +734,19 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd) | |||
| 718 | * associated cmd->se_cmd needs to be released. | 734 | * associated cmd->se_cmd needs to be released. |
| 719 | */ | 735 | */ |
| 720 | if (cmd->se_cmd.se_tfo != NULL) { | 736 | if (cmd->se_cmd.se_tfo != NULL) { |
| 721 | transport_generic_free_cmd(&cmd->se_cmd, 1); | 737 | se_cmd = &cmd->se_cmd; |
| 738 | __iscsit_free_cmd(cmd, true, shutdown); | ||
| 739 | |||
| 740 | rc = transport_generic_free_cmd(&cmd->se_cmd, 1); | ||
| 741 | if (!rc && shutdown && se_cmd->se_sess) { | ||
| 742 | __iscsit_free_cmd(cmd, true, shutdown); | ||
| 743 | target_put_sess_cmd(se_cmd->se_sess, se_cmd); | ||
| 744 | } | ||
| 722 | break; | 745 | break; |
| 723 | } | 746 | } |
| 724 | /* Fall-through */ | 747 | /* Fall-through */ |
| 725 | default: | 748 | default: |
| 749 | __iscsit_free_cmd(cmd, false, shutdown); | ||
| 726 | cmd->release_cmd(cmd); | 750 | cmd->release_cmd(cmd); |
| 727 | break; | 751 | break; |
| 728 | } | 752 | } |
diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 4f8e01a47081..a4422659d049 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h | |||
| @@ -29,7 +29,7 @@ extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_co | |||
| 29 | extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *); | 29 | extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *); |
| 30 | extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *); | 30 | extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *); |
| 31 | extern void iscsit_release_cmd(struct iscsi_cmd *); | 31 | extern void iscsit_release_cmd(struct iscsi_cmd *); |
| 32 | extern void iscsit_free_cmd(struct iscsi_cmd *); | 32 | extern void iscsit_free_cmd(struct iscsi_cmd *, bool); |
| 33 | extern int iscsit_check_session_usage_count(struct iscsi_session *); | 33 | extern int iscsit_check_session_usage_count(struct iscsi_session *); |
| 34 | extern void iscsit_dec_session_usage_count(struct iscsi_session *); | 34 | extern void iscsit_dec_session_usage_count(struct iscsi_session *); |
| 35 | extern void iscsit_inc_session_usage_count(struct iscsi_session *); | 35 | extern void iscsit_inc_session_usage_count(struct iscsi_session *); |
