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 | |
| 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>
| -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 | ||
