Commit ecebbf6ccbca58b4470f092cfb0644df59ea05dd

Authored by Nicholas Bellinger
1 parent def2b339b4

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>

Showing 2 changed files with 90 additions and 2 deletions Side-by-side Diff

drivers/target/Kconfig
... ... @@ -14,6 +14,7 @@
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
drivers/target/target_core_iblock.c
... ... @@ -91,6 +91,7 @@
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  
97 98  
... ... @@ -155,8 +156,40 @@
155 156 if (blk_queue_nonrot(q))
156 157 dev->dev_attrib.is_nonrot = 1;
157 158  
  159 + bi = bdev_get_integrity(bd);
  160 + if (bi) {
  161 + struct bio_set *bs = ib_dev->ibd_bio_set;
  162 +
  163 + if (!strcmp(bi->name, "T10-DIF-TYPE3-IP") ||
  164 + !strcmp(bi->name, "T10-DIF-TYPE1-IP")) {
  165 + pr_err("IBLOCK export of blk_integrity: %s not"
  166 + " supported\n", bi->name);
  167 + ret = -ENOSYS;
  168 + goto out_blkdev_put;
  169 + }
  170 +
  171 + if (!strcmp(bi->name, "T10-DIF-TYPE3-CRC")) {
  172 + dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE3_PROT;
  173 + } else if (!strcmp(bi->name, "T10-DIF-TYPE1-CRC")) {
  174 + dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE1_PROT;
  175 + }
  176 +
  177 + if (dev->dev_attrib.pi_prot_type) {
  178 + if (bioset_integrity_create(bs, IBLOCK_BIO_POOL_SIZE) < 0) {
  179 + pr_err("Unable to allocate bioset for PI\n");
  180 + ret = -ENOMEM;
  181 + goto out_blkdev_put;
  182 + }
  183 + pr_debug("IBLOCK setup BIP bs->bio_integrity_pool: %p\n",
  184 + bs->bio_integrity_pool);
  185 + }
  186 + dev->dev_attrib.hw_pi_prot_type = dev->dev_attrib.pi_prot_type;
  187 + }
  188 +
158 189 return 0;
159 190  
  191 +out_blkdev_put:
  192 + blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
160 193 out_free_bioset:
161 194 bioset_free(ib_dev->ibd_bio_set);
162 195 ib_dev->ibd_bio_set = NULL;
163 196  
... ... @@ -170,8 +203,10 @@
170 203  
171 204 if (ib_dev->ibd_bd != NULL)
172 205 blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
173   - if (ib_dev->ibd_bio_set != NULL)
  206 + if (ib_dev->ibd_bio_set != NULL) {
  207 + bioset_integrity_free(ib_dev->ibd_bio_set);
174 208 bioset_free(ib_dev->ibd_bio_set);
  209 + }
175 210 kfree(ib_dev);
176 211 }
177 212  
178 213  
... ... @@ -586,13 +621,58 @@
586 621 return bl;
587 622 }
588 623  
  624 +static int
  625 +iblock_alloc_bip(struct se_cmd *cmd, struct bio *bio)
  626 +{
  627 + struct se_device *dev = cmd->se_dev;
  628 + struct blk_integrity *bi;
  629 + struct bio_integrity_payload *bip;
  630 + struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
  631 + struct scatterlist *sg;
  632 + int i, rc;
  633 +
  634 + bi = bdev_get_integrity(ib_dev->ibd_bd);
  635 + if (!bi) {
  636 + pr_err("Unable to locate bio_integrity\n");
  637 + return -ENODEV;
  638 + }
  639 +
  640 + bip = bio_integrity_alloc(bio, GFP_NOIO, cmd->t_prot_nents);
  641 + if (!bip) {
  642 + pr_err("Unable to allocate bio_integrity_payload\n");
  643 + return -ENOMEM;
  644 + }
  645 +
  646 + bip->bip_size = (cmd->data_length / dev->dev_attrib.block_size) *
  647 + dev->prot_length;
  648 + bip->bip_sector = bio->bi_sector;
  649 +
  650 + pr_debug("IBLOCK BIP Size: %u Sector: %llu\n", bip->bip_size,
  651 + (unsigned long long)bip->bip_sector);
  652 +
  653 + for_each_sg(cmd->t_prot_sg, sg, cmd->t_prot_nents, i) {
  654 +
  655 + rc = bio_integrity_add_page(bio, sg_page(sg), sg->length,
  656 + sg->offset);
  657 + if (rc != sg->length) {
  658 + pr_err("bio_integrity_add_page() failed; %d\n", rc);
  659 + return -ENOMEM;
  660 + }
  661 +
  662 + pr_debug("Added bio integrity page: %p length: %d offset; %d\n",
  663 + sg_page(sg), sg->length, sg->offset);
  664 + }
  665 +
  666 + return 0;
  667 +}
  668 +
589 669 static sense_reason_t
590 670 iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
591 671 enum dma_data_direction data_direction)
592 672 {
593 673 struct se_device *dev = cmd->se_dev;
594 674 struct iblock_req *ibr;
595   - struct bio *bio;
  675 + struct bio *bio, *bio_start;
596 676 struct bio_list list;
597 677 struct scatterlist *sg;
598 678 u32 sg_num = sgl_nents;
... ... @@ -655,6 +735,7 @@
655 735 if (!bio)
656 736 goto fail_free_ibr;
657 737  
  738 + bio_start = bio;
658 739 bio_list_init(&list);
659 740 bio_list_add(&list, bio);
660 741  
... ... @@ -686,6 +767,12 @@
686 767 /* Always in 512 byte units for Linux/Block */
687 768 block_lba += sg->length >> IBLOCK_LBA_SHIFT;
688 769 sg_num--;
  770 + }
  771 +
  772 + if (cmd->prot_type) {
  773 + int rc = iblock_alloc_bip(cmd, bio_start);
  774 + if (rc)
  775 + goto fail_put_bios;
689 776 }
690 777  
691 778 iblock_submit_bios(&list, rw);