diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-11-30 21:18:33 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-12-14 06:48:46 -0500 |
commit | 4d2300ccffd22d1d0213b6a8e4d685eb6ca069c0 (patch) | |
tree | a76817aa4aaba5a6ffb05b3e6a0ea9ca654a0519 /drivers | |
parent | 65586d51e0986be574118286c3d0007e903a2add (diff) |
target: Remove extra se_device->execute_task_lock access in fast path
This patch makes __transport_execute_tasks() perform the addition of
tasks to dev->execute_task_list via __transport_add_tasks_from_cmd()
while holding dev->execute_task_lock during normal I/O fast path
submission.
It effectively removes the unnecessary re-acquire of dev->execute_task_lock
during transport_execute_tasks() -> transport_add_tasks_from_cmd() ahead
of calling __transport_execute_tasks() to queue tasks for the passed
*se_cmd descriptor.
(v2: Re-add goto check_depth usage for multi-task submission for now..)
Cc: Christoph Hellwig <hch@lst.de>
Cc: Roland Dreier <roland@purestorage.com>
Cc: Joern Engel <joern@logfs.org>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/target/target_core_transport.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 7c2def7e2593..46e25118ab25 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -68,7 +68,7 @@ struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; | |||
68 | 68 | ||
69 | static int transport_generic_write_pending(struct se_cmd *); | 69 | static int transport_generic_write_pending(struct se_cmd *); |
70 | static int transport_processing_thread(void *param); | 70 | static int transport_processing_thread(void *param); |
71 | static int __transport_execute_tasks(struct se_device *dev); | 71 | static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *); |
72 | static void transport_complete_task_attr(struct se_cmd *cmd); | 72 | static void transport_complete_task_attr(struct se_cmd *cmd); |
73 | static void transport_handle_queue_full(struct se_cmd *cmd, | 73 | static void transport_handle_queue_full(struct se_cmd *cmd, |
74 | struct se_device *dev); | 74 | struct se_device *dev); |
@@ -851,13 +851,11 @@ static void transport_add_tasks_to_state_queue(struct se_cmd *cmd) | |||
851 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | 851 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); |
852 | } | 852 | } |
853 | 853 | ||
854 | static void transport_add_tasks_from_cmd(struct se_cmd *cmd) | 854 | static void __transport_add_tasks_from_cmd(struct se_cmd *cmd) |
855 | { | 855 | { |
856 | struct se_device *dev = cmd->se_dev; | 856 | struct se_device *dev = cmd->se_dev; |
857 | struct se_task *task, *task_prev = NULL; | 857 | struct se_task *task, *task_prev = NULL; |
858 | unsigned long flags; | ||
859 | 858 | ||
860 | spin_lock_irqsave(&dev->execute_task_lock, flags); | ||
861 | list_for_each_entry(task, &cmd->t_task_list, t_list) { | 859 | list_for_each_entry(task, &cmd->t_task_list, t_list) { |
862 | if (!list_empty(&task->t_execute_list)) | 860 | if (!list_empty(&task->t_execute_list)) |
863 | continue; | 861 | continue; |
@@ -868,6 +866,15 @@ static void transport_add_tasks_from_cmd(struct se_cmd *cmd) | |||
868 | __transport_add_task_to_execute_queue(task, task_prev, dev); | 866 | __transport_add_task_to_execute_queue(task, task_prev, dev); |
869 | task_prev = task; | 867 | task_prev = task; |
870 | } | 868 | } |
869 | } | ||
870 | |||
871 | static void transport_add_tasks_from_cmd(struct se_cmd *cmd) | ||
872 | { | ||
873 | unsigned long flags; | ||
874 | struct se_device *dev = cmd->se_dev; | ||
875 | |||
876 | spin_lock_irqsave(&dev->execute_task_lock, flags); | ||
877 | __transport_add_tasks_from_cmd(cmd); | ||
871 | spin_unlock_irqrestore(&dev->execute_task_lock, flags); | 878 | spin_unlock_irqrestore(&dev->execute_task_lock, flags); |
872 | } | 879 | } |
873 | 880 | ||
@@ -2075,19 +2082,16 @@ static int transport_execute_tasks(struct se_cmd *cmd) | |||
2075 | if (!add_tasks) | 2082 | if (!add_tasks) |
2076 | goto execute_tasks; | 2083 | goto execute_tasks; |
2077 | /* | 2084 | /* |
2078 | * This calls transport_add_tasks_from_cmd() to handle | 2085 | * __transport_execute_tasks() -> __transport_add_tasks_from_cmd() |
2079 | * HEAD_OF_QUEUE ordering for SAM Task Attribute emulation | 2086 | * adds associated se_tasks while holding dev->execute_task_lock |
2080 | * (if enabled) in __transport_add_task_to_execute_queue() and | 2087 | * before I/O dispath to avoid a double spinlock access. |
2081 | * transport_add_task_check_sam_attr(). | ||
2082 | */ | 2088 | */ |
2083 | transport_add_tasks_from_cmd(cmd); | 2089 | __transport_execute_tasks(se_dev, cmd); |
2090 | return 0; | ||
2084 | } | 2091 | } |
2085 | /* | 2092 | |
2086 | * Kick the execution queue for the cmd associated struct se_device | ||
2087 | * storage object. | ||
2088 | */ | ||
2089 | execute_tasks: | 2093 | execute_tasks: |
2090 | __transport_execute_tasks(se_dev); | 2094 | __transport_execute_tasks(se_dev, NULL); |
2091 | return 0; | 2095 | return 0; |
2092 | } | 2096 | } |
2093 | 2097 | ||
@@ -2097,7 +2101,7 @@ execute_tasks: | |||
2097 | * | 2101 | * |
2098 | * Called from transport_processing_thread() | 2102 | * Called from transport_processing_thread() |
2099 | */ | 2103 | */ |
2100 | static int __transport_execute_tasks(struct se_device *dev) | 2104 | static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *new_cmd) |
2101 | { | 2105 | { |
2102 | int error; | 2106 | int error; |
2103 | struct se_cmd *cmd = NULL; | 2107 | struct se_cmd *cmd = NULL; |
@@ -2106,6 +2110,9 @@ static int __transport_execute_tasks(struct se_device *dev) | |||
2106 | 2110 | ||
2107 | check_depth: | 2111 | check_depth: |
2108 | spin_lock_irq(&dev->execute_task_lock); | 2112 | spin_lock_irq(&dev->execute_task_lock); |
2113 | if (new_cmd != NULL) | ||
2114 | __transport_add_tasks_from_cmd(new_cmd); | ||
2115 | |||
2109 | if (list_empty(&dev->execute_task_list)) { | 2116 | if (list_empty(&dev->execute_task_list)) { |
2110 | spin_unlock_irq(&dev->execute_task_lock); | 2117 | spin_unlock_irq(&dev->execute_task_lock); |
2111 | return 0; | 2118 | return 0; |
@@ -2139,6 +2146,7 @@ check_depth: | |||
2139 | transport_generic_request_failure(cmd); | 2146 | transport_generic_request_failure(cmd); |
2140 | } | 2147 | } |
2141 | 2148 | ||
2149 | new_cmd = NULL; | ||
2142 | goto check_depth; | 2150 | goto check_depth; |
2143 | 2151 | ||
2144 | return 0; | 2152 | return 0; |
@@ -4647,7 +4655,7 @@ static int transport_processing_thread(void *param) | |||
4647 | goto out; | 4655 | goto out; |
4648 | 4656 | ||
4649 | get_cmd: | 4657 | get_cmd: |
4650 | __transport_execute_tasks(dev); | 4658 | __transport_execute_tasks(dev, NULL); |
4651 | 4659 | ||
4652 | cmd = transport_get_cmd_from_queue(&dev->dev_queue_obj); | 4660 | cmd = transport_get_cmd_from_queue(&dev->dev_queue_obj); |
4653 | if (!cmd) | 4661 | if (!cmd) |