Unverified Commit 4a3def74 authored by Christian Brauner's avatar Christian Brauner
Browse files

Merge patch series "add ioctl to query metadata and protection info capabilities"

Anuj Gupta <anuj20.g@samsung.com> says:

This patch series adds a new ioctl to query metadata and integrity
capability.

* patches from https://lore.kernel.org/20250630090548.3317-1-anuj20.g@samsung.com:
  fs: add ioctl to query metadata and protection info capabilities
  nvme: set pi_offset only when checksum type is not BLK_INTEGRITY_CSUM_NONE
  block: introduce pi_tuple_size field in blk_integrity
  block: rename tuple_size field in blk_integrity to metadata_size

Link: https://lore.kernel.org/20250630090548.3317-1-anuj20.g@samsung.com


Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parents 19272b37 9eb22f7f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -54,10 +54,10 @@ static bool bi_offload_capable(struct blk_integrity *bi)
{
	switch (bi->csum_type) {
	case BLK_INTEGRITY_CSUM_CRC64:
		return bi->tuple_size == sizeof(struct crc64_pi_tuple);
		return bi->metadata_size == sizeof(struct crc64_pi_tuple);
	case BLK_INTEGRITY_CSUM_CRC:
	case BLK_INTEGRITY_CSUM_IP:
		return bi->tuple_size == sizeof(struct t10_pi_tuple);
		return bi->metadata_size == sizeof(struct t10_pi_tuple);
	default:
		pr_warn_once("%s: unknown integrity checksum type:%d\n",
			__func__, bi->csum_type);
+53 −1
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/scatterlist.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/t10-pi.h>

#include "blk.h"

@@ -54,6 +55,57 @@ int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio)
	return segments;
}

int blk_get_meta_cap(struct block_device *bdev, unsigned int cmd,
		     struct logical_block_metadata_cap __user *argp)
{
	struct blk_integrity *bi = blk_get_integrity(bdev->bd_disk);
	struct logical_block_metadata_cap meta_cap = {};
	size_t usize = _IOC_SIZE(cmd);

	if (!argp)
		return -EINVAL;
	if (usize < LBMD_SIZE_VER0)
		return -EINVAL;
	if (!bi)
		goto out;

	if (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE)
		meta_cap.lbmd_flags |= LBMD_PI_CAP_INTEGRITY;
	if (bi->flags & BLK_INTEGRITY_REF_TAG)
		meta_cap.lbmd_flags |= LBMD_PI_CAP_REFTAG;
	meta_cap.lbmd_interval = 1 << bi->interval_exp;
	meta_cap.lbmd_size = bi->metadata_size;
	meta_cap.lbmd_pi_size = bi->pi_tuple_size;
	meta_cap.lbmd_pi_offset = bi->pi_offset;
	meta_cap.lbmd_opaque_size = bi->metadata_size - bi->pi_tuple_size;
	if (meta_cap.lbmd_opaque_size && !bi->pi_offset)
		meta_cap.lbmd_opaque_offset = bi->pi_tuple_size;

	meta_cap.lbmd_guard_tag_type = bi->csum_type;
	if (bi->csum_type != BLK_INTEGRITY_CSUM_NONE)
		meta_cap.lbmd_app_tag_size = 2;

	if (bi->flags & BLK_INTEGRITY_REF_TAG) {
		switch (bi->csum_type) {
		case BLK_INTEGRITY_CSUM_CRC64:
			meta_cap.lbmd_ref_tag_size =
				sizeof_field(struct crc64_pi_tuple, ref_tag);
			break;
		case BLK_INTEGRITY_CSUM_CRC:
		case BLK_INTEGRITY_CSUM_IP:
			meta_cap.lbmd_ref_tag_size =
				sizeof_field(struct t10_pi_tuple, ref_tag);
			break;
		default:
			break;
		}
	}

out:
	return copy_struct_to_user(argp, usize, &meta_cap, sizeof(meta_cap),
				   NULL);
}

