Skip to content

Commit cec40a7

Browse files
committed
Merge tag 'vfs-6.17-rc1.integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs 'protection info' updates from Christian Brauner: "This adds the new FS_IOC_GETLBMD_CAP ioctl() to query metadata and protection info (PI) capabilities. This ioctl returns information about the files integrity profile. This is useful for userspace applications to understand a files end-to-end data protection support and configure the I/O accordingly. For now this interface is only supported by block devices. However the design and placement of this ioctl in generic FS ioctl space allows us to extend it to work over files as well. This maybe useful when filesystems start supporting PI-aware layouts. A new structure struct logical_block_metadata_cap is introduced, which contains the following fields: - lbmd_flags: bitmask of logical block metadata capability flags - lbmd_interval: the amount of data described by each unit of logical block metadata - lbmd_size: size in bytes of the logical block metadata associated with each interval - lbmd_opaque_size: size in bytes of the opaque block tag associated with each interval - lbmd_opaque_offset: offset in bytes of the opaque block tag within the logical block metadata - lbmd_pi_size: size in bytes of the T10 PI tuple associated with each interval - lbmd_pi_offset: offset in bytes of T10 PI tuple within the logical block metadata - lbmd_pi_guard_tag_type: T10 PI guard tag type - lbmd_pi_app_tag_size: size in bytes of the T10 PI application tag - lbmd_pi_ref_tag_size: size in bytes of the T10 PI reference tag - lbmd_pi_storage_tag_size: size in bytes of the T10 PI storage tag The internal logic to fetch the capability is encapsulated in a helper function blk_get_meta_cap(), which uses the blk_integrity profile associated with the device. The ioctl returns -EOPNOTSUPP, if CONFIG_BLK_DEV_INTEGRITY is not enabled" * tag 'vfs-6.17-rc1.integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: block: fix lbmd_guard_tag_type assignment in FS_IOC_GETLBMD_CAP block: fix FS_IOC_GETLBMD_CAP parsing in blkdev_common_ioctl() 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
2 parents add0751 + bc5b0c8 commit cec40a7

File tree

14 files changed

+209
-31
lines changed

14 files changed

