diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
index be5a0d775952..2400b4615766 100644
--- a/tools/testing/selftests/ublk/kublk.c
+++ b/tools/testing/selftests/ublk/kublk.c
@@ -8,6 +8,13 @@
#include "kublk.h"
#define MAX_NR_TGT_ARG 64
+#define KUBLK_PARAM_LOGICAL_BS_SHIFT 9
+#define KUBLK_PARAM_PHYSICAL_BS_SHIFT 12
+#define KUBLK_PARAM_ZONE_SECTORS 128
+#define KUBLK_PARAM_NR_ZONES 16
+#define KUBLK_PARAM_DEV_SECTORS \
+ (KUBLK_PARAM_ZONE_SECTORS * KUBLK_PARAM_NR_ZONES)
+#define KUBLK_PARAM_ZONE_APPEND_SECTORS 8
unsigned int ublk_dbg_mask = UBLK_LOG;
static const struct ublk_tgt_ops *tgt_ops_list[] = {@@ -227,6 +234,55 @@ static int ublk_ctrl_get_features(struct ublk_dev *dev,
return __ublk_ctrl_cmd(dev, &data);
}
+static int parse_param_types(const char *arg, __u32 *types)
+{
+ char buf[128], *save = NULL, *tok;
+
+ if (strlen(arg) >= sizeof(buf))
+ return -EINVAL;
+
+ strcpy(buf, arg);
+ *types = 0;
+ tok = strtok_r(buf, ",", &save);
+ while (tok) {
+ if (!strcmp(tok, "none"))
+ ;
+ else if (!strcmp(tok, "basic"))
+ *types |= UBLK_PARAM_TYPE_BASIC;
+ else if (!strcmp(tok, "zoned"))
+ *types |= UBLK_PARAM_TYPE_ZONED;
+ else
+ return -EINVAL;
+ tok = strtok_r(NULL, ",", &save);
+ }
+
+ return 0;
+}
+
+static void ublk_init_params_from_ctx(const struct dev_ctx *ctx,
+ struct ublk_params *params)
+{
+ const struct params_ctx *p = &ctx->params;
+
+ *params = (struct ublk_params) {
+ .types = p->types,
+ .basic = {
+ .logical_bs_shift = p->logical_bs_shift,
+ .physical_bs_shift = p->physical_bs_shift,
+ .io_min_shift = p->io_min_shift,
+ .io_opt_shift = p->io_opt_shift,
+ .max_sectors = p->max_sectors,
+ .chunk_sectors = p->chunk_sectors,
+ .dev_sectors = p->dev_sectors,
+ },
+ .zoned = {
+ .max_open_zones = p->max_open_zones,
+ .max_active_zones = p->max_active_zones,
+ .max_zone_append_sectors = p->max_zone_append_sectors,
+ },
+ };
+}
+
static int ublk_ctrl_update_size(struct ublk_dev *dev,
__u64 nr_sects)
{@@ -1772,6 +1828,51 @@ static int __cmd_dev_add(const struct dev_ctx *ctx)
static int __cmd_dev_list(struct dev_ctx *ctx);
+static int cmd_dev_set_params(struct dev_ctx *ctx)
+{
+ struct ublksrv_ctrl_dev_info *info;
+ struct ublk_params params;
+ struct ublk_dev *dev;
+ __u64 features;
+ int ret, del_ret;
+
+ dev = ublk_ctrl_init();
+ if (!dev)
+ return -ENODEV;
+
+ ret = ublk_ctrl_get_features(dev, &features);
+ if (ret < 0)
+ goto out;
+
+ if (!(features & UBLK_F_CMD_IOCTL_ENCODE)) {
+ ret = -ENOTSUP;
+ goto out;
+ }
+
+ info = &dev->dev_info;
+ info->dev_id = ctx->dev_id;
+ info->nr_hw_queues = ctx->nr_hw_queues;
+ info->queue_depth = ctx->queue_depth;
+ info->io_desc_size = ctx->io_desc_size;
+ info->flags = ctx->flags;
+
+ ret = ublk_ctrl_add_dev(dev);
+ if (ret < 0)
+ goto out;
+
+ ublk_init_params_from_ctx(ctx, ¶ms);
+
+ ret = ublk_ctrl_set_params(dev, ¶ms);
+ printf("SET_PARAMS returned %d\n", ret);
+
+ del_ret = ublk_ctrl_del_dev(dev);
+ if (del_ret < 0 && ret == 0)
+ ret = del_ret;
+out:
+ ublk_ctrl_deinit(dev);
+ return ret < 0 ? ret : 0;
+}
+
static int cmd_dev_add(struct dev_ctx *ctx)
{
int res;@@ -2117,6 +2218,9 @@ static int cmd_dev_help(char *exe)
printf("\t --safe only stop if device has no active openers\n\n");
printf("%s list [-n dev_id] -a \n", exe);
printf("\t -a list all devices, -n list specified device, default -a \n\n");
+ printf("%s set_params [-n dev_id] [-q nr_queues] [-d depth] [-u] [--zoned]\n", exe);
+ printf("\t[--param_types basic[,zoned]|none]\n");
+ printf("\t issue ADD_DEV, SET_PARAMS and DEL_DEV without START_DEV\n\n");
printf("%s features\n", exe);
printf("%s update_size -n dev_id -s|--size size_in_bytes \n", exe);
printf("%s quiesce -n dev_id\n", exe);@@ -2160,6 +2264,18 @@ int main(int argc, char *argv[])
{ "htlb", 1, NULL, 0 },
{ "rdonly_shmem_buf", 0, NULL, 0 },
{ "io_desc_size", 1, NULL, 0 },
+ { "zoned", 0, NULL, 0 },
+ { "param_types", 1, NULL, 0 },
+ { "logical_bs_shift", 1, NULL, 0 },
+ { "physical_bs_shift", 1, NULL, 0 },
+ { "io_min_shift", 1, NULL, 0 },
+ { "io_opt_shift", 1, NULL, 0 },
+ { "max_sectors", 1, NULL, 0 },
+ { "chunk_sectors", 1, NULL, 0 },
+ { "dev_sectors", 1, NULL, 0 },
+ { "max_zone_append_sectors", 1, NULL, 0 },
+ { "max_open_zones", 1, NULL, 0 },
+ { "max_active_zones", 1, NULL, 0 },
{ 0, 0, 0, 0 }
};
const struct ublk_tgt_ops *ops = NULL;@@ -2173,6 +2289,19 @@ int main(int argc, char *argv[])
.tgt_type = "unknown",
.csum_type = LBMD_PI_CSUM_NONE,
.io_desc_size = sizeof(struct ublksrv_io_desc),
+ .params = {
+ .types = UBLK_PARAM_TYPE_BASIC,
+ .logical_bs_shift = KUBLK_PARAM_LOGICAL_BS_SHIFT,
+ .physical_bs_shift = KUBLK_PARAM_PHYSICAL_BS_SHIFT,
+ .io_min_shift = KUBLK_PARAM_LOGICAL_BS_SHIFT,
+ .io_opt_shift = KUBLK_PARAM_PHYSICAL_BS_SHIFT,
+ .max_sectors =
+ UBLK_IO_MAX_BYTES >> KUBLK_PARAM_LOGICAL_BS_SHIFT,
+ .chunk_sectors = KUBLK_PARAM_ZONE_SECTORS,
+ .dev_sectors = KUBLK_PARAM_DEV_SECTORS,
+ .max_zone_append_sectors =
+ KUBLK_PARAM_ZONE_APPEND_SECTORS,
+ },
};
int ret = -EINVAL, i;
int tgt_argc = 1;@@ -2288,6 +2417,34 @@ int main(int argc, char *argv[])
ctx.flags |= UBLK_F_IO_DESC_SIZE;
ctx.io_desc_size = strtoul(optarg, NULL, 0);
}
+ if (!strcmp(longopts[option_idx].name, "zoned"))
+ ctx.flags |= UBLK_F_ZONED;
+ if (!strcmp(longopts[option_idx].name, "param_types")) {
+ ret = parse_param_types(optarg, &ctx.params.types);
+ if (ret)
+ return ret;
+ }
+ if (!strcmp(longopts[option_idx].name, "logical_bs_shift"))
+ ctx.params.logical_bs_shift = strtoul(optarg, NULL, 0);
+ if (!strcmp(longopts[option_idx].name, "physical_bs_shift"))
+ ctx.params.physical_bs_shift = strtoul(optarg, NULL, 0);
+ if (!strcmp(longopts[option_idx].name, "io_min_shift"))
+ ctx.params.io_min_shift = strtoul(optarg, NULL, 0);
+ if (!strcmp(longopts[option_idx].name, "io_opt_shift"))
+ ctx.params.io_opt_shift = strtoul(optarg, NULL, 0);
+ if (!strcmp(longopts[option_idx].name, "max_sectors"))
+ ctx.params.max_sectors = strtoul(optarg, NULL, 0);
+ if (!strcmp(longopts[option_idx].name, "chunk_sectors"))
+ ctx.params.chunk_sectors = strtoul(optarg, NULL, 0);
+ if (!strcmp(longopts[option_idx].name, "dev_sectors"))
+ ctx.params.dev_sectors = strtoull(optarg, NULL, 0);
+ if (!strcmp(longopts[option_idx].name, "max_zone_append_sectors"))
+ ctx.params.max_zone_append_sectors =
+ strtoul(optarg, NULL, 0);
+ if (!strcmp(longopts[option_idx].name, "max_open_zones"))
+ ctx.params.max_open_zones = strtoul(optarg, NULL, 0);
+ if (!strcmp(longopts[option_idx].name, "max_active_zones"))
+ ctx.params.max_active_zones = strtoul(optarg, NULL, 0);
break;
case '?':
/*@@ -2377,7 +2534,9 @@ int main(int argc, char *argv[])
ops->parse_cmd_line(&ctx, tgt_argc, tgt_argv);
}
- if (!strcmp(cmd, "add"))
+ if (!strcmp(cmd, "set_params"))
+ ret = cmd_dev_set_params(&ctx);
+ else if (!strcmp(cmd, "add"))
ret = cmd_dev_add(&ctx);
else if (!strcmp(cmd, "recover")) {
if (ctx.dev_id < 0) {diff --git a/tools/testing/selftests/ublk/kublk.h b/tools/testing/selftests/ublk/kublk.h
index e27c154fc910..d98f3d612d88 100644
--- a/tools/testing/selftests/ublk/kublk.h
+++ b/tools/testing/selftests/ublk/kublk.h
@@ -63,6 +63,22 @@ struct fault_inject_ctx {
bool die_during_fetch;
};
+struct params_ctx {
+ __u32 types;
+
+ __u32 logical_bs_shift;
+ __u32 physical_bs_shift;
+ __u32 io_min_shift;
+ __u32 io_opt_shift;
+ __u32 max_sectors;
+ __u32 chunk_sectors;
+ __u64 dev_sectors;
+
+ __u32 max_open_zones;
+ __u32 max_active_zones;
+ __u32 max_zone_append_sectors;
+};
+
struct dev_ctx {
char tgt_type[16];
unsigned long flags;@@ -99,6 +115,8 @@ struct dev_ctx {
/* for 'update_size' command */
unsigned long long size;
+ struct params_ctx params;
+
char *htlb_path;
union {--
2.25.1