aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-10-18 06:57:03 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2011-10-23 23:22:04 -0400
commitaf3f00c75949369d937f499f49118e879939724d (patch)
tree97be6b877cd80489eb055ccf1dd0bdb5e8c3f526 /drivers/target
parent9ac549873d35626cd6d7718691aaf4c55f2667a7 (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.c42
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