/**
 * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
 * @rq:		request to map
@@ -239,7 +291,7 @@ static ssize_t format_show(struct device *dev, struct device_attribute *attr,
{
	struct blk_integrity *bi = dev_to_bi(dev);

	if (!bi->tuple_size)
	if (!bi->metadata_size)
		return sysfs_emit(page, "none\n");
	return sysfs_emit(page, "%s\n", blk_integrity_profile_name(bi));
}
+41 −3
Original line number Diff line number Diff line
@@ -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"
@@ -114,7 +116,7 @@ static int blk_validate_integrity_limits(struct queue_limits *lim)
{
	struct blk_integrity *bi = &lim->integrity;

	if (!bi->tuple_size) {
	if (!bi->metadata_size) {
		if (bi->csum_type != BLK_INTEGRITY_CSUM_NONE ||
		    bi->tag_size || ((bi->flags & BLK_INTEGRITY_REF_TAG))) {
			pr_warn("invalid PI settings.\n");
@@ -135,6 +137,42 @@ static int blk_validate_integrity_limits(struct queue_limits *lim)
		return -EINVAL;
	}

	if (bi->pi_tuple_size > bi->metadata_size) {
		pr_warn("pi_tuple_size (%u) exceeds metadata_size (%u)\n",
			 bi->pi_tuple_size,
			 bi->metadata_size);
		return -EINVAL;
	}

	switch (bi->csum_type) {
	case BLK_INTEGRITY_CSUM_NONE:
		if (bi->pi_tuple_size) {
			pr_warn("pi_tuple_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_tuple_size != sizeof(struct t10_pi_tuple)) {
			pr_warn("pi_tuple_size mismatch for T10 PI: expected \
				 %zu, got %u\n",
				 sizeof(struct t10_pi_tuple),
				 bi->pi_tuple_size);
			return -EINVAL;
		}
		break;
	case BLK_INTEGRITY_CSUM_CRC64:
		if (bi->pi_tuple_size != sizeof(struct crc64_pi_tuple)) {
			pr_warn("pi_tuple_size mismatch for CRC64 PI: \
				 expected %zu, got %u\n",
				 sizeof(struct crc64_pi_tuple),
				 bi->pi_tuple_size);
			return -EINVAL;
		}
		break;
	}

	if (!bi->interval_exp)
		bi->interval_exp = ilog2(lim->logical_block_size);

@@ -875,7 +913,7 @@ bool queue_limits_stack_integrity(struct queue_limits *t,
		return true;

	if (ti->flags & BLK_INTEGRITY_STACKED) {
		if (ti->tuple_size != bi->tuple_size)
		if (ti->metadata_size != bi->metadata_size)
			goto incompatible;
		if (ti->interval_exp != bi->interval_exp)
			goto incompatible;
@@ -891,7 +929,7 @@ bool queue_limits_stack_integrity(struct queue_limits *t,
		ti->flags |= (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE) |
			     (bi->flags & BLK_INTEGRITY_REF_TAG);
		ti->csum_type = bi->csum_type;
		ti->tuple_size = bi->tuple_size;
		ti->metadata_size = bi->metadata_size;
		ti->pi_offset = bi->pi_offset;
		ti->interval_exp = bi->interval_exp;
		ti->tag_size = bi->tag_size;
+4 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/uaccess.h>
#include <linux/pagemap.h>
#include <linux/io_uring/cmd.h>
#include <linux/blk-integrity.h>
#include <uapi/linux/blkdev.h>
#include "blk.h"
#include "blk-crypto-internal.h"
@@ -566,6 +567,9 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
{
	unsigned int max_sectors;

	if (_IOC_NR(cmd) == _IOC_NR(FS_IOC_GETLBMD_CAP))
		return blk_get_meta_cap(bdev, cmd, argp);

	switch (cmd) {
	case BLKFLSBUF:
		return blkdev_flushbuf(bdev, cmd, arg);
+8 −8
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ static void t10_pi_generate(struct blk_integrity_iter *iter,
			pi->ref_tag = 0;

		iter->data_buf += iter->interval;
		iter->prot_buf += bi->tuple_size;
		iter->prot_buf += bi->metadata_size;
		iter->seed++;
	}
}
@@ -105,7 +105,7 @@ static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,

next:
		iter->data_buf += iter->interval;
		iter->prot_buf += bi->tuple_size;
		iter->prot_buf += bi->metadata_size;
		iter->seed++;
	}

@@ -125,7 +125,7 @@ static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,
static void t10_pi_type1_prepare(struct request *rq)
{
	struct blk_integrity *bi = &rq->q->limits.integrity;
	const int tuple_sz = bi->tuple_size;
	const int tuple_sz = bi->metadata_size;
	u32 ref_tag = t10_pi_ref_tag(rq);
	u8 offset = bi->pi_offset;
	struct bio *bio;
@@ -177,7 +177,7 @@ static void t10_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
{
	struct blk_integrity *bi = &rq->q->limits.integrity;
	unsigned intervals = nr_bytes >> bi->interval_exp;
	const int tuple_sz = bi->tuple_size;
	const int tuple_sz = bi->metadata_size;
	u32 ref_tag = t10_pi_ref_tag(rq);
	u8 offset = bi->pi_offset;
	struct bio *bio;
@@ -234,7 +234,7 @@ static void ext_pi_crc64_generate(struct blk_integrity_iter *iter,
			put_unaligned_be48(0ULL, pi->ref_tag);

		iter->data_buf += iter->interval;
		iter->prot_buf += bi->tuple_size;
		iter->prot_buf += bi->metadata_size;
		iter->seed++;
	}
}
@@ -289,7 +289,7 @@ static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,

next:
		iter->data_buf += iter->interval;
		iter->prot_buf += bi->tuple_size;
		iter->prot_buf += bi->metadata_size;
		iter->seed++;
	}

@@ -299,7 +299,7 @@ static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
static void ext_pi_type1_prepare(struct request *rq)
{
	struct blk_integrity *bi = &rq->q->limits.integrity;
	const int tuple_sz = bi->tuple_size;
	const int tuple_sz = bi->metadata_size;
	u64 ref_tag = ext_pi_ref_tag(rq);
	u8 offset = bi->pi_offset;
	struct bio *bio;
@@ -340,7 +340,7 @@ static void ext_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
{
	struct blk_integrity *bi = &rq->q->limits.integrity;
	unsigned intervals = nr_bytes >> bi->interval_exp;
	const int tuple_sz = bi->tuple_size;
	const int tuple_sz = bi->metadata_size;
	u64 ref_tag = ext_pi_ref_tag(rq);
	u8 offset = bi->pi_offset;
	struct bio *bio;
Loading