Introduce a new pi_size field in struct blk_integrity to explicitly represent the size (in bytes) of the protection information (PI) tuple. This is a prep patch. Add validation in blk_validate_integrity_limits() to ensure that pi_size matches the expected size for know checksum types and never exceeds the tuple_size. Suggested-by: Christoph Hellwig <hch@xxxxxx> Signed-off-by: Anuj Gupta <anuj20.g@xxxxxxxxxxx> --- block/blk-settings.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/nvme/host/core.c | 1 + drivers/scsi/sd_dif.c | 1 + include/linux/blkdev.h | 1 + 4 files changed, 40 insertions(+) diff --git a/block/blk-settings.c b/block/blk-settings.c index a000daafbfb4..125b23acb5b7 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -14,6 +14,8 @@ #include <linux/jiffies.h> #include <linux/gfp.h> #include <linux/dma-mapping.h> +#include <linux/t10-pi.h> +#include <linux/crc64.h> #include "blk.h" #include "blk-rq-qos.h" @@ -135,6 +137,41 @@ static int blk_validate_integrity_limits(struct queue_limits *lim) return -EINVAL; } + if (bi->pi_size > bi->tuple_size) { + pr_warn("pi_size (%u) exceeds tuple_size (%u)\n", + bi->pi_size, bi->tuple_size); + return -EINVAL; + } + + switch (bi->csum_type) { + case BLK_INTEGRITY_CSUM_NONE: + if (!bi->pi_size) { + pr_warn("pi_size must be 0 when checksum type \ + is none\n"); + return -EINVAL; + } + break; + case BLK_INTEGRITY_CSUM_CRC: + case BLK_INTEGRITY_CSUM_IP: + if (bi->pi_size != sizeof(struct t10_pi_tuple)) { + pr_warn("pi_size mismatch for T10 PI: expected \ + %zu, got %u\n", + sizeof(struct t10_pi_tuple), + bi->pi_size); + return -EINVAL; + } + break; + case BLK_INTEGRITY_CSUM_CRC64: + if (bi->pi_size != sizeof(struct crc64_pi_tuple)) { + pr_warn("pi_size mismatch for CRC64 PI: \ + expected %zu, got %u\n", + sizeof(struct crc64_pi_tuple), + bi->pi_size); + return -EINVAL; + } + break; + } + if (!bi->interval_exp) bi->interval_exp = ilog2(lim->logical_block_size); diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index f69a232a000a..a9a2a0ca9797 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1868,6 +1868,7 @@ static bool nvme_init_integrity(struct nvme_ns_head *head, } bi->tuple_size = head->ms; + bi->pi_size = head->pi_size; bi->pi_offset = info->pi_offset; return true; } diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index ae6ce6f5d622..9c39a82298da 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c @@ -53,6 +53,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp, struct queue_limits *lim) bi->flags |= BLK_INTEGRITY_REF_TAG; bi->tuple_size = sizeof(struct t10_pi_tuple); + bi->pi_size = bi->tuple_size; if (dif && type) { bi->flags |= BLK_INTEGRITY_DEVICE_CAPABLE; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 332b56f323d9..1ed604b70e0f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -120,6 +120,7 @@ struct blk_integrity { unsigned char pi_offset; unsigned char interval_exp; unsigned char tag_size; + unsigned char pi_size; }; typedef unsigned int __bitwise blk_mode_t; -- 2.25.1