target: Propigate up ->cmd_kref put return via transport_generic_free_cmd

Go ahead and propigate up the ->cmd_kref put return value from
target_put_sess_cmd() -> transport_release_cmd() -> transport_put_cmd()
-> transport_generic_free_cmd().

This is useful for certain fabrics when determining the active I/O
shutdown case with SCF_ACK_KREF where a final target_put_sess_cmd()
is still required by the caller.

Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Nicholas Bellinger 2013-05-31 00:46:11 -07:00
parent cea4dcfdad
commit d5ddad4168
2 changed files with 16 additions and 14 deletions

View File

@ -65,7 +65,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd);
static void transport_handle_queue_full(struct se_cmd *cmd, static void transport_handle_queue_full(struct se_cmd *cmd,
struct se_device *dev); struct se_device *dev);
static int transport_generic_get_mem(struct se_cmd *cmd); static int transport_generic_get_mem(struct se_cmd *cmd);
static void transport_put_cmd(struct se_cmd *cmd); static int transport_put_cmd(struct se_cmd *cmd);
static void target_complete_ok_work(struct work_struct *work); static void target_complete_ok_work(struct work_struct *work);
int init_se_kmem_caches(void) int init_se_kmem_caches(void)
@ -1944,7 +1944,7 @@ static inline void transport_free_pages(struct se_cmd *cmd)
* This routine unconditionally frees a command, and reference counting * This routine unconditionally frees a command, and reference counting
* or list removal must be done in the caller. * or list removal must be done in the caller.
*/ */
static void transport_release_cmd(struct se_cmd *cmd) static int transport_release_cmd(struct se_cmd *cmd)
{ {
BUG_ON(!cmd->se_tfo); BUG_ON(!cmd->se_tfo);
@ -1956,11 +1956,11 @@ static void transport_release_cmd(struct se_cmd *cmd)
* If this cmd has been setup with target_get_sess_cmd(), drop * If this cmd has been setup with target_get_sess_cmd(), drop
* the kref and call ->release_cmd() in kref callback. * the kref and call ->release_cmd() in kref callback.
*/ */
if (cmd->check_release != 0) { if (cmd->check_release != 0)
target_put_sess_cmd(cmd->se_sess, cmd); return target_put_sess_cmd(cmd->se_sess, cmd);
return;
}
cmd->se_tfo->release_cmd(cmd); cmd->se_tfo->release_cmd(cmd);
return 1;
} }
/** /**
@ -1969,7 +1969,7 @@ static void transport_release_cmd(struct se_cmd *cmd)
* *
* This routine releases our reference to the command and frees it if possible. * This routine releases our reference to the command and frees it if possible.
*/ */
static void transport_put_cmd(struct se_cmd *cmd) static int transport_put_cmd(struct se_cmd *cmd)
{ {
unsigned long flags; unsigned long flags;
@ -1977,7 +1977,7 @@ static void transport_put_cmd(struct se_cmd *cmd)
if (atomic_read(&cmd->t_fe_count) && if (atomic_read(&cmd->t_fe_count) &&
!atomic_dec_and_test(&cmd->t_fe_count)) { !atomic_dec_and_test(&cmd->t_fe_count)) {
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
return; return 0;
} }
if (cmd->transport_state & CMD_T_DEV_ACTIVE) { if (cmd->transport_state & CMD_T_DEV_ACTIVE) {
@ -1987,8 +1987,7 @@ static void transport_put_cmd(struct se_cmd *cmd)
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
transport_free_pages(cmd); transport_free_pages(cmd);
transport_release_cmd(cmd); return transport_release_cmd(cmd);
return;
} }
void *transport_kmap_data_sg(struct se_cmd *cmd) void *transport_kmap_data_sg(struct se_cmd *cmd)
@ -2153,13 +2152,15 @@ static void transport_write_pending_qf(struct se_cmd *cmd)
} }
} }
void 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)
{ {
int ret = 0;
if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) { if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {
if (wait_for_tasks && (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) if (wait_for_tasks && (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
transport_wait_for_tasks(cmd); transport_wait_for_tasks(cmd);
transport_release_cmd(cmd); ret = transport_release_cmd(cmd);
} else { } else {
if (wait_for_tasks) if (wait_for_tasks)
transport_wait_for_tasks(cmd); transport_wait_for_tasks(cmd);
@ -2167,8 +2168,9 @@ void 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);
transport_put_cmd(cmd); ret = transport_put_cmd(cmd);
} }
return ret;
} }
EXPORT_SYMBOL(transport_generic_free_cmd); EXPORT_SYMBOL(transport_generic_free_cmd);

View File

@ -114,7 +114,7 @@ sense_reason_t transport_generic_new_cmd(struct se_cmd *);
void target_execute_cmd(struct se_cmd *cmd); void target_execute_cmd(struct se_cmd *cmd);
void transport_generic_free_cmd(struct se_cmd *, int); int transport_generic_free_cmd(struct se_cmd *, int);
bool transport_wait_for_tasks(struct se_cmd *); bool transport_wait_for_tasks(struct se_cmd *);
int transport_check_aborted_status(struct se_cmd *, int); int transport_check_aborted_status(struct se_cmd *, int);