Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af3f00c7 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Nicholas Bellinger
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 9ac54987
Loading
Loading
Loading
Loading
+31 −11
Original line number Diff line number Diff line
@@ -3551,6 +3551,8 @@ static void transport_free_dev_tasks(struct se_cmd *cmd)
		 */
		del_timer_sync(&task->task_timer);

		if (task->task_sg != cmd->t_data_sg &&
		    task->task_sg != cmd->t_bidi_data_sg)
			kfree(task->task_sg);

		list_del(&task->t_list);
@@ -3831,6 +3833,32 @@ transport_allocate_data_tasks(struct se_cmd *cmd,
	sectors = DIV_ROUND_UP(cmd->data_length, sector_size);
	task_count = DIV_ROUND_UP_SECTOR_T(sectors, dev_max_sectors);

	/*
	 * If we need just a single task reuse the SG list in the command
	 * and avoid a lot of work.
	 */
	if (task_count == 1) {
		struct se_task *task;
		unsigned long flags;

		task = transport_generic_get_task(cmd, data_direction);
		if (!task)
			return -ENOMEM;

		task->task_sg = cmd_sg;
		task->task_sg_nents = sgl_nents;

		task->task_lba = lba;
		task->task_sectors = sectors;
		task->task_size = task->task_sectors * sector_size;

		spin_lock_irqsave(&cmd->t_state_lock, flags);
		list_add_tail(&task->t_list, &cmd->t_task_list);
		spin_unlock_irqrestore(&cmd->t_state_lock, flags);

		return task_count;
	}

	for (i = 0; i < task_count; i++) {
		struct se_task *task;
		unsigned int task_size, task_sg_nents_padded;
@@ -3906,15 +3934,7 @@ transport_allocate_control_task(struct se_cmd *cmd)
	if (!task)
		return -ENOMEM;

	task->task_sg = kmalloc(sizeof(struct scatterlist) * cmd->t_data_nents,
				GFP_KERNEL);
	if (!task->task_sg) {
		cmd->se_dev->transport->free_task(task);
		return -ENOMEM;
	}

	memcpy(task->task_sg, cmd->t_data_sg,
	       sizeof(struct scatterlist) * cmd->t_data_nents);
	task->task_sg = cmd->t_data_sg;
	task->task_size = cmd->data_length;
	task->task_sg_nents = cmd->t_data_nents;