forked from Minki/linux
target/iblock: pass WRITE_SAME to device if possible
This patch has iblock pass the WRITE_SAME command to the device for offloading if possible. It is similar to what is done for UNMAP/discards, except that we export a large max write same value to the initiator, and then rely on the block layer to break it up into multiple requests if it cannot fit into one. v2. - Drop file backend changes and move helper function to iblock backend. Signed-off-by: Mike Christie <mchristi@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
e3416ab2d1
commit
07b6319687
@ -412,9 +412,40 @@ iblock_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sense_reason_t
|
||||
iblock_execute_write_same_direct(struct block_device *bdev, struct se_cmd *cmd)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct scatterlist *sg = &cmd->t_data_sg[0];
|
||||
struct page *page = NULL;
|
||||
int ret;
|
||||
|
||||
if (sg->offset) {
|
||||
page = alloc_page(GFP_KERNEL);
|
||||
if (!page)
|
||||
return TCM_OUT_OF_RESOURCES;
|
||||
sg_copy_to_buffer(sg, cmd->t_data_nents, page_address(page),
|
||||
dev->dev_attrib.block_size);
|
||||
}
|
||||
|
||||
ret = blkdev_issue_write_same(bdev,
|
||||
target_to_linux_sector(dev, cmd->t_task_lba),
|
||||
target_to_linux_sector(dev,
|
||||
sbc_get_write_same_sectors(cmd)),
|
||||
GFP_KERNEL, page ? page : sg_page(sg));
|
||||
if (page)
|
||||
__free_page(page);
|
||||
if (ret)
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sense_reason_t
|
||||
iblock_execute_write_same(struct se_cmd *cmd)
|
||||
{
|
||||
struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
|
||||
struct iblock_req *ibr;
|
||||
struct scatterlist *sg;
|
||||
struct bio *bio;
|
||||
@ -439,6 +470,9 @@ iblock_execute_write_same(struct se_cmd *cmd)
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
}
|
||||
|
||||
if (bdev_write_same(bdev))
|
||||
return iblock_execute_write_same_direct(bdev, cmd);
|
||||
|
||||
ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
|
||||
if (!ibr)
|
||||
goto fail;
|
||||
|
Loading…
Reference in New Issue
Block a user