Commit 7b2cc7dc authored by Bart Van Assche's avatar Bart Van Assche Committed by Martin K. Petersen

scsi: target: Simplify the code for waiting for command completion

Instead of embedding the completion that is used for waiting for command
completion in struct se_cmd, let the context that waits for command
completion allocate it. This makes it possible to have a single code path
for non-aborted and aborted commands in target_release_cmd_kref() and
avoids that transport_generic_free_cmd() has to call
cmd->se_tfo->release_cmd() directly. This patch does not change any
functionality. Note: transport_generic_free_cmd() only waits until the
se_cmd reference count has reached zero after it has set both
CMD_T_FABRIC_STOP and CMD_T_ABORTED.
Signed-off-by: default avatarBart Van Assche <bart.vanassche@wdc.com>
Reviewed-by: default avatarMike Christie <mchristi@redhat.com>
Cc: Hannes Reinecke <hare@suse.com>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent edf46eee
...@@ -1309,7 +1309,7 @@ void transport_init_se_cmd( ...@@ -1309,7 +1309,7 @@ void transport_init_se_cmd(
INIT_LIST_HEAD(&cmd->se_cmd_list); INIT_LIST_HEAD(&cmd->se_cmd_list);
INIT_LIST_HEAD(&cmd->state_list); INIT_LIST_HEAD(&cmd->state_list);
init_completion(&cmd->t_transport_stop_comp); init_completion(&cmd->t_transport_stop_comp);
init_completion(&cmd->cmd_wait_comp); cmd->compl = NULL;
spin_lock_init(&cmd->t_state_lock); spin_lock_init(&cmd->t_state_lock);
INIT_WORK(&cmd->work, NULL); INIT_WORK(&cmd->work, NULL);
kref_init(&cmd->cmd_kref); kref_init(&cmd->cmd_kref);
...@@ -2658,6 +2658,7 @@ static void target_wait_free_cmd(struct se_cmd *cmd, bool *aborted, bool *tas) ...@@ -2658,6 +2658,7 @@ static void target_wait_free_cmd(struct se_cmd *cmd, bool *aborted, bool *tas)
*/ */
int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
{ {
DECLARE_COMPLETION_ONSTACK(compl);
int ret = 0; int ret = 0;
bool aborted = false, tas = false; bool aborted = false, tas = false;
...@@ -2676,12 +2677,13 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) ...@@ -2676,12 +2677,13 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
if (cmd->se_lun) if (cmd->se_lun)
transport_lun_remove_cmd(cmd); transport_lun_remove_cmd(cmd);
} }
if (aborted)
cmd->compl = &compl;
if (!aborted || tas) if (!aborted || tas)
ret = target_put_sess_cmd(cmd); ret = target_put_sess_cmd(cmd);
if (aborted) { if (aborted) {
pr_debug("Detected CMD_T_ABORTED for ITT: %llu\n", cmd->tag); pr_debug("Detected CMD_T_ABORTED for ITT: %llu\n", cmd->tag);
wait_for_completion(&cmd->cmd_wait_comp); wait_for_completion(&compl);
cmd->se_tfo->release_cmd(cmd);
ret = 1; ret = 1;
} }
return ret; return ret;
...@@ -2742,31 +2744,21 @@ static void target_release_cmd_kref(struct kref *kref) ...@@ -2742,31 +2744,21 @@ static void target_release_cmd_kref(struct kref *kref)
{ {
struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref); struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
struct se_session *se_sess = se_cmd->se_sess; struct se_session *se_sess = se_cmd->se_sess;
struct completion *compl = se_cmd->compl;
unsigned long flags; unsigned long flags;
bool fabric_stop;
if (se_sess) { if (se_sess) {
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
list_del_init(&se_cmd->se_cmd_list); list_del_init(&se_cmd->se_cmd_list);
if (list_empty(&se_sess->sess_cmd_list)) if (list_empty(&se_sess->sess_cmd_list))
wake_up(&se_sess->cmd_list_wq); wake_up(&se_sess->cmd_list_wq);
spin_lock(&se_cmd->t_state_lock);
fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP) &&
(se_cmd->transport_state & CMD_T_ABORTED);
spin_unlock(&se_cmd->t_state_lock);
if (fabric_stop) {
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
target_free_cmd_mem(se_cmd);
complete(&se_cmd->cmd_wait_comp);
return;
}
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
} }
target_free_cmd_mem(se_cmd); target_free_cmd_mem(se_cmd);
se_cmd->se_tfo->release_cmd(se_cmd); se_cmd->se_tfo->release_cmd(se_cmd);
if (compl)
complete(compl);
} }
/** /**
......
...@@ -475,7 +475,7 @@ struct se_cmd { ...@@ -475,7 +475,7 @@ struct se_cmd {
struct se_session *se_sess; struct se_session *se_sess;
struct se_tmr_req *se_tmr_req; struct se_tmr_req *se_tmr_req;
struct list_head se_cmd_list; struct list_head se_cmd_list;
struct completion cmd_wait_comp; struct completion *compl;
const struct target_core_fabric_ops *se_tfo; const struct target_core_fabric_ops *se_tfo;
sense_reason_t (*execute_cmd)(struct se_cmd *); sense_reason_t (*execute_cmd)(struct se_cmd *);
sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool, int *); sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool, int *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment