target: Make target_put_sess_cmd use target_release_cmd_kref

This patch moves target_put_sess_cmd() to use a se_cmd->cmd_kref
callback target_release_cmd_kref when performing driver release of
fabric->se_cmd descriptor memory.  It sets the default cmd_kref
count value to '2' within target_get_sess_cmd() setup, and
currently assumes TFO->check_stop_free() usage.

It drops se_tfo->check_release_cmd() usage in the main
transport_release_cmd codepath.

Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Nicholas Bellinger 2011-11-12 00:32:17 -08:00
parent ce136176fe
commit 7481deb413
2 changed files with 25 additions and 15 deletions

View File

@ -3349,13 +3349,13 @@ static void transport_release_cmd(struct se_cmd *cmd)
if (cmd->t_task_cdb != cmd->__t_task_cdb) if (cmd->t_task_cdb != cmd->__t_task_cdb)
kfree(cmd->t_task_cdb); kfree(cmd->t_task_cdb);
/* /*
* Check if target_wait_for_sess_cmds() is expecting to * If this cmd has been setup with target_get_sess_cmd(), drop
* release se_cmd directly here.. * the kref and call ->release_cmd() in kref callback.
*/ */
if (cmd->check_release != 0 && cmd->se_tfo->check_release_cmd) if (cmd->check_release != 0) {
if (cmd->se_tfo->check_release_cmd(cmd) != 0) target_put_sess_cmd(cmd->se_sess, cmd);
return; return;
}
cmd->se_tfo->release_cmd(cmd); cmd->se_tfo->release_cmd(cmd);
} }
@ -3915,6 +3915,9 @@ void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
{ {
unsigned long flags; unsigned long flags;
kref_init(&se_cmd->cmd_kref);
kref_get(&se_cmd->cmd_kref);
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list);
se_cmd->check_release = 1; se_cmd->check_release = 1;
@ -3922,30 +3925,36 @@ void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
} }
EXPORT_SYMBOL(target_get_sess_cmd); EXPORT_SYMBOL(target_get_sess_cmd);
/* target_put_sess_cmd - Check for active I/O shutdown or list delete static void target_release_cmd_kref(struct kref *kref)
* @se_sess: session to reference
* @se_cmd: command descriptor to drop
*/
int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
{ {
struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
struct se_session *se_sess = se_cmd->se_sess;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
if (list_empty(&se_cmd->se_cmd_list)) { if (list_empty(&se_cmd->se_cmd_list)) {
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
WARN_ON(1); WARN_ON(1);
return 0; return;
} }
if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) { if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) {
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
complete(&se_cmd->cmd_wait_comp); complete(&se_cmd->cmd_wait_comp);
return 1; return;
} }
list_del(&se_cmd->se_cmd_list); list_del(&se_cmd->se_cmd_list);
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
return 0; se_cmd->se_tfo->release_cmd(se_cmd);
}
/* target_put_sess_cmd - Check for active I/O shutdown via kref_put
* @se_sess: session to reference
* @se_cmd: command descriptor to drop
*/
int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
{
return kref_put(&se_cmd->cmd_kref, target_release_cmd_kref);
} }
EXPORT_SYMBOL(target_put_sess_cmd); EXPORT_SYMBOL(target_put_sess_cmd);

View File

@ -541,6 +541,7 @@ struct se_cmd {
struct list_head se_queue_node; struct list_head se_queue_node;
struct list_head se_cmd_list; struct list_head se_cmd_list;
struct completion cmd_wait_comp; struct completion cmd_wait_comp;
struct kref cmd_kref;
struct target_core_fabric_ops *se_tfo; struct target_core_fabric_ops *se_tfo;
int (*execute_task)(struct se_task *); int (*execute_task)(struct se_task *);
void (*transport_complete_callback)(struct se_cmd *); void (*transport_complete_callback)(struct se_cmd *);