diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-07-03 06:11:48 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-04 04:50:34 -0400 |
commit | c6ccbb9b6e24e35d71fd8706dfc5a8eab07f6937 (patch) | |
tree | 8ca00d0d33adf2cb6e683fa179d1473b5524bb2d | |
parent | d9e507c05ca19ad2ec166577edd8b47e17c8961e (diff) |
iscsi-target: Fix ISCSI_OP_SCSI_TMFUNC handling for iser
commit 186a9647019587b3784694894c4d136fd00cfd7b upstream.
This patch adds target_get_sess_cmd reference counting for
iscsit_handle_task_mgt_cmd(), and adds a target_put_sess_cmd()
for the failure case.
It also fixes a bug where ISCSI_OP_SCSI_TMFUNC type commands
where leaking iscsi_cmd->i_conn_node and eventually triggering
an OOPs during struct isert_conn shutdown.
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/infiniband/ulp/isert/ib_isert.c | 16 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 12 |
2 files changed, 18 insertions, 10 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 6b20a9d09cbb..bfc21798bd5e 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c | |||
@@ -1202,14 +1202,12 @@ isert_put_cmd(struct isert_cmd *isert_cmd) | |||
1202 | { | 1202 | { |
1203 | struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; | 1203 | struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; |
1204 | struct isert_conn *isert_conn = isert_cmd->conn; | 1204 | struct isert_conn *isert_conn = isert_cmd->conn; |
1205 | struct iscsi_conn *conn; | 1205 | struct iscsi_conn *conn = isert_conn->conn; |
1206 | 1206 | ||
1207 | pr_debug("Entering isert_put_cmd: %p\n", isert_cmd); | 1207 | pr_debug("Entering isert_put_cmd: %p\n", isert_cmd); |
1208 | 1208 | ||
1209 | switch (cmd->iscsi_opcode) { | 1209 | switch (cmd->iscsi_opcode) { |
1210 | case ISCSI_OP_SCSI_CMD: | 1210 | case ISCSI_OP_SCSI_CMD: |
1211 | conn = isert_conn->conn; | ||
1212 | |||
1213 | spin_lock_bh(&conn->cmd_lock); | 1211 | spin_lock_bh(&conn->cmd_lock); |
1214 | if (!list_empty(&cmd->i_conn_node)) | 1212 | if (!list_empty(&cmd->i_conn_node)) |
1215 | list_del(&cmd->i_conn_node); | 1213 | list_del(&cmd->i_conn_node); |
@@ -1219,16 +1217,18 @@ isert_put_cmd(struct isert_cmd *isert_cmd) | |||
1219 | iscsit_stop_dataout_timer(cmd); | 1217 | iscsit_stop_dataout_timer(cmd); |
1220 | 1218 | ||
1221 | isert_unmap_cmd(isert_cmd, isert_conn); | 1219 | isert_unmap_cmd(isert_cmd, isert_conn); |
1222 | /* | 1220 | transport_generic_free_cmd(&cmd->se_cmd, 0); |
1223 | * Fall-through | 1221 | break; |
1224 | */ | ||
1225 | case ISCSI_OP_SCSI_TMFUNC: | 1222 | case ISCSI_OP_SCSI_TMFUNC: |
1223 | spin_lock_bh(&conn->cmd_lock); | ||
1224 | if (!list_empty(&cmd->i_conn_node)) | ||
1225 | list_del(&cmd->i_conn_node); | ||
1226 | spin_unlock_bh(&conn->cmd_lock); | ||
1227 | |||
1226 | transport_generic_free_cmd(&cmd->se_cmd, 0); | 1228 | transport_generic_free_cmd(&cmd->se_cmd, 0); |
1227 | break; | 1229 | break; |
1228 | case ISCSI_OP_REJECT: | 1230 | case ISCSI_OP_REJECT: |
1229 | case ISCSI_OP_NOOP_OUT: | 1231 | case ISCSI_OP_NOOP_OUT: |
1230 | conn = isert_conn->conn; | ||
1231 | |||
1232 | spin_lock_bh(&conn->cmd_lock); | 1232 | spin_lock_bh(&conn->cmd_lock); |
1233 | if (!list_empty(&cmd->i_conn_node)) | 1233 | if (!list_empty(&cmd->i_conn_node)) |
1234 | list_del(&cmd->i_conn_node); | 1234 | list_del(&cmd->i_conn_node); |
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index d7705e5824fb..f1db6ee71006 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -1757,8 +1757,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1757 | struct se_tmr_req *se_tmr; | 1757 | struct se_tmr_req *se_tmr; |
1758 | struct iscsi_tmr_req *tmr_req; | 1758 | struct iscsi_tmr_req *tmr_req; |
1759 | struct iscsi_tm *hdr; | 1759 | struct iscsi_tm *hdr; |
1760 | int out_of_order_cmdsn = 0; | 1760 | int out_of_order_cmdsn = 0, ret; |
1761 | int ret; | 1761 | bool sess_ref = false; |
1762 | u8 function; | 1762 | u8 function; |
1763 | 1763 | ||
1764 | hdr = (struct iscsi_tm *) buf; | 1764 | hdr = (struct iscsi_tm *) buf; |
@@ -1814,6 +1814,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1814 | conn->sess->se_sess, 0, DMA_NONE, | 1814 | conn->sess->se_sess, 0, DMA_NONE, |
1815 | MSG_SIMPLE_TAG, cmd->sense_buffer + 2); | 1815 | MSG_SIMPLE_TAG, cmd->sense_buffer + 2); |
1816 | 1816 | ||
1817 | target_get_sess_cmd(conn->sess->se_sess, &cmd->se_cmd, true); | ||
1818 | sess_ref = true; | ||
1819 | |||
1817 | switch (function) { | 1820 | switch (function) { |
1818 | case ISCSI_TM_FUNC_ABORT_TASK: | 1821 | case ISCSI_TM_FUNC_ABORT_TASK: |
1819 | tcm_function = TMR_ABORT_TASK; | 1822 | tcm_function = TMR_ABORT_TASK; |
@@ -1956,6 +1959,11 @@ attach: | |||
1956 | * For connection recovery, this is also the default action for | 1959 | * For connection recovery, this is also the default action for |
1957 | * TMR TASK_REASSIGN. | 1960 | * TMR TASK_REASSIGN. |
1958 | */ | 1961 | */ |
1962 | if (sess_ref) { | ||
1963 | pr_debug("Handle TMR, using sess_ref=true check\n"); | ||
1964 | target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | ||
1965 | } | ||
1966 | |||
1959 | iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); | 1967 | iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); |
1960 | return 0; | 1968 | return 0; |
1961 | } | 1969 | } |