Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

target/file: Add DIF protection init/format support

This patch adds support for DIF protection init/format support into
the FILEIO backend.

It involves using a seperate $FILE.protection for storing PI that is
opened via fd_init_prot() using the common pi_prot_type attribute.
The actual formatting of the protection is done via fd_format_prot()
using the common pi_prot_format attribute, that will populate the
initial PI data based upon the currently configured pi_prot_type.

Based on original FILEIO code from Sagi.

v1 changes:
- Fix sparse warnings in fd_init_format_buf (Fengguang)

Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Sagi Grimberg <sagig@mellanox.com>
Cc: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

+141
+137
drivers/target/target_core_file.c
··· 700 700 dev->dev_attrib.block_size); 701 701 } 702 702 703 + static int fd_init_prot(struct se_device *dev) 704 + { 705 + struct fd_dev *fd_dev = FD_DEV(dev); 706 + struct file *prot_file, *file = fd_dev->fd_file; 707 + struct inode *inode; 708 + int ret, flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; 709 + char buf[FD_MAX_DEV_PROT_NAME]; 710 + 711 + if (!file) { 712 + pr_err("Unable to locate fd_dev->fd_file\n"); 713 + return -ENODEV; 714 + } 715 + 716 + inode = file->f_mapping->host; 717 + if (S_ISBLK(inode->i_mode)) { 718 + pr_err("FILEIO Protection emulation only supported on" 719 + " !S_ISBLK\n"); 720 + return -ENOSYS; 721 + } 722 + 723 + if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) 724 + flags &= ~O_DSYNC; 725 + 726 + snprintf(buf, FD_MAX_DEV_PROT_NAME, "%s.protection", 727 + fd_dev->fd_dev_name); 728 + 729 + prot_file = filp_open(buf, flags, 0600); 730 + if (IS_ERR(prot_file)) { 731 + pr_err("filp_open(%s) failed\n", buf); 732 + ret = PTR_ERR(prot_file); 733 + return ret; 734 + } 735 + fd_dev->fd_prot_file = prot_file; 736 + 737 + return 0; 738 + } 739 + 740 + static void fd_init_format_buf(struct se_device *dev, unsigned char *buf, 741 + u32 unit_size, u32 *ref_tag, u16 app_tag, 742 + bool inc_reftag) 743 + { 744 + unsigned char *p = buf; 745 + int i; 746 + 747 + for (i = 0; i < unit_size; i += dev->prot_length) { 748 + *((u16 *)&p[0]) = 0xffff; 749 + *((__be16 *)&p[2]) = cpu_to_be16(app_tag); 750 + *((__be32 *)&p[4]) = cpu_to_be32(*ref_tag); 751 + 752 + if (inc_reftag) 753 + (*ref_tag)++; 754 + 755 + p += dev->prot_length; 756 + } 757 + } 758 + 759 + static int fd_format_prot(struct se_device *dev) 760 + { 761 + struct fd_dev *fd_dev = FD_DEV(dev); 762 + struct file *prot_fd = fd_dev->fd_prot_file; 763 + sector_t prot_length, prot; 764 + unsigned char *buf; 765 + loff_t pos = 0; 766 + u32 ref_tag = 0; 767 + int unit_size = FDBD_FORMAT_UNIT_SIZE * dev->dev_attrib.block_size; 768 + int rc, ret = 0, size, len; 769 + bool inc_reftag = false; 770 + 771 + if (!dev->dev_attrib.pi_prot_type) { 772 + pr_err("Unable to format_prot while pi_prot_type == 0\n"); 773 + return -ENODEV; 774 + } 775 + if (!prot_fd) { 776 + pr_err("Unable to locate fd_dev->fd_prot_file\n"); 777 + return -ENODEV; 778 + } 779 + 780 + switch (dev->dev_attrib.pi_prot_type) { 781 + case TARGET_DIF_TYPE3_PROT: 782 + ref_tag = 0xffffffff; 783 + break; 784 + case TARGET_DIF_TYPE2_PROT: 785 + case TARGET_DIF_TYPE1_PROT: 786 + inc_reftag = true; 787 + break; 788 + default: 789 + break; 790 + } 791 + 792 + buf = vzalloc(unit_size); 793 + if (!buf) { 794 + pr_err("Unable to allocate FILEIO prot buf\n"); 795 + return -ENOMEM; 796 + } 797 + 798 + prot_length = (dev->transport->get_blocks(dev) + 1) * dev->prot_length; 799 + size = prot_length; 800 + 801 + pr_debug("Using FILEIO prot_length: %llu\n", 802 + (unsigned long long)prot_length); 803 + 804 + for (prot = 0; prot < prot_length; prot += unit_size) { 805 + 806 + fd_init_format_buf(dev, buf, unit_size, &ref_tag, 0xffff, 807 + inc_reftag); 808 + 809 + len = min(unit_size, size); 810 + 811 + rc = kernel_write(prot_fd, buf, len, pos); 812 + if (rc != len) { 813 + pr_err("vfs_write to prot file failed: %d\n", rc); 814 + ret = -ENODEV; 815 + goto out; 816 + } 817 + pos += len; 818 + size -= len; 819 + } 820 + 821 + out: 822 + vfree(buf); 823 + return ret; 824 + } 825 + 826 + static void fd_free_prot(struct se_device *dev) 827 + { 828 + struct fd_dev *fd_dev = FD_DEV(dev); 829 + 830 + if (!fd_dev->fd_prot_file) 831 + return; 832 + 833 + filp_close(fd_dev->fd_prot_file, NULL); 834 + fd_dev->fd_prot_file = NULL; 835 + } 836 + 703 837 static struct sbc_ops fd_sbc_ops = { 704 838 .execute_rw = fd_execute_rw, 705 839 .execute_sync_cache = fd_execute_sync_cache, ··· 864 730 .show_configfs_dev_params = fd_show_configfs_dev_params, 865 731 .get_device_type = sbc_get_device_type, 866 732 .get_blocks = fd_get_blocks, 733 + .init_prot = fd_init_prot, 734 + .format_prot = fd_format_prot, 735 + .free_prot = fd_free_prot, 867 736 }; 868 737 869 738 static int __init fileio_module_init(void)
+4
drivers/target/target_core_file.h
··· 4 4 #define FD_VERSION "4.0" 5 5 6 6 #define FD_MAX_DEV_NAME 256 7 + #define FD_MAX_DEV_PROT_NAME FD_MAX_DEV_NAME + 16 7 8 #define FD_DEVICE_QUEUE_DEPTH 32 8 9 #define FD_MAX_DEVICE_QUEUE_DEPTH 128 9 10 #define FD_BLOCKSIZE 512 ··· 16 15 #define FBDF_HAS_PATH 0x01 17 16 #define FBDF_HAS_SIZE 0x02 18 17 #define FDBD_HAS_BUFFERED_IO_WCE 0x04 18 + #define FDBD_FORMAT_UNIT_SIZE 2048 19 + 19 20 20 21 struct fd_dev { 21 22 struct se_device dev; ··· 32 29 u32 fd_block_size; 33 30 unsigned long long fd_dev_size; 34 31 struct file *fd_file; 32 + struct file *fd_prot_file; 35 33 /* FILEIO HBA device is connected to */ 36 34 struct fd_host *fd_host; 37 35 } ____cacheline_aligned;