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