]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests: ublk: add kublk support for integrity params
authorCaleb Sander Mateos <csander@purestorage.com>
Thu, 8 Jan 2026 09:19:42 +0000 (02:19 -0700)
committerJens Axboe <axboe@kernel.dk>
Mon, 12 Jan 2026 16:16:38 +0000 (09:16 -0700)
Add integrity param command line arguments to kublk. Plumb these to
struct ublk_params for the null and fault_inject targets, as they don't
need to actually read or write the integrity data. Forbid the integrity
params for loop or stripe until the integrity data copy is implemented.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
tools/testing/selftests/ublk/fault_inject.c
tools/testing/selftests/ublk/file_backed.c
tools/testing/selftests/ublk/kublk.c
tools/testing/selftests/ublk/kublk.h
tools/testing/selftests/ublk/null.c
tools/testing/selftests/ublk/stripe.c

index b227bd78b25281f27a6f9bcbbc6260df13cdba78..3b897f69c014cc73b4b469d816e80284dd21b577 100644 (file)
@@ -33,6 +33,7 @@ static int ublk_fault_inject_tgt_init(const struct dev_ctx *ctx,
                        .dev_sectors            = dev_size >> 9,
                },
        };
+       ublk_set_integrity_params(ctx, &dev->tgt.params);
 
        dev->private_data = (void *)(unsigned long)(ctx->fault_inject.delay_us * 1000);
        return 0;
index 269d5f124e06a0387b522404d54a501be90f1529..c14ce6608696de5012ed38cb88c572c72437aa55 100644 (file)
@@ -158,6 +158,10 @@ static int ublk_loop_tgt_init(const struct dev_ctx *ctx, struct ublk_dev *dev)
                ublk_err("%s: not support auto_zc_fallback\n", __func__);
                return -EINVAL;
        }
+       if (ctx->metadata_size) {
+               ublk_err("%s: integrity not supported\n", __func__);
+               return -EINVAL;
+       }
 
        ret = backing_file_tgt_init(dev);
        if (ret)
index 261095f19c93aa8a08d84d5be2c4202e64f0920e..48e1865b4875b670b94b7a6ee101e03b5975c75b 100644 (file)
@@ -3,6 +3,7 @@
  * Description: uring_cmd based ublk
  */
 
+#include <linux/fs.h>
 #include "kublk.h"
 
 #define MAX_NR_TGT_ARG         64
@@ -1550,6 +1551,8 @@ static void __cmd_create_help(char *exe, bool recovery)
        printf("\t[--foreground] [--quiet] [-z] [--auto_zc] [--auto_zc_fallback] [--debug_mask mask] [-r 0|1] [-g] [-u]\n");
        printf("\t[-e 0|1 ] [-i 0|1] [--no_ublk_fixed_fd]\n");
        printf("\t[--nthreads threads] [--per_io_tasks]\n");
+       printf("\t[--integrity_capable] [--integrity_reftag] [--metadata_size SIZE] "
+                "[--pi_offset OFFSET] [--csum_type ip|t10dif|nvme] [--tag_size SIZE]\n");
        printf("\t[target options] [backfile1] [backfile2] ...\n");
        printf("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n");
        printf("\tdefault: nthreads=nr_queues");
@@ -1613,6 +1616,12 @@ int main(int argc, char *argv[])
                { "nthreads",           1,      NULL,  0 },
                { "per_io_tasks",       0,      NULL,  0 },
                { "no_ublk_fixed_fd",   0,      NULL,  0 },
+               { "integrity_capable",  0,      NULL,  0 },
+               { "integrity_reftag",   0,      NULL,  0 },
+               { "metadata_size",      1,      NULL,  0 },
+               { "pi_offset",          1,      NULL,  0 },
+               { "csum_type",          1,      NULL,  0 },
+               { "tag_size",           1,      NULL,  0 },
                { 0, 0, 0, 0 }
        };
        const struct ublk_tgt_ops *ops = NULL;
@@ -1623,6 +1632,7 @@ int main(int argc, char *argv[])
                .nr_hw_queues   =       2,
                .dev_id         =       -1,
                .tgt_type       =       "unknown",
+               .csum_type      =       LBMD_PI_CSUM_NONE,
        };
        int ret = -EINVAL, i;
        int tgt_argc = 1;
@@ -1697,6 +1707,28 @@ int main(int argc, char *argv[])
                                ctx.per_io_tasks = 1;
                        if (!strcmp(longopts[option_idx].name, "no_ublk_fixed_fd"))
                                ctx.no_ublk_fixed_fd = 1;
