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

target/iblock: Add blk_integrity + BIP passthrough support

This patch adds blk_integrity passthrough support for block_device
backends using IBLOCK.

This includes iblock_alloc_bip() + setup of bio_integrity_payload
information that attaches to the leading struct bio once bio_list
is populated during fast-path iblock_execute_rw() I/O dispatch.

It also updates setup in iblock_configure_device() to detect modes
of protection + se dev->dev_attrib.pi_prot_type accordingly, along
with creating required bio_set integrity mempools.

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>

+90 -2
+1
drivers/target/Kconfig
··· 14 14 15 15 config TCM_IBLOCK 16 16 tristate "TCM/IBLOCK Subsystem Plugin for Linux/BLOCK" 17 + select BLK_DEV_INTEGRITY 17 18 help 18 19 Say Y here to enable the TCM/IBLOCK subsystem plugin for non-buffered 19 20 access to Linux/Block devices using BIO
+89 -2
drivers/target/target_core_iblock.c
··· 91 91 struct iblock_dev *ib_dev = IBLOCK_DEV(dev); 92 92 struct request_queue *q; 93 93 struct block_device *bd = NULL; 94 + struct blk_integrity *bi; 94 95 fmode_t mode; 95 96 int ret = -ENOMEM; 96 97 ··· 156 155 if (blk_queue_nonrot(q)) 157 156 dev->dev_attrib.is_nonrot = 1; 158 157 158 + bi = bdev_get_integrity(bd); 159 + if (bi) { 160 + struct bio_set *bs = ib_dev->ibd_bio_set; 161 + 162 + if (!strcmp(bi->name, "T10-DIF-TYPE3-IP") || 163 + !strcmp(bi->name, "T10-DIF-TYPE1-IP")) { 164 + pr_err("IBLOCK export of blk_integrity: %s not" 165 + " supported\n", bi->name); 166 + ret = -ENOSYS; 167 + goto out_blkdev_put; 168 + } 169 + 170 + if (!strcmp(bi->name, "T10-DIF-TYPE3-CRC")) { 171 + dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE3_PROT; 172 + } else if (!strcmp(bi->name, "T10-DIF-TYPE1-CRC")) { 173 + dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE1_PROT; 174 + } 175 + 176 + if (dev->dev_attrib.pi_prot_type) { 177 + if (bioset_integrity_create(bs, IBLOCK_BIO_POOL_SIZE) < 0) { 178 + pr_err("Unable to allocate bioset for PI\n"); 179 + ret = -ENOMEM; 180 + goto out_blkdev_put; 181 + } 182 + pr_debug("IBLOCK setup BIP bs->bio_integrity_pool: %p\n", 183 + bs->bio_integrity_pool); 184 + } 185 + dev->dev_attrib.hw_pi_prot_type = dev->dev_attrib.pi_prot_type; 186 + } 187 + 159 188 return 0; 160 189 190 + out_blkdev_put: 191 + blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); 161 192 out_free_bioset: 162 193 bioset_free(ib_dev->ibd_bio_set); 163 194 ib_dev->ibd_bio_set = NULL; ··· 203 170 204 171 if (ib_dev->ibd_bd != NULL) 205 172 blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); 206 - if (ib_dev->ibd_bio_set != NULL) 173 + if (ib_dev->ibd_bio_set != NULL) { 174 + bioset_integrity_free(ib_dev->ibd_bio_set); 207 175 bioset_free(ib_dev->ibd_bio_set); 176 + } 208 177 kfree(ib_dev); 209 178 } 210 179 ··· 621 586 return bl; 622 587 } 623 588 589 + static int 590 + iblock_alloc_bip(struct se_cmd *cmd, struct bio *bio) 591 + { 592 + struct se_device *dev = cmd->se_dev; 593 + struct blk_integrity *bi; 594 + struct bio_integrity_payload *bip; 595 + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); 596 + struct scatterlist *sg; 597 + int i, rc; 598 + 599 + bi = bdev_get_integrity(ib_dev->ibd_bd); 600 + if (!bi) { 601 + pr_err("Unable to locate bio_integrity\n"); 602 + return -ENODEV; 603 + } 604 + 605 + bip = bio_integrity_alloc(bio, GFP_NOIO, cmd->t_prot_nents); 606 + if (!bip) { 607 + pr_err("Unable to allocate bio_integrity_payload\n"); 608 + return -ENOMEM; 609 + } 610 + 611 + bip->bip_size = (cmd->data_length / dev->dev_attrib.block_size) * 612 + dev->prot_length; 613 + bip->bip_sector = bio->bi_sector; 614 + 615 + pr_debug("IBLOCK BIP Size: %u Sector: %llu\n", bip->bip_size, 616 + (unsigned long long)bip->bip_sector); 617 + 618 + for_each_sg(cmd->t_prot_sg, sg, cmd->t_prot_nents, i) { 619 + 620 + rc = bio_integrity_add_page(bio, sg_page(sg), sg->length, 621 + sg->offset); 622 + if (rc != sg->length) { 623 + pr_err("bio_integrity_add_page() failed; %d\n", rc); 624 + return -ENOMEM; 625 + } 626 + 627 + pr_debug("Added bio integrity page: %p length: %d offset; %d\n", 628 + sg_page(sg), sg->length, sg->offset); 629 + } 630 + 631 + return 0; 632 + } 633 + 624 634 static sense_reason_t 625 635 iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, 626 636 enum dma_data_direction data_direction) 627 637 { 628 638 struct se_device *dev = cmd->se_dev; 629 639 struct iblock_req *ibr; 630 - struct bio *bio; 640 + struct bio *bio, *bio_start; 631 641 struct bio_list list; 632 642 struct scatterlist *sg; 633 643 u32 sg_num = sgl_nents; ··· 735 655 if (!bio) 736 656 goto fail_free_ibr; 737 657 658 + bio_start = bio; 738 659 bio_list_init(&list); 739 660 bio_list_add(&list, bio); 740 661 ··· 767 686 /* Always in 512 byte units for Linux/Block */ 768 687 block_lba += sg->length >> IBLOCK_LBA_SHIFT; 769 688 sg_num--; 689 + } 690 + 691 + if (cmd->prot_type) { 692 + int rc = iblock_alloc_bip(cmd, bio_start); 693 + if (rc) 694 + goto fail_put_bios; 770 695 } 771 696 772 697 iblock_submit_bios(&list, rw);