Skip to content

Commit 203247c

Browse files
keithbuschaxboe
authored andcommitted
blk-integrity: support arbitrary buffer alignment
A bio segment may have partial interval block data with the rest continuing into the next segments because direct-io data payloads only need to align in memory to the device's DMA limits. At the same time, the protection information may also be split in multiple segments. The most likely way that may happen is if two requests merge, or if we're directly using the io_uring user metadata. The generate/verify, however, only ever accessed the first bip_vec. Further, it may be possible to unalign the protection fields from the user space buffer, or if there are odd additional opaque bytes in front or in back of the protection information metadata region. Change up the iteration to allow spanning multiple segments. This patch is mostly a re-write of the protection information handling to allow any arbitrary alignments, so it's probably easier to review the end result rather than the diff. Many controllers are not able to handle interval data composed of multiple segments when PI is used, so this patch introduces a new integrity limit that a low level driver can set to notify that it is capable, default to false. The nvme driver is the first one to enable it in this patch. Everyone else will force DMA alignment to the logical block size as before to ensure interval data is always aligned within a single segment. Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Keith Busch <kbusch@kernel.org> Link: https://patch.msgid.link/20260313144701.1221652-2-kbusch@meta.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 3dbaacf commit 203247c

4 files changed

Lines changed: 465 additions & 365 deletions

File tree

block/blk-settings.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,11 @@ static int blk_validate_integrity_limits(struct queue_limits *lim)
189189
}
190190

191191
/*
192-
* The PI generation / validation helpers do not expect intervals to
193-
* straddle multiple bio_vecs. Enforce alignment so that those are
192+
* Some IO controllers can not handle data intervals straddling
193+
* multiple bio_vecs. For those, enforce alignment so that those are
194194
* never generated, and that each buffer is aligned as expected.
195195
*/
196-
if (bi->csum_type) {
196+
if (!(bi->flags & BLK_SPLIT_INTERVAL_CAPABLE) && bi->csum_type) {
197197
lim->dma_alignment = max(lim->dma_alignment,
198198
(1U << bi->interval_exp) - 1);
199199
}
@@ -992,10 +992,14 @@ bool queue_limits_stack_integrity(struct queue_limits *t,
992992
if ((ti->flags & BLK_INTEGRITY_REF_TAG) !=
993993
(bi->flags & BLK_INTEGRITY_REF_TAG))
994994
goto incompatible;
995+
if ((ti->flags & BLK_SPLIT_INTERVAL_CAPABLE) &&
996+
!(bi->flags & BLK_SPLIT_INTERVAL_CAPABLE))
997+
ti->flags &= ~BLK_SPLIT_INTERVAL_CAPABLE;
995998
} else {
996999
ti->flags = BLK_INTEGRITY_STACKED;
9971000
ti->flags |= (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE) |
998-
(bi->flags & BLK_INTEGRITY_REF_TAG);
1001+
(bi->flags & BLK_INTEGRITY_REF_TAG) |
1002+
(bi->flags & BLK_SPLIT_INTERVAL_CAPABLE);
9991003
ti->csum_type = bi->csum_type;
10001004
ti->pi_tuple_size = bi->pi_tuple_size;
10011005
ti->metadata_size = bi->metadata_size;

0 commit comments

Comments
 (0)