Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions block/blk-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ bool blk_integrity_merge_rq(struct request_queue *q, struct request *req,
struct request *next)
{
struct bio_integrity_payload *bip, *bip_next;
struct blk_integrity *bi;
u64 intervals;

if (blk_integrity_rq(req) == 0 && blk_integrity_rq(next) == 0)
return true;
Expand All @@ -157,6 +159,13 @@ bool blk_integrity_merge_rq(struct request_queue *q, struct request *req,
bip->app_tag != bip_next->app_tag)
return false;

bi = blk_get_integrity(req->bio->bi_bdev->bd_disk);
intervals = blk_rq_bytes(req) >> bi->interval_exp;
if (bip->bip_flags & BIP_CHECK_REFTAG &&
bi->flags & BLK_EXPECTED_REF_TAG_CAPABLE &&
bip->bip_iter.bi_sector + intervals != bip_next->bip_iter.bi_sector)
return false;

if (req->nr_integrity_segments + next->nr_integrity_segments >
q->limits.max_integrity_segments)
return false;
Expand All @@ -171,7 +180,9 @@ 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);
struct blk_integrity *bi;
int nr_integrity_segs;
u64 intervals;

if (blk_integrity_rq(req) == 0 && bip_bio == NULL)
return true;
Expand All @@ -187,6 +198,13 @@ bool blk_integrity_merge_bio(struct request_queue *q, struct request *req,
bip->app_tag != bip_bio->app_tag)
return false;

bi = blk_get_integrity(req->bio->bi_bdev->bd_disk);
intervals = blk_rq_bytes(req) >> bi->interval_exp;
if (bip->bip_flags & BIP_CHECK_REFTAG &&
bi->flags & BLK_EXPECTED_REF_TAG_CAPABLE &&
bip->bip_iter.bi_sector + intervals != bip_bio->bip_iter.bi_sector)
return false;

nr_integrity_segs = blk_rq_count_integrity_sg(q, bio);
if (req->nr_integrity_segments + nr_integrity_segs >
q->limits.max_integrity_segments)
Expand Down
3 changes: 2 additions & 1 deletion block/t10-pi.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,8 @@ static void blk_integrity_remap(struct request *rq, unsigned int nr_bytes,
unsigned intervals = nr_bytes >> bi->interval_exp;
struct bio *bio;

if (!(bi->flags & BLK_INTEGRITY_REF_TAG))
if (!(bi->flags & BLK_INTEGRITY_REF_TAG) ||
bi->flags & BLK_EXPECTED_REF_TAG_CAPABLE)
return;

__rq_for_each_bio(bio, rq) {
Expand Down
20 changes: 10 additions & 10 deletions drivers/nvme/host/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -916,8 +916,7 @@ static void nvme_set_app_tag(struct request *req, struct nvme_command *cmnd)
static void nvme_set_ref_tag(struct nvme_ns *ns, struct nvme_command *cmnd,
struct request *req)
{
u32 upper, lower;
u64 ref48;
u64 ref_tag;

/* only type1 and type 2 PI formats have a reftag */
switch (ns->head->pi_type) {
Expand All @@ -928,18 +927,19 @@ static void nvme_set_ref_tag(struct nvme_ns *ns, struct nvme_command *cmnd,
return;
}

ref_tag = full_pi_ref_tag(req);
if (blk_integrity_rq(req))
ref_tag = bio_integrity(req->bio)->bip_iter.bi_sector;

/* both rw and write zeroes share the same reftag format */
switch (ns->head->guard_type) {
case NVME_NVM_NS_16B_GUARD:
cmnd->rw.reftag = cpu_to_le32(t10_pi_ref_tag(req));
cmnd->rw.reftag = cpu_to_le32(lower_32_bits(ref_tag));
break;
case NVME_NVM_NS_64B_GUARD:
ref48 = ext_pi_ref_tag(req);
lower = lower_32_bits(ref48);
upper = upper_32_bits(ref48);

cmnd->rw.reftag = cpu_to_le32(lower);
cmnd->rw.cdw3 = cpu_to_le32(upper);
ref_tag = lower_48_bits(ref_tag);
cmnd->rw.reftag = cpu_to_le32(lower_32_bits(ref_tag));
cmnd->rw.cdw3 = cpu_to_le32(upper_32_bits(ref_tag));
break;
default:
break;
Expand Down Expand Up @@ -1891,7 +1891,7 @@ static bool nvme_init_integrity(struct nvme_ns_head *head,
break;
}

bi->flags |= BLK_SPLIT_INTERVAL_CAPABLE;
bi->flags |= BLK_SPLIT_INTERVAL_CAPABLE | BLK_EXPECTED_REF_TAG_CAPABLE;
bi->metadata_size = head->ms;
if (bi->csum_type) {
bi->pi_tuple_size = head->pi_size;
Expand Down
2 changes: 2 additions & 0 deletions include/linux/blk-integrity.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ enum blk_integrity_flags {
BLK_INTEGRITY_REF_TAG = 1 << 3,
BLK_INTEGRITY_STACKED = 1 << 4,
BLK_SPLIT_INTERVAL_CAPABLE = 1 << 5,
/* Device I/O specifies expected initial ref tag independent of LBA */
BLK_EXPECTED_REF_TAG_CAPABLE = 1 << 6,
};

const char *blk_integrity_profile_name(struct blk_integrity *bi);
Expand Down
5 changes: 0 additions & 5 deletions include/linux/t10-pi.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,4 @@ static inline u64 lower_48_bits(u64 n)
return n & ((1ull << 48) - 1);
}

static inline u64 ext_pi_ref_tag(struct request *rq)
{
return lower_48_bits(full_pi_ref_tag(rq));
}

#endif