aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorAsias He <asias@redhat.com>2013-02-25 01:03:42 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2013-04-25 04:05:23 -0400
commit70d3ae5c80758cb2bf3cf1e0d5b2c89d040de90b (patch)
treeafee073ae3aa38326b8f0a4b2e4655cb7b463181 /drivers/target
parentc0c2dd499b7ae3d4d314ef2965ee2387848a39d9 (diff)
target/file: Add WRITE_SAME w/ UNMAP=1 emulation support
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. Changes in v2: - Set the various dev->dev_attrib.*unmap* values (nab) Cc: Christoph Hellwig <hch@lst.de> Cc: Martin K. Petersen <martin.petersen@oracle.com> Cc: Nicholas Bellinger <nab@linux-iscsi.org> Signed-off-by: Asias He <asias@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_file.c94
1 files changed, 89 insertions, 5 deletions
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 17a6acbc3ab0..e1878bfd97b7 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -30,6 +30,7 @@
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/falloc.h>
33#include <scsi/scsi.h> 34#include <scsi/scsi.h>
34#include <scsi/scsi_host.h> 35#include <scsi/scsi_host.h>
35 36
@@ -166,6 +167,30 @@ static int fd_configure_device(struct se_device *dev)
166 " block_device blocks: %llu logical_block_size: %d\n", 167 " block_device blocks: %llu logical_block_size: %d\n",
167 dev_size, div_u64(dev_size, fd_dev->fd_block_size), 168 dev_size, div_u64(dev_size, fd_dev->fd_block_size),
168 fd_dev->fd_block_size); 169 fd_dev->fd_block_size);
170 /*
171 * Check if the underlying struct block_device request_queue supports
172 * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
173 * in ATA and we need to set TPE=1
174 */
175 if (blk_queue_discard(q)) {
176 dev->dev_attrib.max_unmap_lba_count =
177 q->limits.max_discard_sectors;
178 /*
179 * Currently hardcoded to 1 in Linux/SCSI code..
180 */
181 dev->dev_attrib.max_unmap_block_desc_count = 1;
182 dev->dev_attrib.unmap_granularity =
183 q->limits.discard_granularity >> 9;
184 dev->dev_attrib.unmap_granularity_alignment =
185 q->limits.discard_alignment;
186 pr_debug("IFILE: BLOCK Discard support available,"
187 " disabled by default\n");
188 }
189 /*
190 * Enable write same emulation for IBLOCK and use 0xFFFF as
191 * the smaller WRITE_SAME(10) only has a two-byte block count.
192 */
193 dev->dev_attrib.max_write_same_len = 0xFFFF;
169 } else { 194 } else {
170 if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) { 195 if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) {
171 pr_err("FILEIO: Missing fd_dev_size=" 196 pr_err("FILEIO: Missing fd_dev_size="
@@ -176,6 +201,23 @@ static int fd_configure_device(struct se_device *dev)
176 201
177 dev->dev_attrib.hw_block_size = FD_BLOCKSIZE; 202 dev->dev_attrib.hw_block_size = FD_BLOCKSIZE;
178 dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS; 203 dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
204
205 /*
206 * Limit UNMAP emulation to 8k Number of LBAs (NoLB)
207 */
208 dev->dev_attrib.max_unmap_lba_count = 0x2000;
209 /*
210 * Currently hardcoded to 1 in Linux/SCSI code..
211 */
212 dev->dev_attrib.max_unmap_block_desc_count = 1;
213 dev->dev_attrib.unmap_granularity = 1;
214 dev->dev_attrib.unmap_granularity_alignment = 0;
215
216 /*
217 * Limit WRITE_SAME w/ UNMAP=0 emulation to 8k Number of LBAs (NoLB)
218 * based upon struct iovec limit for vfs_writev()
219 */
220 dev->dev_attrib.max_write_same_len = 0x1000;
179 } 221 }
180 222
181 fd_dev->fd_block_size = dev->dev_attrib.hw_block_size; 223 fd_dev->fd_block_size = dev->dev_attrib.hw_block_size;
@@ -190,11 +232,6 @@ static int fd_configure_device(struct se_device *dev)
190 232
191 fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++; 233 fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++;
192 fd_dev->fd_queue_depth = dev->queue_depth; 234 fd_dev->fd_queue_depth = dev->queue_depth;
193 /*
194 * Limit WRITE_SAME w/ UNMAP=0 emulation to 8k Number of LBAs (NoLB)
195 * based upon struct iovec limit for vfs_writev()
196 */
197 dev->dev_attrib.max_write_same_len = 0x1000;
198 235
199 pr_debug("CORE_FILE[%u] - Added TCM FILEIO Device ID: %u at %s," 236 pr_debug("CORE_FILE[%u] - Added TCM FILEIO Device ID: %u at %s,"
200 " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id, 237 " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id,
@@ -442,6 +479,52 @@ fd_execute_write_same(struct se_cmd *cmd)
442} 479}
443 480
444static sense_reason_t 481static sense_reason_t
482fd_execute_write_same_unmap(struct se_cmd *cmd)
483{
484 struct se_device *se_dev = cmd->se_dev;
485 struct fd_dev *fd_dev = FD_DEV(se_dev);
486 struct file *file = fd_dev->fd_file;
487 struct inode *inode = file->f_mapping->host;
488 sector_t nolb = sbc_get_write_same_sectors(cmd);
489 int ret;
490
491 if (!nolb) {
492 target_complete_cmd(cmd, SAM_STAT_GOOD);
493 return 0;
494 }
495
496 if (S_ISBLK(inode->i_mode)) {
497 /* The backend is block device, use discard */
498 struct block_device *bdev = inode->i_bdev;
499
500 ret = blkdev_issue_discard(bdev, cmd->t_task_lba,
501 nolb, GFP_KERNEL, 0);
502 if (ret < 0) {
503 pr_warn("FILEIO: blkdev_issue_discard() failed: %d\n",
504 ret);
505 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
506 }
507 } else {
508 /* The backend is normal file, use fallocate */
509 loff_t pos = cmd->t_task_lba * se_dev->dev_attrib.block_size;
510 unsigned int len = nolb * se_dev->dev_attrib.block_size;
511 int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
512
513 if (!file->f_op->fallocate)
514 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
515
516 ret = file->f_op->fallocate(file, mode, pos, len);
517 if (ret < 0) {
518 pr_warn("FILEIO: fallocate() failed: %d\n", ret);
519 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
520 }
521 }
522
523 target_complete_cmd(cmd, GOOD);
524 return 0;
525}
526
527static sense_reason_t
445fd_execute_rw(struct se_cmd *cmd) 528fd_execute_rw(struct se_cmd *cmd)
446{ 529{
447 struct scatterlist *sgl = cmd->t_data_sg; 530 struct scatterlist *sgl = cmd->t_data_sg;
@@ -600,6 +683,7 @@ static struct sbc_ops fd_sbc_ops = {
600 .execute_rw = fd_execute_rw, 683 .execute_rw = fd_execute_rw,
601 .execute_sync_cache = fd_execute_sync_cache, 684 .execute_sync_cache = fd_execute_sync_cache,
602 .execute_write_same = fd_execute_write_same, 685 .execute_write_same = fd_execute_write_same,
686 .execute_write_same_unmap = fd_execute_write_same_unmap,
603}; 687};
604 688
605static sense_reason_t 689static sense_reason_t