This patch adds support for emulation of WRITE_SAME w/ UNMAP=1 within fd_execute_write_same_unmap() backend code. If the FILEIO backend is normal file, the emulation uses fallocate to punch hole to reclaim the free space used by the file. If the FILEIO backend is block device, the emulation uses blkdev_issue_discard(). Tested with 512, 1k, 2k, and 4k block_sizes. Cc: Christoph Hellwig <hch@xxxxxx> Cc: Martin K. Petersen <martin.petersen@xxxxxxxxxx> Cc: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> Signed-off-by: Asias He <asias@xxxxxxxxxx> --- drivers/target/target_core_file.c | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 94383a5..2a9ce12 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -30,6 +30,7 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/module.h> +#include <linux/falloc.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> @@ -442,6 +443,52 @@ fd_execute_write_same(struct se_cmd *cmd) } static sense_reason_t +fd_execute_write_same_unmap(struct se_cmd *cmd) +{ + struct se_device *se_dev = cmd->se_dev; + struct fd_dev *fd_dev = FD_DEV(se_dev); + struct file *file = fd_dev->fd_file; + struct inode *inode = file->f_mapping->host; + sector_t nolb = spc_get_write_same_sectors(cmd); + int ret; + + if (!nolb) { + target_complete_cmd(cmd, SAM_STAT_GOOD); + return 0; + } + + if (S_ISBLK(inode->i_mode)) { + /* The backend is block device, use discard */ + struct block_device *bdev = inode->i_bdev; + + ret = blkdev_issue_discard(bdev, cmd->t_task_lba, + nolb, GFP_KERNEL, 0); + if (ret < 0) { + pr_warn("FILEIO: blkdev_issue_discard() failed: %d\n", + ret); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + } else { + /* The backend is normal file, use fallocate */ + loff_t pos = cmd->t_task_lba * se_dev->dev_attrib.block_size; + unsigned int len = nolb * se_dev->dev_attrib.block_size; + int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; + + if (!file->f_op->fallocate) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + ret = file->f_op->fallocate(file, mode, pos, len); + if (ret < 0) { + pr_warn("FILEIO: fallocate() failed: %d\n", ret); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + } + + target_complete_cmd(cmd, GOOD); + return 0; +} + +static sense_reason_t fd_execute_rw(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; @@ -600,6 +647,7 @@ static struct sbc_ops fd_sbc_ops = { .execute_rw = fd_execute_rw, .execute_sync_cache = fd_execute_sync_cache, .execute_write_same = fd_execute_write_same, + .execute_write_same_unmap = fd_execute_write_same_unmap, }; static sense_reason_t -- 1.8.1.2 -- 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