aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <mchristi@redhat.com>2016-02-24 14:56:33 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2016-03-11 00:48:53 -0500
commit07b6319687026bdac90a0bb9eeb0509f1ff27179 (patch)
tree05e7f5b5e9046c813b7d118a5542d83b33240725
parente3416ab2d156ac0f0a3d9e55bcdff69d109ba403 (diff)
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>
-rw-r--r--drivers/target/target_core_iblock.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index abe4eb997a84..026a758e5778 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -413,8 +413,39 @@ iblock_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
413} 413}
414 414
415static sense_reason_t 415static sense_reason_t
416iblock_execute_write_same_direct(struct block_device *bdev, struct se_cmd *cmd)
417{
418 struct se_device *dev = cmd->se_dev;
419 struct scatterlist *sg = &cmd->t_data_sg[0];
420 struct page *page = NULL;
421 int ret;
422
423 if (sg->offset) {
424 page = alloc_page(GFP_KERNEL);
425 if (!page)
426 return TCM_OUT_OF_RESOURCES;
427 sg_copy_to_buffer(sg, cmd->t_data_nents, page_address(page),
428 dev->dev_attrib.block_size);
429 }
430
431 ret = blkdev_issue_write_same(bdev,
432 target_to_linux_sector(dev, cmd->t_task_lba),
433 target_to_linux_sector(dev,
434 sbc_get_write_same_sectors(cmd)),
435 GFP_KERNEL, page ? page : sg_page(sg));
436 if (page)
437 __free_page(page);
438 if (ret)
439 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
440
441 target_complete_cmd(cmd, GOOD);
442 return 0;
443}
444
445static sense_reason_t
416iblock_execute_write_same(struct se_cmd *cmd) 446iblock_execute_write_same(struct se_cmd *cmd)
417{ 447{
448 struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
418 struct iblock_req *ibr; 449 struct iblock_req *ibr;
419 struct scatterlist *sg; 450 struct scatterlist *sg;
420 struct bio *bio; 451 struct bio *bio;
@@ -439,6 +470,9 @@ iblock_execute_write_same(struct se_cmd *cmd)
439 return TCM_INVALID_CDB_FIELD; 470 return TCM_INVALID_CDB_FIELD;
440 } 471 }
441 472
473 if (bdev_write_same(bdev))
474 return iblock_execute_write_same_direct(bdev, cmd);
475
442 ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); 476 ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
443 if (!ibr) 477 if (!ibr)
444 goto fail; 478 goto fail;