diff options
author | Christoph Hellwig <hch@infradead.org> | 2011-10-18 06:57:03 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-10-23 23:22:04 -0400 |
commit | af3f00c75949369d937f499f49118e879939724d (patch) | |
tree | 97be6b877cd80489eb055ccf1dd0bdb5e8c3f526 /drivers/target | |
parent | 9ac549873d35626cd6d7718691aaf4c55f2667a7 (diff) |
target: re-use the command S/G list for single-task commands
If we only have a single task per command (which at least in my testing
is the by far most common case) we do not have to allocate a new per-task
S/G list but can reuse the one from the command.
(nab: Fix BIDI handling in transport_free_dev_tasks)
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_transport.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index ab4e3083d968..ac048db21240 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -3551,7 +3551,9 @@ static void transport_free_dev_tasks(struct se_cmd *cmd) | |||
3551 | */ | 3551 | */ |
3552 | del_timer_sync(&task->task_timer); | 3552 | del_timer_sync(&task->task_timer); |
3553 | 3553 | ||
3554 | kfree(task->task_sg); | 3554 | if (task->task_sg != cmd->t_data_sg && |
3555 | task->task_sg != cmd->t_bidi_data_sg) | ||
3556 | kfree(task->task_sg); | ||
3555 | 3557 | ||
3556 | list_del(&task->t_list); | 3558 | list_del(&task->t_list); |
3557 | 3559 | ||
@@ -3830,7 +3832,33 @@ transport_allocate_data_tasks(struct se_cmd *cmd, | |||
3830 | lba = cmd->t_task_lba; | 3832 | lba = cmd->t_task_lba; |
3831 | sectors = DIV_ROUND_UP(cmd->data_length, sector_size); | 3833 | sectors = DIV_ROUND_UP(cmd->data_length, sector_size); |
3832 | task_count = DIV_ROUND_UP_SECTOR_T(sectors, dev_max_sectors); | 3834 | task_count = DIV_ROUND_UP_SECTOR_T(sectors, dev_max_sectors); |
3833 | 3835 | ||
3836 | /* | ||
3837 | * If we need just a single task reuse the SG list in the command | ||
3838 | * and avoid a lot of work. | ||
3839 | */ | ||
3840 | if (task_count == 1) { | ||
3841 | struct se_task *task; | ||
3842 | unsigned long flags; | ||
3843 | |||
3844 | task = transport_generic_get_task(cmd, data_direction); | ||
3845 | if (!task) | ||
3846 | return -ENOMEM; | ||
3847 | |||
3848 | task->task_sg = cmd_sg; | ||
3849 | task->task_sg_nents = sgl_nents; | ||
3850 | |||
3851 | task->task_lba = lba; | ||
3852 | task->task_sectors = sectors; | ||
3853 | task->task_size = task->task_sectors * sector_size; | ||
3854 | |||
3855 | spin_lock_irqsave(&cmd->t_state_lock, flags); | ||
3856 | list_add_tail(&task->t_list, &cmd->t_task_list); | ||
3857 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | ||
3858 | |||
3859 | return task_count; | ||
3860 | } | ||
3861 | |||
3834 | for (i = 0; i < task_count; i++) { | 3862 | for (i = 0; i < task_count; i++) { |
3835 | struct se_task *task; | 3863 | struct se_task *task; |
3836 | unsigned int task_size, task_sg_nents_padded; | 3864 | unsigned int task_size, task_sg_nents_padded; |
@@ -3906,15 +3934,7 @@ transport_allocate_control_task(struct se_cmd *cmd) | |||
3906 | if (!task) | 3934 | if (!task) |
3907 | return -ENOMEM; | 3935 | return -ENOMEM; |
3908 | 3936 | ||
3909 | task->task_sg = kmalloc(sizeof(struct scatterlist) * cmd->t_data_nents, | 3937 | task->task_sg = cmd->t_data_sg; |
3910 | GFP_KERNEL); | ||
3911 | if (!task->task_sg) { | ||
3912 | cmd->se_dev->transport->free_task(task); | ||
3913 | return -ENOMEM; | ||
3914 | } | ||
3915 | |||
3916 | memcpy(task->task_sg, cmd->t_data_sg, | ||
3917 | sizeof(struct scatterlist) * cmd->t_data_nents); | ||
3918 | task->task_size = cmd->data_length; | 3938 | task->task_size = cmd->data_length; |
3919 | task->task_sg_nents = cmd->t_data_nents; | 3939 | task->task_sg_nents = cmd->t_data_nents; |
3920 | 3940 | ||