]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
block: don't merge bios with different app_tags
authorCaleb Sander Mateos <csander@purestorage.com>
Tue, 6 Jan 2026 20:08:37 +0000 (13:08 -0700)
committerJens Axboe <axboe@kernel.dk>
Wed, 7 Jan 2026 02:10:08 +0000 (19:10 -0700)
nvme_set_app_tag() uses the app_tag value from the bio_integrity_payload
of the struct request's first bio. This assumes all the request's bios
have the same app_tag. However, it is possible for bios with different
app_tag values to be merged into a single request.
Add a check in blk_integrity_merge_{bio,rq}() to prevent the merging of
bios/requests with different app_tag values if BIP_CHECK_APPTAG is set.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Fixes: 3d8b5a22d404 ("block: add support to pass user meta buffer")
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-integrity.c

index 9b27963680dc34675df3a89b55a7129cda8524b9..964eebbee14d04a24966c331d2f22f110047596f 100644 (file)
@@ -140,14 +140,21 @@ EXPORT_SYMBOL_GPL(blk_rq_integrity_map_user);
 bool blk_integrity_merge_rq(struct request_queue *q, struct request *req,
                            struct request *next)
 {
+       struct bio_integrity_payload *bip, *bip_next;
+
        if (blk_integrity_rq(req) == 0 && blk_integrity_rq(next) == 0)
                return true;
 
        if (blk_integrity_rq(req) == 0 || blk_integrity_rq(next) == 0)
                return false;
 
-       if (bio_integrity(req->bio)->bip_flags !=
-           bio_integrity(next->bio)->bip_flags)
+       bip = bio_integrity(req->bio);
+       bip_next = bio_integrity(next->bio);
+       if (bip->bip_flags != bip_next->bip_flags)
+               return false;
+
+       if (bip->bip_flags & BIP_CHECK_APPTAG &&
+           bip->app_tag != bip_next->app_tag)
                return false;
 
        if (req->nr_integrity_segments + next->nr_integrity_segments >
@@ -163,15 +170,21 @@ bool blk_integrity_merge_rq(struct request_queue *q, struct request *req,
 bool blk_integrity_merge_bio(struct request_queue *q, struct request *req,
                             struct bio *bio)
 {
+       struct bio_integrity_payload *bip, *bip_bio = bio_integrity(bio);
        int nr_integrity_segs;
 
-       if (blk_integrity_rq(req) == 0 && bio_integrity(bio) == NULL)
+       if (blk_integrity_rq(req) == 0 && bip_bio == NULL)
                return true;
 
-       if (blk_integrity_rq(req) == 0 || bio_integrity(bio) == NULL)
+       if (blk_integrity_rq(req) == 0 || bip_bio == NULL)
+               return false;
+
+       bip = bio_integrity(req->bio);
+       if (bip->bip_flags != bip_bio->bip_flags)
                return false;
 
-       if (bio_integrity(req->bio)->bip_flags != bio_integrity(bio)->bip_flags)
+       if (bip->bip_flags & BIP_CHECK_APPTAG &&
+           bip->app_tag != bip_bio->app_tag)
                return false;
 
        nr_integrity_segs = blk_rq_count_integrity_sg(q, bio);