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. 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.. --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 -- 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