.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /******************************************************************************* |
---|
2 | 3 | * Filename: target_core_iblock.c |
---|
3 | 4 | * |
---|
.. | .. |
---|
7 | 8 | * (c) Copyright 2003-2013 Datera, Inc. |
---|
8 | 9 | * |
---|
9 | 10 | * Nicholas A. Bellinger <nab@kernel.org> |
---|
10 | | - * |
---|
11 | | - * This program is free software; you can redistribute it and/or modify |
---|
12 | | - * it under the terms of the GNU General Public License as published by |
---|
13 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
14 | | - * (at your option) any later version. |
---|
15 | | - * |
---|
16 | | - * This program is distributed in the hope that it will be useful, |
---|
17 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
18 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
19 | | - * GNU General Public License for more details. |
---|
20 | | - * |
---|
21 | | - * You should have received a copy of the GNU General Public License |
---|
22 | | - * along with this program; if not, write to the Free Software |
---|
23 | | - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
---|
24 | 11 | * |
---|
25 | 12 | ******************************************************************************/ |
---|
26 | 13 | |
---|
.. | .. |
---|
624 | 611 | bl += sprintf(b + bl, " "); |
---|
625 | 612 | if (bd) { |
---|
626 | 613 | bl += sprintf(b + bl, "Major: %d Minor: %d %s\n", |
---|
627 | | - MAJOR(bd->bd_dev), MINOR(bd->bd_dev), (!bd->bd_contains) ? |
---|
628 | | - "" : (bd->bd_holder == ib_dev) ? |
---|
629 | | - "CLAIMED: IBLOCK" : "CLAIMED: OS"); |
---|
| 614 | + MAJOR(bd->bd_dev), MINOR(bd->bd_dev), |
---|
| 615 | + "CLAIMED: IBLOCK"); |
---|
630 | 616 | } else { |
---|
631 | 617 | bl += sprintf(b + bl, "Major: 0 Minor: 0\n"); |
---|
632 | 618 | } |
---|
.. | .. |
---|
635 | 621 | } |
---|
636 | 622 | |
---|
637 | 623 | static int |
---|
638 | | -iblock_alloc_bip(struct se_cmd *cmd, struct bio *bio) |
---|
| 624 | +iblock_alloc_bip(struct se_cmd *cmd, struct bio *bio, |
---|
| 625 | + struct sg_mapping_iter *miter) |
---|
639 | 626 | { |
---|
640 | 627 | struct se_device *dev = cmd->se_dev; |
---|
641 | 628 | struct blk_integrity *bi; |
---|
642 | 629 | struct bio_integrity_payload *bip; |
---|
643 | 630 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
---|
644 | | - struct scatterlist *sg; |
---|
645 | | - int i, rc; |
---|
| 631 | + int rc; |
---|
| 632 | + size_t resid, len; |
---|
646 | 633 | |
---|
647 | 634 | bi = bdev_get_integrity(ib_dev->ibd_bd); |
---|
648 | 635 | if (!bi) { |
---|
.. | .. |
---|
650 | 637 | return -ENODEV; |
---|
651 | 638 | } |
---|
652 | 639 | |
---|
653 | | - bip = bio_integrity_alloc(bio, GFP_NOIO, cmd->t_prot_nents); |
---|
| 640 | + bip = bio_integrity_alloc(bio, GFP_NOIO, |
---|
| 641 | + min_t(unsigned int, cmd->t_prot_nents, BIO_MAX_PAGES)); |
---|
654 | 642 | if (IS_ERR(bip)) { |
---|
655 | 643 | pr_err("Unable to allocate bio_integrity_payload\n"); |
---|
656 | 644 | return PTR_ERR(bip); |
---|
657 | 645 | } |
---|
658 | 646 | |
---|
659 | | - bip->bip_iter.bi_size = (cmd->data_length / dev->dev_attrib.block_size) * |
---|
660 | | - dev->prot_length; |
---|
661 | | - bip->bip_iter.bi_sector = bio->bi_iter.bi_sector; |
---|
| 647 | + bip->bip_iter.bi_size = bio_integrity_bytes(bi, bio_sectors(bio)); |
---|
| 648 | + /* virtual start sector must be in integrity interval units */ |
---|
| 649 | + bip_set_seed(bip, bio->bi_iter.bi_sector >> |
---|
| 650 | + (bi->interval_exp - SECTOR_SHIFT)); |
---|
662 | 651 | |
---|
663 | 652 | pr_debug("IBLOCK BIP Size: %u Sector: %llu\n", bip->bip_iter.bi_size, |
---|
664 | 653 | (unsigned long long)bip->bip_iter.bi_sector); |
---|
665 | 654 | |
---|
666 | | - for_each_sg(cmd->t_prot_sg, sg, cmd->t_prot_nents, i) { |
---|
| 655 | + resid = bip->bip_iter.bi_size; |
---|
| 656 | + while (resid > 0 && sg_miter_next(miter)) { |
---|
667 | 657 | |
---|
668 | | - rc = bio_integrity_add_page(bio, sg_page(sg), sg->length, |
---|
669 | | - sg->offset); |
---|
670 | | - if (rc != sg->length) { |
---|
| 658 | + len = min_t(size_t, miter->length, resid); |
---|
| 659 | + rc = bio_integrity_add_page(bio, miter->page, len, |
---|
| 660 | + offset_in_page(miter->addr)); |
---|
| 661 | + if (rc != len) { |
---|
671 | 662 | pr_err("bio_integrity_add_page() failed; %d\n", rc); |
---|
| 663 | + sg_miter_stop(miter); |
---|
672 | 664 | return -ENOMEM; |
---|
673 | 665 | } |
---|
674 | 666 | |
---|
675 | | - pr_debug("Added bio integrity page: %p length: %d offset; %d\n", |
---|
676 | | - sg_page(sg), sg->length, sg->offset); |
---|
| 667 | + pr_debug("Added bio integrity page: %p length: %zu offset: %lu\n", |
---|
| 668 | + miter->page, len, offset_in_page(miter->addr)); |
---|
| 669 | + |
---|
| 670 | + resid -= len; |
---|
| 671 | + if (len < miter->length) |
---|
| 672 | + miter->consumed -= miter->length - len; |
---|
677 | 673 | } |
---|
| 674 | + sg_miter_stop(miter); |
---|
678 | 675 | |
---|
679 | 676 | return 0; |
---|
680 | 677 | } |
---|
.. | .. |
---|
686 | 683 | struct se_device *dev = cmd->se_dev; |
---|
687 | 684 | sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba); |
---|
688 | 685 | struct iblock_req *ibr; |
---|
689 | | - struct bio *bio, *bio_start; |
---|
| 686 | + struct bio *bio; |
---|
690 | 687 | struct bio_list list; |
---|
691 | 688 | struct scatterlist *sg; |
---|
692 | 689 | u32 sg_num = sgl_nents; |
---|
693 | 690 | unsigned bio_cnt; |
---|
694 | | - int i, op, op_flags = 0; |
---|
| 691 | + int i, rc, op, op_flags = 0; |
---|
| 692 | + struct sg_mapping_iter prot_miter; |
---|
695 | 693 | |
---|
696 | 694 | if (data_direction == DMA_TO_DEVICE) { |
---|
697 | 695 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); |
---|
.. | .. |
---|
726 | 724 | if (!bio) |
---|
727 | 725 | goto fail_free_ibr; |
---|
728 | 726 | |
---|
729 | | - bio_start = bio; |
---|
730 | 727 | bio_list_init(&list); |
---|
731 | 728 | bio_list_add(&list, bio); |
---|
732 | 729 | |
---|
733 | 730 | refcount_set(&ibr->pending, 2); |
---|
734 | 731 | bio_cnt = 1; |
---|
| 732 | + |
---|
| 733 | + if (cmd->prot_type && dev->dev_attrib.pi_prot_type) |
---|
| 734 | + sg_miter_start(&prot_miter, cmd->t_prot_sg, cmd->t_prot_nents, |
---|
| 735 | + op == REQ_OP_READ ? SG_MITER_FROM_SG : |
---|
| 736 | + SG_MITER_TO_SG); |
---|
735 | 737 | |
---|
736 | 738 | for_each_sg(sgl, sg, sgl_nents, i) { |
---|
737 | 739 | /* |
---|
.. | .. |
---|
741 | 743 | */ |
---|
742 | 744 | while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset) |
---|
743 | 745 | != sg->length) { |
---|
| 746 | + if (cmd->prot_type && dev->dev_attrib.pi_prot_type) { |
---|
| 747 | + rc = iblock_alloc_bip(cmd, bio, &prot_miter); |
---|
| 748 | + if (rc) |
---|
| 749 | + goto fail_put_bios; |
---|
| 750 | + } |
---|
| 751 | + |
---|
744 | 752 | if (bio_cnt >= IBLOCK_MAX_BIO_PER_TASK) { |
---|
745 | 753 | iblock_submit_bios(&list); |
---|
746 | 754 | bio_cnt = 0; |
---|
.. | .. |
---|
762 | 770 | } |
---|
763 | 771 | |
---|
764 | 772 | if (cmd->prot_type && dev->dev_attrib.pi_prot_type) { |
---|
765 | | - int rc = iblock_alloc_bip(cmd, bio_start); |
---|
| 773 | + rc = iblock_alloc_bip(cmd, bio, &prot_miter); |
---|
766 | 774 | if (rc) |
---|
767 | 775 | goto fail_put_bios; |
---|
768 | 776 | } |
---|