Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
scsi: target: use the stack for XCOPY passthrough cmds
Browse files Browse the repository at this point in the history
Reads and writes in the XCOPY loop are synchronous, so needn't be heap
allocated / freed with each loop.

Link: https://lore.kernel.org/r/[email protected]
Reviewed-by: Christoph Hellwig <[email protected]>
Signed-off-by: David Disseldorp <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
  • Loading branch information
ddiss authored and martinkpetersen committed Mar 29, 2020
1 parent 5f306af commit b92fcfc
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 58 deletions.
84 changes: 31 additions & 53 deletions drivers/target/target_core_xcopy.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ static void xcopy_pt_release_cmd(struct se_cmd *se_cmd)
struct xcopy_pt_cmd *xpt_cmd = container_of(se_cmd,
struct xcopy_pt_cmd, se_cmd);

kfree(xpt_cmd);
/* xpt_cmd is on the stack, nothing to free here */
pr_debug("xpt_cmd done: %p\n", xpt_cmd);
}

static int xcopy_pt_check_stop_free(struct se_cmd *se_cmd)
Expand Down Expand Up @@ -566,20 +567,15 @@ static int target_xcopy_read_source(
sector_t src_lba,
u32 src_sectors)
{
struct xcopy_pt_cmd *xpt_cmd;
struct se_cmd *se_cmd;
struct xcopy_pt_cmd xpt_cmd;
struct se_cmd *se_cmd = &xpt_cmd.se_cmd;
u32 length = (src_sectors * src_dev->dev_attrib.block_size);
int rc;
unsigned char cdb[16];
bool remote_port = (xop->op_origin == XCOL_DEST_RECV_OP);

xpt_cmd = kzalloc(sizeof(struct xcopy_pt_cmd), GFP_KERNEL);
if (!xpt_cmd) {
pr_err("Unable to allocate xcopy_pt_cmd\n");
return -ENOMEM;
}
init_completion(&xpt_cmd->xpt_passthrough_sem);
se_cmd = &xpt_cmd->se_cmd;
memset(&xpt_cmd, 0, sizeof(xpt_cmd));
init_completion(&xpt_cmd.xpt_passthrough_sem);

memset(&cdb[0], 0, 16);
cdb[0] = READ_16;
Expand All @@ -589,28 +585,24 @@ static int target_xcopy_read_source(
(unsigned long long)src_lba, src_sectors, length);

transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length,
DMA_FROM_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
xop->src_pt_cmd = xpt_cmd;
DMA_FROM_DEVICE, 0, &xpt_cmd.sense_buffer[0]);

rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0],
rc = target_xcopy_setup_pt_cmd(&xpt_cmd, xop, src_dev, &cdb[0],
remote_port);
if (rc < 0) {
ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
transport_generic_free_cmd(se_cmd, 0);
return rc;
ec_cmd->scsi_status = se_cmd->scsi_status;
goto out;
}

pr_debug("XCOPY-READ: Saved xop->xop_data_sg: %p, num: %u for READ"
" memory\n", xop->xop_data_sg, xop->xop_data_nents);

rc = target_xcopy_issue_pt_cmd(xpt_cmd);
if (rc < 0) {
ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
transport_generic_free_cmd(se_cmd, 0);
return rc;
}

return 0;
rc = target_xcopy_issue_pt_cmd(&xpt_cmd);
if (rc < 0)
ec_cmd->scsi_status = se_cmd->scsi_status;
out:
transport_generic_free_cmd(se_cmd, 0);
return rc;
}

static int target_xcopy_write_destination(
Expand All @@ -620,20 +612,15 @@ static int target_xcopy_write_destination(
sector_t dst_lba,
u32 dst_sectors)
{
struct xcopy_pt_cmd *xpt_cmd;
struct se_cmd *se_cmd;
struct xcopy_pt_cmd xpt_cmd;
struct se_cmd *se_cmd = &xpt_cmd.se_cmd;
u32 length = (dst_sectors * dst_dev->dev_attrib.block_size);
int rc;
unsigned char cdb[16];
bool remote_port = (xop->op_origin == XCOL_SOURCE_RECV_OP);

xpt_cmd = kzalloc(sizeof(struct xcopy_pt_cmd), GFP_KERNEL);
if (!xpt_cmd) {
pr_err("Unable to allocate xcopy_pt_cmd\n");
return -ENOMEM;
}
init_completion(&xpt_cmd->xpt_passthrough_sem);
se_cmd = &xpt_cmd->se_cmd;
memset(&xpt_cmd, 0, sizeof(xpt_cmd));
init_completion(&xpt_cmd.xpt_passthrough_sem);

memset(&cdb[0], 0, 16);
cdb[0] = WRITE_16;
Expand All @@ -643,25 +630,21 @@ static int target_xcopy_write_destination(
(unsigned long long)dst_lba, dst_sectors, length);

transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length,
DMA_TO_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
xop->dst_pt_cmd = xpt_cmd;
DMA_TO_DEVICE, 0, &xpt_cmd.sense_buffer[0]);

rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, dst_dev, &cdb[0],
rc = target_xcopy_setup_pt_cmd(&xpt_cmd, xop, dst_dev, &cdb[0],
remote_port);
if (rc < 0) {
ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
transport_generic_free_cmd(se_cmd, 0);
return rc;
}

rc = target_xcopy_issue_pt_cmd(xpt_cmd);
if (rc < 0) {
ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
transport_generic_free_cmd(se_cmd, 0);
return rc;
ec_cmd->scsi_status = se_cmd->scsi_status;
goto out;
}

return 0;
rc = target_xcopy_issue_pt_cmd(&xpt_cmd);
if (rc < 0)
ec_cmd->scsi_status = se_cmd->scsi_status;
out:
transport_generic_free_cmd(se_cmd, 0);
return rc;
}

static void target_xcopy_do_work(struct work_struct *work)
Expand Down Expand Up @@ -736,20 +719,15 @@ static void target_xcopy_do_work(struct work_struct *work)

rc = target_xcopy_write_destination(ec_cmd, xop, dst_dev,
dst_lba, cur_nolb);
if (rc < 0) {
transport_generic_free_cmd(&xop->src_pt_cmd->se_cmd, 0);
if (rc < 0)
goto out;
}

dst_lba += cur_nolb;
pr_debug("target_xcopy_do_work: Incremented WRITE dst_lba to %llu\n",
(unsigned long long)dst_lba);

copied_nolb += cur_nolb;
nolb -= cur_nolb;

transport_generic_free_cmd(&xop->src_pt_cmd->se_cmd, 0);
transport_generic_free_cmd(&xop->dst_pt_cmd->se_cmd, 0);
}

xcopy_pt_undepend_remotedev(xop);
Expand Down
5 changes: 0 additions & 5 deletions drivers/target/target_core_xcopy.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ enum xcopy_origin_list {
XCOL_DEST_RECV_OP = 0x02,
};

struct xcopy_pt_cmd;

struct xcopy_op {
int op_origin;

Expand All @@ -36,9 +34,6 @@ struct xcopy_op {
unsigned short dtdi;
unsigned short nolb;

struct xcopy_pt_cmd *src_pt_cmd;
struct xcopy_pt_cmd *dst_pt_cmd;

u32 xop_data_bytes;
u32 xop_data_nents;
struct scatterlist *xop_data_sg;
Expand Down

0 comments on commit b92fcfc

Please sign in to comment.