On 02/22/2013 06:35 AM, Nicholas A. Bellinger wrote: > On Thu, 2013-02-21 at 13:57 +0800, Asias He wrote: >> 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; >> +} >> + > > So you'll also need to set the various dev->dev_attrib.*unmap* values > for EVPD Block Limits at fd_configure_device() time.. Check out > iblock_configure_device() to see how this is currently done for the > underlying struct block_device case from request_queue->limits. > > For the fallocate() case, you'll need to add some sane defaults here > too. okay. > As for the direct blkdev_issue_discard usage() within FILEIO code, I > don't have a problem with it, but I'd really like to get hch's feedback > here.. okay. > --nab > > > > > > > >> +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 > > -- Asias -- 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