diff options
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_file.c | 94 |
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 | ||
444 | static sense_reason_t | 481 | static sense_reason_t |
482 | fd_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 | |||
527 | static sense_reason_t | ||
445 | fd_execute_rw(struct se_cmd *cmd) | 528 | fd_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 | ||
605 | static sense_reason_t | 689 | static sense_reason_t |