+                       if (!strcmp(longopts[option_idx].name, "integrity_capable"))
+                               ctx.integrity_flags |= LBMD_PI_CAP_INTEGRITY;
+                       if (!strcmp(longopts[option_idx].name, "integrity_reftag"))
+                               ctx.integrity_flags |= LBMD_PI_CAP_REFTAG;
+                       if (!strcmp(longopts[option_idx].name, "metadata_size"))
+                               ctx.metadata_size = strtoul(optarg, NULL, 0);
+                       if (!strcmp(longopts[option_idx].name, "pi_offset"))
+                               ctx.pi_offset = strtoul(optarg, NULL, 0);
+                       if (!strcmp(longopts[option_idx].name, "csum_type")) {
+                               if (!strcmp(optarg, "ip")) {
+                                       ctx.csum_type = LBMD_PI_CSUM_IP;
+                               } else if (!strcmp(optarg, "t10dif")) {
+                                       ctx.csum_type = LBMD_PI_CSUM_CRC16_T10DIF;
+                               } else if (!strcmp(optarg, "nvme")) {
+                                       ctx.csum_type = LBMD_PI_CSUM_CRC64_NVME;
+                               } else {
+                                       ublk_err("invalid csum_type: %s\n", optarg);
+                                       return -EINVAL;
+                               }
+                       }
+                       if (!strcmp(longopts[option_idx].name, "tag_size"))
+                               ctx.tag_size = strtoul(optarg, NULL, 0);
                        break;
                case '?':
                        /*
@@ -1739,6 +1771,21 @@ int main(int argc, char *argv[])
                return -EINVAL;
        }
 
+       if (ctx.metadata_size) {
+               if (!(ctx.flags & UBLK_F_USER_COPY)) {
+                       ublk_err("integrity requires user_copy\n");
+                       return -EINVAL;
+               }
+
+               ctx.flags |= UBLK_F_INTEGRITY;
+       } else if (ctx.integrity_flags ||
+                  ctx.pi_offset ||
+                  ctx.csum_type != LBMD_PI_CSUM_NONE ||
+                  ctx.tag_size) {
+               ublk_err("integrity parameters require metadata_size\n");
+               return -EINVAL;
+       }
+
        i = optind;
        while (i < argc && ctx.nr_files < MAX_BACK_FILES) {
                ctx.files[ctx.nr_files++] = argv[i++];
index 8a83b90ec603ad00735a9393143b588a17a5c12f..d00f2b465cdfb2d0b2b664b7117b65838022d497 100644 (file)
@@ -78,6 +78,11 @@ struct dev_ctx {
        unsigned int    auto_zc_fallback:1;
        unsigned int    per_io_tasks:1;
        unsigned int    no_ublk_fixed_fd:1;
+       __u32 integrity_flags;
+       __u8 metadata_size;
+       __u8 pi_offset;
+       __u8 csum_type;
+       __u8 tag_size;
 
        int _evtfd;
        int _shmid;
@@ -202,6 +207,22 @@ struct ublk_dev {
 
 extern int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io);
 
+static inline void ublk_set_integrity_params(const struct dev_ctx *ctx,
+                                            struct ublk_params *params)
+{
+       if (!ctx->metadata_size)
+               return;
+
+       params->types |= UBLK_PARAM_TYPE_INTEGRITY;
+       params->integrity = (struct ublk_param_integrity) {
+               .flags = ctx->integrity_flags,
+               .interval_exp = params->basic.logical_bs_shift,
+               .metadata_size = ctx->metadata_size,
+               .pi_offset = ctx->pi_offset,
+               .csum_type = ctx->csum_type,
+               .tag_size = ctx->tag_size,
+       };
+}
 
 static inline int ublk_io_auto_zc_fallback(const struct ublksrv_io_desc *iod)
 {
index 280043f6b6896aa8c1fd106a2b4e97dd13efdc89..3aa162f08476faecbcfe7751e5215edfa43b4052 100644 (file)
@@ -36,6 +36,7 @@ static int ublk_null_tgt_init(const struct dev_ctx *ctx, struct ublk_dev *dev)
                        .max_segments           = 32,
                },
        };
+       ublk_set_integrity_params(ctx, &dev->tgt.params);
 
        if (info->flags & UBLK_F_SUPPORT_ZERO_COPY)
                dev->tgt.sq_depth = dev->tgt.cq_depth = 2 * info->queue_depth;
index fd412e1f01c0ee398343392662b78a8f9d4c65a2..d4aaf3351d7126ee2c7e32092e204e4b0a156acf 100644 (file)
@@ -298,6 +298,10 @@ static int ublk_stripe_tgt_init(const struct dev_ctx *ctx, struct ublk_dev *dev)
                ublk_err("%s: not support auto_zc_fallback\n", __func__);
                return -EINVAL;
        }
+       if (ctx->metadata_size) {
+               ublk_err("%s: integrity not supported\n", __func__);
+               return -EINVAL;
+       }
 
        if ((chunk_size & (chunk_size - 1)) || !chunk_size) {
                ublk_err("invalid chunk size %u\n", chunk_size);