Keep track in .refcnt of whether or not target_put_sess_cmd() has already been called. Signed-off-by: Bart Van Assche <bart.vanassche@xxxxxxxxxxx> --- drivers/target/iscsi/cxgbit/cxgbit_target.c | 2 +- drivers/target/iscsi/iscsi_target.c | 16 ++++++------- drivers/target/iscsi/iscsi_target_configfs.c | 4 +++- drivers/target/iscsi/iscsi_target_util.c | 35 +++++++++++++++++++++++++++- include/target/iscsi/iscsi_target_core.h | 1 + include/target/iscsi/iscsi_transport.h | 2 ++ 6 files changed, 49 insertions(+), 11 deletions(-) diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index bdcc8b4c522a..528a25e6cfbd 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -956,7 +956,7 @@ cxgbit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, return -1; if (cmd->sense_reason || cmdsn_ret == CMDSN_LOWER_THAN_EXP) { - target_put_sess_cmd(&cmd->se_cmd); + iscsit_put_cmd(cmd); return 0; } else if (cmd->unsolicited_data) { iscsit_set_unsoliticed_dataout(cmd); diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 73d8eaa0973b..de6b2e430d1a 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -872,8 +872,8 @@ static int iscsit_add_reject_from_cmd( * scsit_setup_scsi_cmd() */ if (cmd->se_cmd.se_tfo != NULL) { - pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n"); - target_put_sess_cmd(&cmd->se_cmd); + pr_debug("iscsi reject: calling iscsit_put_cmd() >>>>>>\n"); + iscsit_put_cmd(cmd); } return -1; } @@ -1167,7 +1167,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length, conn->cid); - target_get_sess_cmd(&cmd->se_cmd, true); + iscsit_get_cmd(cmd); cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, scsilun_to_int(&hdr->lun)); @@ -1235,7 +1235,7 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) return -1; else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { - target_put_sess_cmd(&cmd->se_cmd); + iscsit_put_cmd(cmd); return 0; } } @@ -1251,7 +1251,7 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (!cmd->sense_reason) return 0; - target_put_sess_cmd(&cmd->se_cmd); + iscsit_put_cmd(cmd); return 0; } @@ -1308,7 +1308,7 @@ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, rc = iscsit_dump_data_payload(cmd->conn, cmd->first_burst_len, 1); - target_put_sess_cmd(&cmd->se_cmd); + iscsit_put_cmd(cmd); return rc; } else if (cmd->unsolicited_data) iscsit_set_unsoliticed_dataout(cmd); @@ -2015,7 +2015,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, conn->sess->se_sess, 0, DMA_NONE, TCM_SIMPLE_TAG, cmd->sense_buffer + 2); - target_get_sess_cmd(&cmd->se_cmd, true); + iscsit_get_cmd(cmd); sess_ref = true; tcm_function = iscsit_convert_tmf(function); if (tcm_function == TMR_UNKNOWN) { @@ -2134,7 +2134,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, */ if (sess_ref) { pr_debug("Handle TMR, using sess_ref=true check\n"); - target_put_sess_cmd(&cmd->se_cmd); + iscsit_put_cmd(cmd); } iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index bf40f03755dd..39a7294dfac7 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -1559,7 +1559,9 @@ static void lio_set_default_node_attributes(struct se_node_acl *se_acl) static int lio_check_stop_free(struct se_cmd *se_cmd) { - return target_put_sess_cmd(se_cmd); + struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); + + return iscsit_put_cmd(cmd); } static void lio_release_cmd(struct se_cmd *se_cmd) diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 139746b3b189..1cacfe1003e3 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -688,6 +688,39 @@ void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn) spin_unlock_bh(&conn->response_queue_lock); } +/** + * iscsit_get_cmd - add @cmd to the list of active commands + * @cmd: iSCSI command. + */ +int iscsit_get_cmd(struct iscsi_cmd *cmd) +{ + long refcnt = atomic_read(&cmd->refcnt); + int ret; + + WARN_ONCE(refcnt != 0, "refcnt = %ld\n", refcnt); + ret = target_get_sess_cmd(&cmd->se_cmd, true); + if (ret) + return ret; + atomic_inc(&cmd->refcnt); + return ret; +} + +/** + * iscsit_put_cmd() - decrease the reference count of @cmd + * @cmd: iSCSI command. + * + * Note: this function must be called only once per command. + */ +int iscsit_put_cmd(struct iscsi_cmd *cmd) +{ + long refcnt = atomic_read(&cmd->refcnt); + + WARN_ONCE(refcnt <= 0, "refcnt = %ld\n", refcnt); + atomic_dec(&cmd->refcnt); + return target_put_sess_cmd(&cmd->se_cmd); +} +EXPORT_SYMBOL(iscsit_put_cmd); + void iscsit_release_cmd(struct iscsi_cmd *cmd) { struct iscsi_session *sess; @@ -744,7 +777,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown) rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown); if (!rc && shutdown && se_cmd && se_cmd->se_sess) { __iscsit_free_cmd(cmd, shutdown); - target_put_sess_cmd(se_cmd); + iscsit_put_cmd(cmd); } } else { iscsit_release_cmd(cmd); diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 275581d483dd..83afb5c80fcc 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -349,6 +349,7 @@ struct iscsi_r2t { } ____cacheline_aligned; struct iscsi_cmd { + atomic_t refcnt; enum iscsi_timer_flags_table dataout_timer_flags; /* DataOUT timeout retries */ u8 dataout_timeout_retries; diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index ff1a4f4cd66d..dd4aa931b14e 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -125,6 +125,8 @@ extern int iscsit_tmr_post_handler(struct iscsi_cmd *, struct iscsi_conn *); extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, int); extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, unsigned char *, __be32); +extern int iscsit_get_cmd(struct iscsi_cmd *cmd); +extern int iscsit_put_cmd(struct iscsi_cmd *cmd); extern void iscsit_release_cmd(struct iscsi_cmd *); extern void iscsit_free_cmd(struct iscsi_cmd *, bool); extern void iscsit_add_cmd_to_immediate_queue(struct iscsi_cmd *, -- 2.12.0 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html