aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-11-12 03:32:17 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2011-12-14 06:38:29 -0500
commit7481deb413be132a22193e8a0bce88b311ecb3c2 (patch)
tree6d417c6856f983cb28fae0717563f4efcd6019e1
parentce136176fea522fc8f4c16dcae7e8ed1d890ca39 (diff)
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>
-rw-r--r--drivers/target/target_core_transport.c39
-rw-r--r--include/target/target_core_base.h1
2 files changed, 25 insertions, 15 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 122925686de2..176f956665e8 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -3349,13 +3349,13 @@ static void transport_release_cmd(struct se_cmd *cmd)
3349 if (cmd->t_task_cdb != cmd->__t_task_cdb) 3349 if (cmd->t_task_cdb != cmd->__t_task_cdb)
3350 kfree(cmd->t_task_cdb); 3350 kfree(cmd->t_task_cdb);
3351 /* 3351 /*
3352 * Check if target_wait_for_sess_cmds() is expecting to 3352 * If this cmd has been setup with target_get_sess_cmd(), drop
3353 * release se_cmd directly here.. 3353 * the kref and call ->release_cmd() in kref callback.
3354 */ 3354 */
3355 if (cmd->check_release != 0 && cmd->se_tfo->check_release_cmd) 3355 if (cmd->check_release != 0) {
3356 if (cmd->se_tfo->check_release_cmd(cmd) != 0) 3356 target_put_sess_cmd(cmd->se_sess, cmd);
3357 return; 3357 return;
3358 3358 }
3359 cmd->se_tfo->release_cmd(cmd); 3359 cmd->se_tfo->release_cmd(cmd);
3360} 3360}
3361 3361
@@ -3915,6 +3915,9 @@ void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
3915{ 3915{
3916 unsigned long flags; 3916 unsigned long flags;
3917 3917
3918 kref_init(&se_cmd->cmd_kref);
3919 kref_get(&se_cmd->cmd_kref);
3920
3918 spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); 3921 spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
3919 list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); 3922 list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list);
3920 se_cmd->check_release = 1; 3923 se_cmd->check_release = 1;
@@ -3922,30 +3925,36 @@ void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
3922} 3925}
3923EXPORT_SYMBOL(target_get_sess_cmd); 3926EXPORT_SYMBOL(target_get_sess_cmd);
3924 3927
3925/* target_put_sess_cmd - Check for active I/O shutdown or list delete 3928static void target_release_cmd_kref(struct kref *kref)
3926 * @se_sess: session to reference
3927 * @se_cmd: command descriptor to drop
3928 */
3929int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
3930{ 3929{
3930 struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
3931 struct se_session *se_sess = se_cmd->se_sess;
3931 unsigned long flags; 3932 unsigned long flags;
3932 3933
3933 spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); 3934 spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
3934 if (list_empty(&se_cmd->se_cmd_list)) { 3935 if (list_empty(&se_cmd->se_cmd_list)) {
3935 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); 3936 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
3936 WARN_ON(1); 3937 WARN_ON(1);
3937 return 0; 3938 return;
3938 } 3939 }
3939
3940 if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) { 3940 if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) {
3941 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); 3941 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
3942 complete(&se_cmd->cmd_wait_comp); 3942 complete(&se_cmd->cmd_wait_comp);
3943 return 1; 3943 return;
3944 } 3944 }
3945 list_del(&se_cmd->se_cmd_list); 3945 list_del(&se_cmd->se_cmd_list);
3946 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); 3946 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
3947 3947
3948 return 0; 3948 se_cmd->se_tfo->release_cmd(se_cmd);
3949}
3950
3951/* target_put_sess_cmd - Check for active I/O shutdown via kref_put
3952 * @se_sess: session to reference
3953 * @se_cmd: command descriptor to drop
3954 */
3955int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
3956{
3957 return kref_put(&se_cmd->cmd_kref, target_release_cmd_kref);
3949} 3958}
3950EXPORT_SYMBOL(target_put_sess_cmd); 3959EXPORT_SYMBOL(target_put_sess_cmd);
3951 3960
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index cadd4f6e57e1..af088a9e4905 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -541,6 +541,7 @@ struct se_cmd {
541 struct list_head se_queue_node; 541 struct list_head se_queue_node;
542 struct list_head se_cmd_list; 542 struct list_head se_cmd_list;
543 struct completion cmd_wait_comp; 543 struct completion cmd_wait_comp;
544 struct kref cmd_kref;
544 struct target_core_fabric_ops *se_tfo; 545 struct target_core_fabric_ops *se_tfo;
545 int (*execute_task)(struct se_task *); 546 int (*execute_task)(struct se_task *);
546 void (*transport_complete_callback)(struct se_cmd *); 547 void (*transport_complete_callback)(struct se_cmd *);