+209
-31
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: 69 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,73 @@ 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 (_IOC_DIR(cmd) != _IOC_DIR(FS_IOC_GETLBMD_CAP) ||
66+
_IOC_TYPE(cmd) != _IOC_TYPE(FS_IOC_GETLBMD_CAP) ||
67+
_IOC_NR(cmd) != _IOC_NR(FS_IOC_GETLBMD_CAP) ||
68+
_IOC_SIZE(cmd) < LBMD_SIZE_VER0)
69+
return -ENOIOCTLCMD;
70+
71+
if (!bi)
72+
goto out;
73+
74+
if (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE)
75+
meta_cap.lbmd_flags |= LBMD_PI_CAP_INTEGRITY;
76+
if (bi->flags & BLK_INTEGRITY_REF_TAG)
77+
meta_cap.lbmd_flags |= LBMD_PI_CAP_REFTAG;
78+
meta_cap.lbmd_interval = 1 << bi->interval_exp;
79+
meta_cap.lbmd_size = bi->metadata_size;
80+
meta_cap.lbmd_pi_size = bi->pi_tuple_size;
81+
meta_cap.lbmd_pi_offset = bi->pi_offset;
82+
meta_cap.lbmd_opaque_size = bi->metadata_size - bi->pi_tuple_size;
83+
if (meta_cap.lbmd_opaque_size && !bi->pi_offset)
84+
meta_cap.lbmd_opaque_offset = bi->pi_tuple_size;
85+
86+
switch (bi->csum_type) {
87+
case BLK_INTEGRITY_CSUM_NONE:
88+
meta_cap.lbmd_guard_tag_type = LBMD_PI_CSUM_NONE;
89+
break;
90+
case BLK_INTEGRITY_CSUM_IP:
91+
meta_cap.lbmd_guard_tag_type = LBMD_PI_CSUM_IP;
92+
break;
93+
case BLK_INTEGRITY_CSUM_CRC:
94+
meta_cap.lbmd_guard_tag_type = LBMD_PI_CSUM_CRC16_T10DIF;
95+
break;
96+
case BLK_INTEGRITY_CSUM_CRC64:
97+
meta_cap.lbmd_guard_tag_type = LBMD_PI_CSUM_CRC64_NVME;
98+
break;
99+
}
100+
101+
if (bi->csum_type != BLK_INTEGRITY_CSUM_NONE)
102+
meta_cap.lbmd_app_tag_size = 2;
103+
104+
if (bi->flags & BLK_INTEGRITY_REF_TAG) {
105+
switch (bi->csum_type) {
106+
case BLK_INTEGRITY_CSUM_CRC64:
107+
meta_cap.lbmd_ref_tag_size =
108+
sizeof_field(struct crc64_pi_tuple, ref_tag);
109+
break;
110+
case BLK_INTEGRITY_CSUM_CRC:
111+
case BLK_INTEGRITY_CSUM_IP:
112+
meta_cap.lbmd_ref_tag_size =
113+
sizeof_field(struct t10_pi_tuple, ref_tag);
114+
break;
115+
default:
116+
break;
117+
}
118+
}
119+
120+
out:
121+
return copy_struct_to_user(argp, usize, &meta_cap, sizeof(meta_cap),
122+
NULL);
123+
}
124+
57125
/**
58126
* blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
59127
* @rq: request to map
@@ -239,7 +307,7 @@ static ssize_t format_show(struct device *dev, struct device_attribute *attr,
239307
{
240308
struct blk_integrity *bi = dev_to_bi(dev);
241309

242-
if (!bi->tuple_size)
310+
if (!bi->metadata_size)
243311
return sysfs_emit(page, "none\n");
244312
return sysfs_emit(page, "%s\n", blk_integrity_profile_name(bi));
245313
}

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"
@@ -116,7 +118,7 @@ static int blk_validate_integrity_limits(struct queue_limits *lim)
116118
{
117119
struct blk_integrity *bi = &lim->integrity;
118120

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

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

@@ -891,7 +929,7 @@ bool queue_limits_stack_integrity(struct queue_limits *t,
891929
return true;
892930

893931
if (ti->flags & BLK_INTEGRITY_STACKED) {
894-
if (ti->tuple_size != bi->tuple_size)
932+
if (ti->metadata_size != bi->metadata_size)
895933
goto incompatible;
896934
if (ti->interval_exp != bi->interval_exp)
897935
goto incompatible;
@@ -907,7 +945,7 @@ bool queue_limits_stack_integrity(struct queue_limits *t,
907945
ti->flags |= (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE) |
908946
(bi->flags & BLK_INTEGRITY_REF_TAG);
909947
ti->csum_type = bi->csum_type;
910-
ti->tuple_size = bi->tuple_size;
948+
ti->metadata_size = bi->metadata_size;
911949
ti->pi_offset = bi->pi_offset;
912950
ti->interval_exp = bi->interval_exp;
913951
ti->tag_size = bi->tag_size;

block/ioctl.c

Lines changed: 2 additions & 1 deletion
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"
@@ -644,7 +645,7 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
644645
case IOC_PR_CLEAR:
645646
return blkdev_pr_clear(bdev, mode, argp);
646647
default:
647-
return -ENOIOCTLCMD;
648+
return blk_get_meta_cap(bdev, cmd, argp);
648649
}
649650
}
650651

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
@@ -1192,11 +1192,11 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
11921192
return -EINVAL;
11931193
}
11941194

1195-
if (bi->tuple_size < cc->used_tag_size) {
1195+
if (bi->metadata_size < cc->used_tag_size) {
11961196
ti->error = "Integrity profile tag size mismatch.";
11971197
return -EINVAL;
11981198
}
1199-
cc->tuple_size = bi->tuple_size;
1199+
cc->tuple_size = bi->metadata_size;
12001200
if (1 << bi->interval_exp != cc->sector_size) {
12011201
ti->error = "Integrity profile sector size mismatch.";
12021202
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
@@ -1870,8 +1870,11 @@ static bool nvme_init_integrity(struct nvme_ns_head *head,
18701870
break;
18711871
}
18721872

1873-
bi->tuple_size = head->ms;
1874-
bi->pi_offset = info->pi_offset;
1873+
bi->metadata_size = head->ms;
1874+
if (bi->csum_type) {
1875+
bi->pi_tuple_size = head->pi_size;
1876+
bi->pi_offset = info->pi_offset;
1877+
}
18751878
return true;
18761879
}
18771880

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

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

7171
if (bi->csum_type == BLK_INTEGRITY_CSUM_CRC) {
72-
ns->metadata_size = bi->tuple_size;
72+
ns->metadata_size = bi->metadata_size;
7373
if (bi->flags & BLK_INTEGRITY_REF_TAG)
7474
ns->pi_type = NVME_NS_DPS_PI_TYPE1;
7575
else

0 commit comments

Comments
 (0)