Re: [PATCH 31/42] target: Have iscsi fabric allocate its own buffers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2011-05-27 at 12:07 -0700, Andy Grover wrote:
> Instead of relying on tcm core to allocate data buffers for the cmd,
> iscsi allocates them and then calls map_mem_to_cmd, which creates the
> core-specific se_mem list, and sets a flag so the core will not later
> try to also allocate memory for the cmd.
> 
> Down the road, this will allow iscsi to handle the data buffer only with
> the buffer offset and length, and without relying on the se_mem list
> at all.
> 
> Signed-off-by: Andy Grover <agrover@xxxxxxxxxx>
> ---

Loooks good.  Committed as ef03f53150 with hch's recommendation to use
DIV_ROUND_UP() instead of the locally defined ceil().

Thanks,

--nab

>  drivers/target/iscsi/iscsi_target.c      |   81 ++++++++++++++++++++++++++++++
>  drivers/target/iscsi/iscsi_target_core.h |    5 ++
>  drivers/target/iscsi/iscsi_target_util.c |   11 ++++
>  3 files changed, 97 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
> index 79c2fd7..9e07dca 100644
> --- a/drivers/target/iscsi/iscsi_target.c
> +++ b/drivers/target/iscsi/iscsi_target.c
> @@ -979,6 +979,82 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
>  	spin_unlock_bh(&conn->cmd_lock);
>  }
>  
> +#define ceil(x, y) \
> +	({ unsigned long __x = (x), __y = (y); (__x + __y - 1) / __y; })
> +
> +static int iscsit_alloc_buffs(struct iscsi_cmd *cmd)
> +{
> +	u32 length = cmd->se_cmd.data_length;
> +	struct scatterlist *sgl;
> +	int nents = ceil(length, PAGE_SIZE);
> +	int i = 0;
> +	void *buf;
> +	void *cur;
> +	struct page *page;
> +
> +	sgl = kzalloc(sizeof(*sgl) * nents, GFP_KERNEL);
> +	if (!sgl)
> +		return -ENOMEM;
> +
> +	/*
> +	 * Allocate from slab if nonsg, but sgl should point
> +	 * to the malloced mem.
> +	 * We know we have to kfree it if t_task_buf is set.
> +	 * Alloc pages if sg.
> +	 */
> +	if (cmd->se_cmd.se_cmd_flags & SCF_SCSI_CONTROL_NONSG_IO_CDB) {
> +
> +		buf = kmalloc(length, GFP_KERNEL);
> +		if (!buf)
> +			return -ENOMEM;
> +
> +		cur = buf;
> +		while (length) {
> +			int buf_size = min_t(int, length, PAGE_SIZE);
> +
> +			sg_set_buf(&sgl[i], cur, buf_size);
> +
> +			length -= buf_size;
> +			cur += buf_size;
> +			i++;
> +		}
> +		cmd->se_cmd.t_task_buf = buf;
> +		cmd->t_mem = buf;
> +
> +	} else {
> +
> +		while (length) {
> +			int buf_size = min_t(int, length, PAGE_SIZE);
> +
> +			page = alloc_page(GFP_KERNEL);
> +			if (!page)
> +				goto page_alloc_failed;
> +
> +			sg_set_page(&sgl[i], page, buf_size, 0);
> +
> +			length -= buf_size;
> +			i++;
> +		}
> +	}
> +
> +	cmd->t_mem_sg = sgl;
> +	cmd->t_mem_sg_nents = nents;
> +
> +	/* BIDI ops not supported */
> +
> +	/* make se_mem list from the memory */
> +	transport_generic_map_mem_to_cmd(&cmd->se_cmd, sgl, nents, NULL, 0);
> +
> +	return 0;
> +
> +page_alloc_failed:
> +	while (i >= 0) {
> +		__free_page(sg_page(&sgl[i]));
> +		i--;
> +	}
> +	return -ENOMEM;
> +}
> +
>  static int iscsit_handle_scsi_cmd(
>  	struct iscsi_conn *conn,
>  	unsigned char *buf)
> @@ -1249,6 +1325,11 @@ attach_cmd:
>  		goto after_immediate_data;
>  	}
>  
> +	ret = iscsit_alloc_buffs(cmd);
> +	if (ret < 0) {
> +		return ret;
> +	}
> +
>  	/*
>  	 * Immediate Data is present, send to the transport and block until
>  	 * the underlying transport plugin has allocated the buffer to
> diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
> index 0eaf86b..d64cd30 100644
> --- a/drivers/target/iscsi/iscsi_target_core.h
> +++ b/drivers/target/iscsi/iscsi_target_core.h
> @@ -472,6 +472,11 @@ struct iscsi_cmd {
>  	/* Sense buffer that will be mapped into outgoing status */
>  #define ISCSI_SENSE_BUFFER_LEN          (TRANSPORT_SENSE_BUFFER + 2)
>  	unsigned char		sense_buffer[ISCSI_SENSE_BUFFER_LEN];
> +
> +	void			*t_mem;
> +	struct scatterlist	*t_mem_sg;
> +	u32			t_mem_sg_nents;
> +
>  }  ____cacheline_aligned;
>  
>  #define SE_CMD(cmd)		(&(cmd)->se_cmd)
> diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
> index 612658a..6d770a4 100644
> --- a/drivers/target/iscsi/iscsi_target_util.c
> +++ b/drivers/target/iscsi/iscsi_target_util.c
> @@ -812,6 +812,17 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
>  	kfree(cmd->tmr_req);
>  	kfree(cmd->iov_data);
>  
> +	/* see iscsit_alloc_buffs */
> +	if (cmd->t_mem) {
> +		kfree(cmd->t_mem);
> +	} else {
> +		int i;
> +
> +		for (i = 0; i < cmd->t_mem_sg_nents; i++)
> +			__free_page(sg_page(&cmd->t_mem_sg[i]));
> +	}
> +	kfree(cmd->t_mem_sg);
> +
>  	if (conn) {
>  		iscsit_remove_cmd_from_immediate_queue(cmd, conn);
>  		iscsit_remove_cmd_from_response_queue(cmd, conn);
> -- 
> 1.7.1
> 

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux