Commit ecebbf6ccbca58b4470f092cfb0644df59ea05dd
1 parent
def2b339b4
Exists in
master
and in
16 other branches
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
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); |