aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
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