Skip to content

Commit ecebbf6

Browse files
author
Nicholas Bellinger
committed
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 <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: Hannes Reinecke <[email protected]> Cc: Sagi Grimberg <[email protected]> Cc: Or Gerlitz <[email protected]> Signed-off-by: Nicholas Bellinger <[email protected]>
1 parent def2b33 commit ecebbf6

File tree

2 files changed

+90
-2
lines changed

2 files changed

+90
-2
lines changed

drivers/target/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ if TARGET_CORE
1414

1515
config TCM_IBLOCK
1616
tristate "TCM/IBLOCK Subsystem Plugin for Linux/BLOCK"
17+
select BLK_DEV_INTEGRITY
1718
help
1819
Say Y here to enable the TCM/IBLOCK subsystem plugin for non-buffered
1920
access to Linux/Block devices using BIO

drivers/target/target_core_iblock.c

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ static int iblock_configure_device(struct se_device *dev)
9191
struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
9292
struct request_queue *q;
9393
struct block_device *bd = NULL;
94+
struct blk_integrity *bi;
9495
fmode_t mode;
9596
int ret = -ENOMEM;
9697

@@ -155,8 +156,40 @@ static int iblock_configure_device(struct se_device *dev)
155156
if (blk_queue_nonrot(q))
156157
dev->dev_attrib.is_nonrot = 1;
157158

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+
158189
return 0;
159190

191+
out_blkdev_put:
192+
blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
160193
out_free_bioset:
161194
bioset_free(ib_dev->ibd_bio_set);
162195
ib_dev->ibd_bio_set = NULL;
@@ -170,8 +203,10 @@ static void iblock_free_device(struct se_device *dev)
170203

171204
if (ib_dev->ibd_bd != NULL)
172205
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);
174208
bioset_free(ib_dev->ibd_bio_set);
209+
}
175210
kfree(ib_dev);
176211
}
177212

@@ -586,13 +621,58 @@ static ssize_t iblock_show_configfs_dev_params(struct se_device *dev, char *b)
586621
return bl;
587622
}
588623

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+
589669
static sense_reason_t
590670
iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
591671
enum dma_data_direction data_direction)
592672
{
593673
struct se_device *dev = cmd->se_dev;
594674
struct iblock_req *ibr;
595-
struct bio *bio;
675+
struct bio *bio, *bio_start;
596676
struct bio_list list;
597677
struct scatterlist *sg;
598678
u32 sg_num = sgl_nents;
@@ -655,6 +735,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
655735
if (!bio)
656736
goto fail_free_ibr;
657737

738+
bio_start = bio;
658739
bio_list_init(&list);
659740
bio_list_add(&list, bio);
660741

@@ -688,6 +769,12 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
688769
sg_num--;
689770
}
690771

772+
if (cmd->prot_type) {
773+
int rc = iblock_alloc_bip(cmd, bio_start);
774+
if (rc)
775+
goto fail_put_bios;
776+
}
777+
691778
iblock_submit_bios(&list, rw);
692779
iblock_complete_cmd(cmd);
693780
return 0;

0 commit comments

Comments
 (0)