diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-31 18:31:23 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-31 18:31:23 -0500 |
commit | 4e13c5d0212f25d69a97606b9d5a85edb52a7737 (patch) | |
tree | 002f59b9151f42a6388656762f0e7963d08b89ef /drivers/target/target_core_iblock.c | |
parent | deb2a1d29bf0168ff2575e714e5c1f156be663fb (diff) | |
parent | 5259a06ef97068b710f45d092a587e8d740f750f (diff) |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger:
"The highlights this round include:
- add support for SCSI Referrals (Hannes)
- add support for T10 DIF into target core (nab + mkp)
- add support for T10 DIF emulation in FILEIO + RAMDISK backends (Sagi + nab)
- add support for T10 DIF -> bio_integrity passthrough in IBLOCK backend (nab)
- prep changes to iser-target for >= v3.15 T10 DIF support (Sagi)
- add support for qla2xxx N_Port ID Virtualization - NPIV (Saurav + Quinn)
- allow percpu_ida_alloc() to receive task state bitmask (Kent)
- fix >= v3.12 iscsi-target session reset hung task regression (nab)
- fix >= v3.13 percpu_ref se_lun->lun_ref_active race (nab)
- fix a long-standing network portal creation race (Andy)"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (51 commits)
target: Fix percpu_ref_put race in transport_lun_remove_cmd
target/iscsi: Fix network portal creation race
target: Report bad sector in sense data for DIF errors
iscsi-target: Convert gfp_t parameter to task state bitmask
iscsi-target: Fix connection reset hang with percpu_ida_alloc
percpu_ida: Make percpu_ida_alloc + callers accept task state bitmask
iscsi-target: Pre-allocate more tags to avoid ack starvation
qla2xxx: Configure NPIV fc_vport via tcm_qla2xxx_npiv_make_lport
qla2xxx: Enhancements to enable NPIV support for QLOGIC ISPs with TCM/LIO.
qla2xxx: Fix scsi_host leak on qlt_lport_register callback failure
IB/isert: pass scatterlist instead of cmd to fast_reg_mr routine
IB/isert: Move fastreg descriptor creation to a function
IB/isert: Avoid frwr notation, user fastreg
IB/isert: seperate connection protection domains and dma MRs
tcm_loop: Enable DIF/DIX modes in SCSI host LLD
target/rd: Add DIF protection into rd_execute_rw
target/rd: Add support for protection SGL setup + release
target/rd: Refactor rd_build_device_space + rd_release_device_space
target/file: Add DIF protection support to fd_execute_rw
target/file: Add DIF protection init/format support
...
Diffstat (limited to 'drivers/target/target_core_iblock.c')
-rw-r--r-- | drivers/target/target_core_iblock.c | 93 |
1 files changed, 90 insertions, 3 deletions
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 2d29356d0c85..554d4f75a75a 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 | ||
191 | out_blkdev_put: | ||
192 | blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL); | ||
160 | out_free_bioset: | 193 | out_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 | ||
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_iter.bi_size = (cmd->data_length / dev->dev_attrib.block_size) * | ||
647 | dev->prot_length; | ||
648 | bip->bip_iter.bi_sector = bio->bi_iter.bi_sector; | ||
649 | |||
650 | pr_debug("IBLOCK BIP Size: %u Sector: %llu\n", bip->bip_iter.bi_size, | ||
651 | (unsigned long long)bip->bip_iter.bi_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 | static sense_reason_t | 669 | static sense_reason_t |
590 | iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | 670 | iblock_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; |
@@ -763,7 +850,7 @@ iblock_parse_cdb(struct se_cmd *cmd) | |||
763 | return sbc_parse_cdb(cmd, &iblock_sbc_ops); | 850 | return sbc_parse_cdb(cmd, &iblock_sbc_ops); |
764 | } | 851 | } |
765 | 852 | ||
766 | bool iblock_get_write_cache(struct se_device *dev) | 853 | static bool iblock_get_write_cache(struct se_device *dev) |
767 | { | 854 | { |
768 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); | 855 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
769 | struct block_device *bd = ib_dev->ibd_bd; | 856 | struct block_device *bd = ib_dev->ibd_bd; |