| From 3b49719a62e5389e6dfc93a279a6be235697f609 Mon Sep 17 00:00:00 2001 |
| From: Israel Rukshin <israelr@mellanox.com> |
| Date: Wed, 11 Dec 2019 17:36:02 +0200 |
| Subject: [PATCH] scsi: target/iblock: Fix protection error with blocks greater |
| than 512B |
| |
| commit e4dc9a4c31fe10d1751c542702afc85be8a5c56a upstream. |
| |
| The sector size of the block layer is 512 bytes, but integrity interval |
| size might be different (in case of 4K block size of the media). At the |
| initiator side the virtual start sector is the one that was originally |
| submitted by the block layer (512 bytes) for the Reftag usage. The |
| initiator converts the Reftag to integrity interval units and sends it to |
| the target. So the target virtual start sector should be calculated at |
| integrity interval units. prepare_fn() and complete_fn() don't remap |
| correctly the Reftag when using incorrect units of the virtual start |
| sector, which leads to the following protection error at the device: |
| |
| "blk_update_request: protection error, dev sdb, sector 2048 op 0x0:(READ) |
| flags 0x10000 phys_seg 1 prio class 0" |
| |
| To fix that, set the seed in integrity interval units. |
| |
| Link: https://lore.kernel.org/r/1576078562-15240-1-git-send-email-israelr@mellanox.com |
| Signed-off-by: Israel Rukshin <israelr@mellanox.com> |
| Reviewed-by: Max Gurtovoy <maxg@mellanox.com> |
| Reviewed-by: Sagi Grimberg <sagi@grimberg.me> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c |
| index 6949ea8bc387..51ffd5c002de 100644 |
| --- a/drivers/target/target_core_iblock.c |
| +++ b/drivers/target/target_core_iblock.c |
| @@ -646,7 +646,9 @@ iblock_alloc_bip(struct se_cmd *cmd, struct bio *bio, |
| } |
| |
| bip->bip_iter.bi_size = bio_integrity_bytes(bi, bio_sectors(bio)); |
| - bip_set_seed(bip, bio->bi_iter.bi_sector); |
| + /* virtual start sector must be in integrity interval units */ |
| + bip_set_seed(bip, bio->bi_iter.bi_sector >> |
| + (bi->interval_exp - SECTOR_SHIFT)); |
| |
| pr_debug("IBLOCK BIP Size: %u Sector: %llu\n", bip->bip_iter.bi_size, |
| (unsigned long long)bip->bip_iter.bi_sector); |
| -- |
| 2.7.4 |
| |