aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2015-04-13 10:21:58 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2015-04-16 01:47:27 -0400
commit64d240b721b21e266ffde645ec965c3b6d1c551f (patch)
treeec77072987a3592c3f305cf50257bdfff1ce23fb
parentc836777830428372074d5129ac513e1472c99791 (diff)
target/file: Fix UNMAP with DIF protection support
When UNMAP command is issued with DIF protection support enabled, the protection info for the unmapped region is remain unchanged. So READ command for the region causes data integrity failure. This fixes it by invalidating protection info for the unmapped region by filling with 0xff pattern. This change also adds helper function fd_do_prot_fill() in order to reduce code duplication with existing fd_format_prot(). Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Reviewed-by: Sagi Grimberg <sagig@mellanox.com> Reviewed-by: "Martin K. Petersen" <martin.petersen@oracle.com> Cc: Christoph Hellwig <hch@lst.de> Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com> Cc: <stable@vger.kernel.org> # v3.14+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_file.c86
1 files changed, 61 insertions, 25 deletions
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 1284fec63db8..f7e6e51aed36 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -482,6 +482,56 @@ fd_execute_write_same(struct se_cmd *cmd)
482 return 0; 482 return 0;
483} 483}
484 484
485static int
486fd_do_prot_fill(struct se_device *se_dev, sector_t lba, sector_t nolb,
487 void *buf, size_t bufsize)
488{
489 struct fd_dev *fd_dev = FD_DEV(se_dev);
490 struct file *prot_fd = fd_dev->fd_prot_file;
491 sector_t prot_length, prot;
492 loff_t pos = lba * se_dev->prot_length;
493
494 if (!prot_fd) {
495 pr_err("Unable to locate fd_dev->fd_prot_file\n");
496 return -ENODEV;
497 }
498
499 prot_length = nolb * se_dev->prot_length;
500
501 for (prot = 0; prot < prot_length;) {
502 sector_t len = min_t(sector_t, bufsize, prot_length - prot);
503 ssize_t ret = kernel_write(prot_fd, buf, len, pos + prot);
504
505 if (ret != len) {
506 pr_err("vfs_write to prot file failed: %zd\n", ret);
507 return ret < 0 ? ret : -ENODEV;
508 }
509 prot += ret;
510 }
511
512 return 0;
513}
514
515static int
516fd_do_prot_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
517{
518 void *buf;
519 int rc;
520
521 buf = (void *)__get_free_page(GFP_KERNEL);
522 if (!buf) {
523 pr_err("Unable to allocate FILEIO prot buf\n");
524 return -ENOMEM;
525 }
526 memset(buf, 0xff, PAGE_SIZE);
527
528 rc = fd_do_prot_fill(cmd->se_dev, lba, nolb, buf, PAGE_SIZE);
529
530 free_page((unsigned long)buf);
531
532 return rc;
533}
534
485static sense_reason_t 535static sense_reason_t
486fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb) 536fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb)
487{ 537{
@@ -489,6 +539,12 @@ fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb)
489 struct inode *inode = file->f_mapping->host; 539 struct inode *inode = file->f_mapping->host;
490 int ret; 540 int ret;
491 541
542 if (cmd->se_dev->dev_attrib.pi_prot_type) {
543 ret = fd_do_prot_unmap(cmd, lba, nolb);
544 if (ret)
545 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
546 }
547
492 if (S_ISBLK(inode->i_mode)) { 548 if (S_ISBLK(inode->i_mode)) {
493 /* The backend is block device, use discard */ 549 /* The backend is block device, use discard */
494 struct block_device *bdev = inode->i_bdev; 550 struct block_device *bdev = inode->i_bdev;
@@ -811,48 +867,28 @@ static int fd_init_prot(struct se_device *dev)
811 867
812static int fd_format_prot(struct se_device *dev) 868static int fd_format_prot(struct se_device *dev)
813{ 869{
814 struct fd_dev *fd_dev = FD_DEV(dev);
815 struct file *prot_fd = fd_dev->fd_prot_file;
816 sector_t prot_length, prot;
817 unsigned char *buf; 870 unsigned char *buf;
818 loff_t pos = 0;
819 int unit_size = FDBD_FORMAT_UNIT_SIZE * dev->dev_attrib.block_size; 871 int unit_size = FDBD_FORMAT_UNIT_SIZE * dev->dev_attrib.block_size;
820 int rc, ret = 0, size, len; 872 int ret;
821 873
822 if (!dev->dev_attrib.pi_prot_type) { 874 if (!dev->dev_attrib.pi_prot_type) {
823 pr_err("Unable to format_prot while pi_prot_type == 0\n"); 875 pr_err("Unable to format_prot while pi_prot_type == 0\n");
824 return -ENODEV; 876 return -ENODEV;
825 } 877 }
826 if (!prot_fd) {
827 pr_err("Unable to locate fd_dev->fd_prot_file\n");
828 return -ENODEV;
829 }
830 878
831 buf = vzalloc(unit_size); 879 buf = vzalloc(unit_size);
832 if (!buf) { 880 if (!buf) {
833 pr_err("Unable to allocate FILEIO prot buf\n"); 881 pr_err("Unable to allocate FILEIO prot buf\n");
834 return -ENOMEM; 882 return -ENOMEM;
835 } 883 }
836 prot_length = (dev->transport->get_blocks(dev) + 1) * dev->prot_length;
837 size = prot_length;
838 884
839 pr_debug("Using FILEIO prot_length: %llu\n", 885 pr_debug("Using FILEIO prot_length: %llu\n",
840 (unsigned long long)prot_length); 886 (unsigned long long)(dev->transport->get_blocks(dev) + 1) *
887 dev->prot_length);
841 888
842 memset(buf, 0xff, unit_size); 889 memset(buf, 0xff, unit_size);
843 for (prot = 0; prot < prot_length; prot += unit_size) { 890 ret = fd_do_prot_fill(dev, 0, dev->transport->get_blocks(dev) + 1,
844 len = min(unit_size, size); 891 buf, unit_size);
845 rc = kernel_write(prot_fd, buf, len, pos);
846 if (rc != len) {
847 pr_err("vfs_write to prot file failed: %d\n", rc);
848 ret = -ENODEV;
849 goto out;
850 }
851 pos += len;
852 size -= len;
853 }
854
855out:
856 vfree(buf); 892 vfree(buf);
857 return ret; 893 return ret;
858} 894}