aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2013-12-23 15:31:24 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2014-01-18 05:14:22 -0500
commitecebbf6ccbca58b4470f092cfb0644df59ea05dd (patch)
tree62bf3d2934841d0076315eddf23f17bc0985c0ac
parentdef2b339b422070ecb99298a80e4b15033adc0ce (diff)
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>
-rw-r--r--drivers/target/Kconfig1
-rw-r--r--drivers/target/target_core_iblock.c91
2 files changed, 90 insertions, 2 deletions
diff --git a/drivers/target/Kconfig b/drivers/target/Kconfig
index 50aad2eeed6e..dc2d84ac5a0e 100644
--- a/drivers/target/Kconfig
+++ b/drivers/target/Kconfig
@@ -14,6 +14,7 @@ if TARGET_CORE
14 14
15config TCM_IBLOCK 15config TCM_IBLOCK
16 tristate "TCM/IBLOCK Subsystem Plugin for Linux/BLOCK" 16 tristate "TCM/IBLOCK Subsystem Plugin for Linux/BLOCK"
17 select BLK_DEV_INTEGRITY
17 help 18 help
18 Say Y here to enable the TCM/IBLOCK subsystem plugin for non-buffered 19 Say Y here to enable the TCM/IBLOCK subsystem plugin for non-buffered
19 access to Linux/Block devices using BIO 20 access to Linux/Block devices using BIO
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 15d9121a517e..293d9b081e8a 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -91,6 +91,7 @@ static int iblock_configure_device(struct se_device *dev)
91 struct iblock_dev *ib_dev = IBLOCK_DEV(dev); 91 struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
92 struct request_queue *q; 92 struct request_queue *q;
93 struct block_device *bd = NULL; 93 struct block_device *bd = NULL;
94 struct blk_integrity *bi;
94 fmode_t mode; 95 fmode_t mode;
95 int ret = -ENOMEM; 96 int ret = -ENOMEM;
96 97
@@ -155,8 +156,40 @@ static int iblock_configure_device(struct se_device *dev)
155 if (blk_queue_nonrot(q)) 156 if (blk_queue_nonrot(q))
156 dev->dev_attrib.is_nonrot = 1; 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 return 0; 189 return 0;
159 190
191out_blkdev_put:
192 blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
160out_free_bioset: 193out_free_bioset:
161 bioset_free(ib_dev->ibd_bio_set); 194 bioset_free(ib_dev->ibd_bio_set);
162 ib_dev->ibd_bio_set = NULL; 195 ib_dev->ibd_bio_set = NULL;
@@ -170,8 +203,10 @@ static void iblock_free_device(struct se_device *dev)
170 203
171 if (ib_dev->ibd_bd != NULL) 204 if (ib_dev->ibd_bd != NULL)
172 blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); 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 bioset_free(ib_dev->ibd_bio_set); 208 bioset_free(ib_dev->ibd_bio_set);
209 }
175 kfree(ib_dev); 210 kfree(ib_dev);
176} 211}
177 212
@@ -586,13 +621,58 @@ static ssize_t iblock_show_configfs_dev_params(struct se_device *dev, char *b)
586 return bl; 621 return bl;
587} 622}
588 623
624static int
625iblock_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
589static sense_reason_t 669static sense_reason_t
590iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, 670iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
591 enum dma_data_direction data_direction) 671 enum dma_data_direction data_direction)
592{ 672{
593 struct se_device *dev = cmd->se_dev; 673 struct se_device *dev = cmd->se_dev;
594 struct iblock_req *ibr; 674 struct iblock_req *ibr;
595 struct bio *bio; 675 struct bio *bio, *bio_start;
596 struct bio_list list; 676 struct bio_list list;
597 struct scatterlist *sg; 677 struct scatterlist *sg;
598 u32 sg_num = sgl_nents; 678 u32 sg_num = sgl_nents;
@@ -655,6 +735,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
655 if (!bio) 735 if (!bio)
656 goto fail_free_ibr; 736 goto fail_free_ibr;
657 737
738 bio_start = bio;
658 bio_list_init(&list); 739 bio_list_init(&list);
659 bio_list_add(&list, bio); 740 bio_list_add(&list, bio);
660 741
@@ -688,6 +769,12 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
688 sg_num--; 769 sg_num--;
689 } 770 }
690 771
772 if (cmd->prot_type) {
773 int rc = iblock_alloc_bip(cmd, bio_start);
774 if (rc)
775 goto fail_put_bios;
776 }
777
691 iblock_submit_bios(&list, rw); 778 iblock_submit_bios(&list, rw);
692 iblock_complete_cmd(cmd); 779 iblock_complete_cmd(cmd);
693 return 0; 780 return 0;