diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-11-12 03:32:17 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-12-14 06:38:29 -0500 |
commit | 7481deb413be132a22193e8a0bce88b311ecb3c2 (patch) | |
tree | 6d417c6856f983cb28fae0717563f4efcd6019e1 | |
parent | ce136176fea522fc8f4c16dcae7e8ed1d890ca39 (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.c | 39 | ||||
-rw-r--r-- | include/target/target_core_base.h | 1 |
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 | } |
3923 | EXPORT_SYMBOL(target_get_sess_cmd); | 3926 | EXPORT_SYMBOL(target_get_sess_cmd); |
3924 | 3927 | ||
3925 | /* target_put_sess_cmd - Check for active I/O shutdown or list delete | 3928 | static void target_release_cmd_kref(struct kref *kref) |
3926 | * @se_sess: session to reference | ||
3927 | * @se_cmd: command descriptor to drop | ||
3928 | */ | ||
3929 | int 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 | */ | ||
3955 | int 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 | } |
3950 | EXPORT_SYMBOL(target_put_sess_cmd); | 3959 | EXPORT_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 *); |