Re: [PATCH v4 1/5] block: use integrity interval instead of sector as seed
Caleb Sander Mateos <[email protected]> Wed, 1 Jul 2026 12:56:24 -0700
| Newsgroups | org.kernel.vger.target-devel,org.infradead.lists.linux-nvme,org.kernel.vger.linux-block,org.kernel.vger.linux-kernel,org.kernel.vger.linux-scsi |
|---|---|
| Message-ID | <CADUfDZqE6JLLbugK+qYe=XFSLV5zUwFEQ6qRqvJ-=uVs8OtfVg@mail.gmail.com> |
On Fri, Jun 26, 2026 at 10:42 PM Caleb Sander Mateos <[email protected]> wrote: > > bio_integrity_setup_default() and blk_integrity_iterate() set the > integrity seed (initial reference tag) to the absolute address in the > block device in units of 512-byte sectors. However, Type 1 and Type 2 > ref tags are actually the least significant bits of the integrity > interval number. On devices with integrity interval size > 512 bytes, > the ref tag seed thus isn't the correct initial ref tag. The ref tag > seed is correctly incremented/decremented in units of integrity > intervals in bio_integrity_map_iter(), bio_integrity_advance(), and > blk_integrity_interval(). > > For REQ_OP_{WRITE,READ}, blk_integrity_{prepare,complete}() covers up > this ref tag seed discrepancy by adding/subtracting the difference > between the initial integrity interval and ref tag values to/from each > ref tag in the protection information. However, REQ_OP_ZONE_APPEND can > also carry PI but doesn't go through blk_integrity_prepare() because the > final data location on the zoned block device isn't known until the > operation completes. As a result, the REQ_OP_ZONE_APPEND PI ref tags > start from the ref tag seed, which isn't in integrity interval units. > Subsequent reads of the appended blocks will fail to remap the ref tags > from the expected integrity interval numbers to sector numbers. > > Additionally, NVMe and many SCSI transports support offloading ref tag > remapping to the device by specifying the expected initial ref tag in > the command. The kernel doesn't currently take advantage of this, always > remapping ref tags in software for reads and writes and setting the > expected initial ref tag to the integrity interval. Setting the ref tag > seed in units of integrity intervals would be a prerequisite to allowing > the kernel to skip the software remapping and pass the ref tag seed as > the expected initial ref tag in the command. > > So compute the ref tag seed in units of integrity intervals instead of > sectors to avoid relying on ref tag remapping for the conversion. Martin, are you okay with this updated commit message? Would be nice to get this fix in so auto-integrity works correctly for zone appends on 4KB-integrity-interval devices. Thanks, Caleb > > Fixes: 0512a75b98f8 ("block: Introduce REQ_OP_ZONE_APPEND") > Signed-off-by: Caleb Sander Mateos <[email protected]> > Reviewed-by: Anuj Gupta <[email protected]> > Reviewed-by: Christoph Hellwig <[email protected]> > --- > block/bio-integrity.c | 3 ++- > block/t10-pi.c | 3 ++- > 2 files changed, 4 insertions(+), 2 deletions(-) > > diff --git a/block/bio-integrity.c b/block/bio-integrity.c > index b23e2434d80c..d20f9002c7c9 100644 > --- a/block/bio-integrity.c > +++ b/block/bio-integrity.c > @@ -102,12 +102,13 @@ void bio_integrity_free_buf(struct bio_integrity_payload *bip) > > void bio_integrity_setup_default(struct bio *bio) > { > struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); > struct bio_integrity_payload *bip = bio_integrity(bio); > + u64 seed = bio->bi_iter.bi_sector >> (bi->interval_exp - SECTOR_SHIFT); > > - bip_set_seed(bip, bio->bi_iter.bi_sector); > + bip_set_seed(bip, seed); > > if (bi->csum_type) { > bip->bip_flags |= BIP_CHECK_GUARD; > if (bi->csum_type == BLK_INTEGRITY_CSUM_IP) > bip->bip_flags |= BIP_IP_CHECKSUM; > diff --git a/block/t10-pi.c b/block/t10-pi.c > index a19b4e102a83..e58d5eb6cefb 100644 > --- a/block/t10-pi.c > +++ b/block/t10-pi.c > @@ -308,18 +308,19 @@ static blk_status_t blk_integrity_iterate(struct bio *bio, > struct bvec_iter *data_iter, > bool verify) > { > struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); > struct bio_integrity_payload *bip = bio_integrity(bio); > + u64 seed = data_iter->bi_sector >> (bi->interval_exp - SECTOR_SHIFT); > struct blk_integrity_iter iter = { > .bio = bio, > .bip = bip, > .bi = bi, > .data_iter = *data_iter, > .prot_iter = bip->bip_iter, > .interval_remaining = 1 << bi->interval_exp, > - .seed = data_iter->bi_sector, > + .seed = seed, > .csum = 0, > }; > blk_status_t ret = BLK_STS_OK; > > while (iter.data_iter.bi_size && ret == BLK_STS_OK) { > -- > 2.54.0 >