Skip to content

Commit 4a3def7

Browse files
committed
Merge patch series "add ioctl to query metadata and protection info capabilities"
Anuj Gupta <[email protected]> says: This patch series adds a new ioctl to query metadata and integrity capability. * patches from https://lore.kernel.org/[email protected]: 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/[email protected] Signed-off-by: Christian Brauner <[email protected]>
2 parents 19272b3 + 9eb22f7 commit 4a3def7

File tree

14 files changed

+195
-30
lines changed

14 files changed

+195
-30
lines changed

block/bio-integrity-auto.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ static bool bi_offload_capable(struct blk_integrity *bi)
5454
{
5555
switch (bi->csum_type) {
5656
case BLK_INTEGRITY_CSUM_CRC64:
57-
return bi->tuple_size == sizeof(struct crc64_pi_tuple);
57+
return bi->metadata_size == sizeof(struct crc64_pi_tuple);
5858
case BLK_INTEGRITY_CSUM_CRC:
5959
case BLK_INTEGRITY_CSUM_IP:
60-
return bi->tuple_size == sizeof(struct t10_pi_tuple);
60+
return bi->metadata_size == sizeof(struct t10_pi_tuple);
6161
default:
6262
pr_warn_once("%s: unknown integrity checksum type:%d\n",
6363
__func__, bi->csum_type);

block/blk-integrity.c

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/scatterlist.h>
1414
#include <linux/export.h>
1515
#include <linux/slab.h>
16+
#include <linux/t10-pi.h>
1617

1718
#include "blk.h"
1819

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

58+
int blk_get_meta_cap(struct block_device *bdev, unsigned int cmd,
59+
struct logical_block_metadata_cap __user *argp)
60+
{
61+
struct blk_integrity *bi = blk_get_integrity(bdev->bd_disk);
62+
struct logical_block_metadata_cap meta_cap = {};
63+
size_t usize = _IOC_SIZE(cmd);
64+
65+
if (!argp)
66+
return -EINVAL;
67+
if (usize < LBMD_SIZE_VER0)
68+
return -EINVAL;
69+
if (!bi)
70+
goto out;
71+
72+
if (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE)
73+
meta_cap.lbmd_flags |= LBMD_PI_CAP_INTEGRITY;
74+
if (bi->flags & BLK_INTEGRITY_REF_TAG)
75+
meta_cap.lbmd_flags |= LBMD_PI_CAP_REFTAG;
76+
meta_cap.lbmd_interval = 1 << bi->interval_exp;
77+
meta_cap.lbmd_size = bi->metadata_size;
78+
meta_cap.lbmd_pi_size = bi->pi_tuple_size;
79+
meta_cap.lbmd_pi_offset = bi->pi_offset;
80+
meta_cap.lbmd_opaque_size = bi->metadata_size - bi->pi_tuple_size;
81+
if (meta_cap.lbmd_opaque_size && !bi->pi_offset)
82+
meta_cap.lbmd_opaque_offset = bi->pi_tuple_size;
83+
84+
meta_cap.lbmd_guard_tag_type = bi->csum_type;
85+
if (bi->csum_type != BLK_INTEGRITY_CSUM_NONE)
86+
meta_cap.lbmd_app_tag_size = 2;
87+
88+
if (bi->flags & BLK_INTEGRITY_REF_TAG) {
89+
switch (bi->csum_type) {
90+
case BLK_INTEGRITY_CSUM_CRC64:
91+
meta_cap.lbmd_ref_tag_size =
92+
sizeof_field(struct crc64_pi_tuple, ref_tag);
93+
break;
94+
case BLK_INTEGRITY_CSUM_CRC:
95+
case BLK_INTEGRITY_CSUM_IP:
96+
meta_cap.lbmd_ref_tag_size =
97+
sizeof_field(struct t10_pi_tuple, ref_tag);
98+
break;
99+
default:
100+
break;
101+
}
102+
}
103+
104+
out:
105+
return copy_struct_to_user(argp, usize, &meta_cap, sizeof(meta_cap),
106+
NULL);
107+
}
108+
57109
/**
58110
* blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
59111
* @rq: request to map
@@ -239,7 +291,7 @@ static ssize_t format_show(struct device *dev, struct device_attribute *attr,
239291
{
240292
struct blk_integrity *bi = dev_to_bi(dev);
241293

242-
if (!bi->tuple_size)
294+
if (!bi->metadata_size)
243295
return sysfs_emit(page, "none\n");
244296
return sysfs_emit(page, "%s\n", blk_integrity_profile_name(bi));
245297
}

block/blk-settings.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <linux/jiffies.h>
1515
#include <linux/gfp.h>
1616
#include <linux/dma-mapping.h>
17+
#include <linux/t10-pi.h>
18+
#include <linux/crc64.h>
1719

1820
#include "blk.h"
1921
#include "blk-rq-qos.h"
@@ -114,7 +116,7 @@ static int blk_validate_integrity_limits(struct queue_limits *lim)
114116
{
115117
struct blk_integrity *bi = &lim->integrity;
116118

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

140+
if (bi->pi_tuple_size > bi->metadata_size) {
141+
pr_warn("pi_tuple_size (%u) exceeds metadata_size (%u)\n",
142+
bi->pi_tuple_size,
143+
bi->metadata_size);
144+
return -EINVAL;
145+
}
146+
147+
switch (bi->csum_type) {
148+
case BLK_INTEGRITY_CSUM_NONE:
149+
if (bi->pi_tuple_size) {
150+
pr_warn("pi_tuple_size must be 0 when checksum type \
151+
is none\n");
152+
return -EINVAL;
153+
}
154+
break;
155+
case BLK_INTEGRITY_CSUM_CRC:
156+
case BLK_INTEGRITY_CSUM_IP:
157+
if (bi->pi_tuple_size != sizeof(struct t10_pi_tuple)) {
158+
pr_warn("pi_tuple_size mismatch for T10 PI: expected \
159+
%zu, got %u\n",
160+
sizeof(struct t10_pi_tuple),
161+
bi->pi_tuple_size);
162+
return -EINVAL;
163+
}
164+
break;
165+
case BLK_INTEGRITY_CSUM_CRC64:
166+
if (bi->pi_tuple_size != sizeof(struct crc64_pi_tuple)) {
167+
pr_warn("pi_tuple_size mismatch for CRC64 PI: \
168+
expected %zu, got %u\n",
169+
sizeof(struct crc64_pi_tuple),
170+
bi->pi_tuple_size);
171+
return -EINVAL;
172+
}
173+
break;
174+
}
175+
138176
if (!bi->interval_exp)
139177
bi->interval_exp = ilog2(lim->logical_block_size);
140178

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

877915
if (ti->flags & BLK_INTEGRITY_STACKED) {
878-
if (ti->tuple_size != bi->tuple_size)
916+
if (ti->metadata_size != bi->metadata_size)
879917
goto incompatible;
880918
if (ti->interval_exp != bi->interval_exp)
881919
goto incompatible;
@@ -891,7 +929,7 @@ bool queue_limits_stack_integrity(struct queue_limits *t,
891929
ti->flags |= (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE) |
892930
(bi->flags & BLK_INTEGRITY_REF_TAG);
893931
ti->csum_type = bi->csum_type;
894-
ti->tuple_size = bi->tuple_size;
932+
ti->metadata_size = bi->metadata_size;
895933
ti->pi_offset = bi->pi_offset;
896934
ti->interval_exp = bi->interval_exp;
897935
ti->tag_size = bi->tag_size;

block/ioctl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/uaccess.h>
1414
#include <linux/pagemap.h>
1515
#include <linux/io_uring/cmd.h>
16+
#include <linux/blk-integrity.h>
1617
#include <uapi/linux/blkdev.h>
1718
#include "blk.h"
1819
#include "blk-crypto-internal.h"
@@ -566,6 +567,9 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
566567
{
567568
unsigned int max_sectors;
568569

570+
if (_IOC_NR(cmd) == _IOC_NR(FS_IOC_GETLBMD_CAP))
571+
return blk_get_meta_cap(bdev, cmd, argp);
572+
569573
switch (cmd) {
570574
case BLKFLSBUF:
571575
return blkdev_flushbuf(bdev, cmd, arg);

block/t10-pi.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static void t10_pi_generate(struct blk_integrity_iter *iter,
5656
pi->ref_tag = 0;
5757

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

106106
next:
107107
iter->data_buf += iter->interval;
108-
iter->prot_buf += bi->tuple_size;
108+
iter->prot_buf += bi->metadata_size;
109109
iter->seed++;
110110
}
111111

@@ -125,7 +125,7 @@ static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,
125125
static void t10_pi_type1_prepare(struct request *rq)
126126
{
127127
struct blk_integrity *bi = &rq->q->limits.integrity;
128-
const int tuple_sz = bi->tuple_size;
128+
const int tuple_sz = bi->metadata_size;
129129
u32 ref_tag = t10_pi_ref_tag(rq);
130130
u8 offset = bi->pi_offset;
131131
struct bio *bio;
@@ -177,7 +177,7 @@ static void t10_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
177177
{
178178
struct blk_integrity *bi = &rq->q->limits.integrity;
179179
unsigned intervals = nr_bytes >> bi->interval_exp;
180-
const int tuple_sz = bi->tuple_size;
180+
const int tuple_sz = bi->metadata_size;
181181
u32 ref_tag = t10_pi_ref_tag(rq);
182182
u8 offset = bi->pi_offset;
183183
struct bio *bio;
@@ -234,7 +234,7 @@ static void ext_pi_crc64_generate(struct blk_integrity_iter *iter,
234234
put_unaligned_be48(0ULL, pi->ref_tag);
235235

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

290290
next:
291291
iter->data_buf += iter->interval;
292-
iter->prot_buf += bi->tuple_size;
292+
iter->prot_buf += bi->metadata_size;
293293
iter->seed++;
294294
}
295295

@@ -299,7 +299,7 @@ static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
299299
static void ext_pi_type1_prepare(struct request *rq)
300300
{
301301
struct blk_integrity *bi = &rq->q->limits.integrity;
302-
const int tuple_sz = bi->tuple_size;
302+
const int tuple_sz = bi->metadata_size;
303303
u64 ref_tag = ext_pi_ref_tag(rq);
304304
u8 offset = bi->pi_offset;
305305
struct bio *bio;
@@ -340,7 +340,7 @@ static void ext_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
340340
{
341341
struct blk_integrity *bi = &rq->q->limits.integrity;
342342
unsigned intervals = nr_bytes >> bi->interval_exp;
343-
const int tuple_sz = bi->tuple_size;
343+
const int tuple_sz = bi->metadata_size;
344344
u64 ref_tag = ext_pi_ref_tag(rq);
345345
u8 offset = bi->pi_offset;
346346
struct bio *bio;

drivers/md/dm-crypt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,11 +1189,11 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
11891189
return -EINVAL;
11901190
}
11911191

1192-
if (bi->tuple_size < cc->used_tag_size) {
1192+
if (bi->metadata_size < cc->used_tag_size) {
11931193
ti->error = "Integrity profile tag size mismatch.";
11941194
return -EINVAL;
11951195
}
1196-
cc->tuple_size = bi->tuple_size;
1196+
cc->tuple_size = bi->metadata_size;
11971197
if (1 << bi->interval_exp != cc->sector_size) {
11981198
ti->error = "Integrity profile sector size mismatch.";
11991199
return -EINVAL;

drivers/md/dm-integrity.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3906,8 +3906,8 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *lim
39063906
struct blk_integrity *bi = &limits->integrity;
39073907

39083908
memset(bi, 0, sizeof(*bi));
3909-
bi->tuple_size = ic->tag_size;
3910-
bi->tag_size = bi->tuple_size;
3909+
bi->metadata_size = ic->tag_size;
3910+
bi->tag_size = bi->metadata_size;
39113911
bi->interval_exp =
39123912
ic->sb->log2_sectors_per_block + SECTOR_SHIFT;
39133913
}
@@ -4746,18 +4746,18 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv
47464746
ti->error = "Integrity profile not supported";
47474747
goto bad;
47484748
}
4749-
/*printk("tag_size: %u, tuple_size: %u\n", bi->tag_size, bi->tuple_size);*/
4750-
if (bi->tuple_size < ic->tag_size) {
4749+
/*printk("tag_size: %u, metadata_size: %u\n", bi->tag_size, bi->metadata_size);*/
4750+
if (bi->metadata_size < ic->tag_size) {
47514751
r = -EINVAL;
47524752
ti->error = "The integrity profile is smaller than tag size";
47534753
goto bad;
47544754
}
4755-
if ((unsigned long)bi->tuple_size > PAGE_SIZE / 2) {
4755+
if ((unsigned long)bi->metadata_size > PAGE_SIZE / 2) {
47564756
r = -EINVAL;
47574757
ti->error = "Too big tuple size";
47584758
goto bad;
47594759
}
4760-
ic->tuple_size = bi->tuple_size;
4760+
ic->tuple_size = bi->metadata_size;
47614761
if (1 << bi->interval_exp != ic->sectors_per_block << SECTOR_SHIFT) {
47624762
r = -EINVAL;
47634763
ti->error = "Integrity profile sector size mismatch";

drivers/nvdimm/btt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1506,7 +1506,7 @@ static int btt_blk_init(struct btt *btt)
15061506
int rc;
15071507

15081508
if (btt_meta_size(btt) && IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) {
1509-
lim.integrity.tuple_size = btt_meta_size(btt);
1509+
lim.integrity.metadata_size = btt_meta_size(btt);
15101510
lim.integrity.tag_size = btt_meta_size(btt);
15111511
}
15121512

drivers/nvme/host/core.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,8 +1866,11 @@ static bool nvme_init_integrity(struct nvme_ns_head *head,
18661866
break;
18671867
}
18681868

1869-
bi->tuple_size = head->ms;
1870-
bi->pi_offset = info->pi_offset;
1869+
bi->metadata_size = head->ms;
1870+
if (bi->csum_type) {
1871+
bi->pi_tuple_size = head->pi_size;
1872+
bi->pi_offset = info->pi_offset;
1873+
}
18711874
return true;
18721875
}
18731876

drivers/nvme/target/io-cmd-bdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static void nvmet_bdev_ns_enable_integrity(struct nvmet_ns *ns)
6565
return;
6666

6767
if (bi->csum_type == BLK_INTEGRITY_CSUM_CRC) {
68-
ns->metadata_size = bi->tuple_size;
68+
ns->metadata_size = bi->metadata_size;
6969
if (bi->flags & BLK_INTEGRITY_REF_TAG)
7070
ns->pi_type = NVME_NS_DPS_PI_TYPE1;
7171
else

0 commit comments

Comments
 (0)