Skip to content

Commit 810b88f

Browse files
Ming Leiaxboe
authored andcommitted
selftests: ublk: support target specific command line
Support target specific command line for making related command line code handling more readable & clean. Also helps for adding new features. Signed-off-by: Ming Lei <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 6c62fd0 commit 810b88f

File tree

3 files changed

+95
-12
lines changed

3 files changed

+95
-12
lines changed

tools/testing/selftests/ublk/kublk.c

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#include "kublk.h"
77

8+
#define MAX_NR_TGT_ARG 64
9+
810
unsigned int ublk_dbg_mask = UBLK_LOG;
911
static const struct ublk_tgt_ops *tgt_ops_list[] = {
1012
&null_tgt_ops,
@@ -1202,12 +1204,25 @@ static int cmd_dev_get_features(void)
12021204

12031205
static int cmd_dev_help(char *exe)
12041206
{
1205-
printf("%s add -t [null|loop] [-q nr_queues] [-d depth] [-n dev_id] [backfile1] [backfile2] ...\n", exe);
1206-
printf("\t default: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n");
1207+
int i;
1208+
1209+
printf("%s add -t [null|loop|stripe] [-q nr_queues] [-d depth] [-n dev_id]\n", exe);
1210+
printf("\t[--foreground] [--quiet] [-z] [--debug_mask mask]\n");
1211+
printf("\t[target options] [backfile1] [backfile2] ...\n");
1212+
printf("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n");
1213+
1214+
for (i = 0; i < sizeof(tgt_ops_list) / sizeof(tgt_ops_list[0]); i++) {
1215+
const struct ublk_tgt_ops *ops = tgt_ops_list[i];
1216+
1217+
if (ops->usage)
1218+
ops->usage(ops);
1219+
}
1220+
printf("\n");
1221+
12071222
printf("%s del [-n dev_id] -a \n", exe);
1208-
printf("\t -a delete all devices -n delete specified device\n");
1223+
printf("\t -a delete all devices -n delete specified device\n\n");
12091224
printf("%s list [-n dev_id] -a \n", exe);
1210-
printf("\t -a list all devices, -n list specified device, default -a \n");
1225+
printf("\t -a list all devices, -n list specified device, default -a \n\n");
12111226
printf("%s features\n", exe);
12121227
return 0;
12131228
}
@@ -1224,23 +1239,25 @@ int main(int argc, char *argv[])
12241239
{ "quiet", 0, NULL, 0 },
12251240
{ "zero_copy", 0, NULL, 'z' },
12261241
{ "foreground", 0, NULL, 0 },
1227-
{ "chunk_size", 1, NULL, 0 },
12281242
{ 0, 0, 0, 0 }
12291243
};
1244+
const struct ublk_tgt_ops *ops = NULL;
12301245
int option_idx, opt;
12311246
const char *cmd = argv[1];
12321247
struct dev_ctx ctx = {
12331248
.queue_depth = 128,
12341249
.nr_hw_queues = 2,
12351250
.dev_id = -1,
12361251
.tgt_type = "unknown",
1237-
.chunk_size = 65536, /* def chunk size is 64K */
12381252
};
12391253
int ret = -EINVAL, i;
1254+
int tgt_argc = 1;
1255+
char *tgt_argv[MAX_NR_TGT_ARG] = { NULL };
12401256

12411257
if (argc == 1)
12421258
return ret;
12431259

1260+
opterr = 0;
12441261
optind = 2;
12451262
while ((opt = getopt_long(argc, argv, "t:n:d:q:az",
12461263
longopts, &option_idx)) != -1) {
@@ -1271,8 +1288,26 @@ int main(int argc, char *argv[])
12711288
ublk_dbg_mask = 0;
12721289
if (!strcmp(longopts[option_idx].name, "foreground"))
12731290
ctx.fg = 1;
1274-
if (!strcmp(longopts[option_idx].name, "chunk_size"))
1275-
ctx.chunk_size = strtol(optarg, NULL, 10);
1291+
break;
1292+
case '?':
1293+
/*
1294+
* target requires every option must have argument
1295+
*/
1296+
if (argv[optind][0] == '-' || argv[optind - 1][0] != '-') {
1297+
fprintf(stderr, "every target option requires argument: %s %s\n",
1298+
argv[optind - 1], argv[optind]);
1299+
exit(EXIT_FAILURE);
1300+
}
1301+
1302+
if (tgt_argc < (MAX_NR_TGT_ARG - 1) / 2) {
1303+
tgt_argv[tgt_argc++] = argv[optind - 1];
1304+
tgt_argv[tgt_argc++] = argv[optind];
1305+
} else {
1306+
fprintf(stderr, "too many target options\n");
1307+
exit(EXIT_FAILURE);
1308+
}
1309+
optind += 1;
1310+
break;
12761311
}
12771312
}
12781313

@@ -1281,6 +1316,14 @@ int main(int argc, char *argv[])
12811316
ctx.files[ctx.nr_files++] = argv[i++];
12821317
}
12831318

1319+
ops = ublk_find_tgt(ctx.tgt_type);
1320+
if (ops && ops->parse_cmd_line) {
1321+
optind = 0;
1322+
1323+
tgt_argv[0] = ctx.tgt_type;
1324+
ops->parse_cmd_line(&ctx, tgt_argc, tgt_argv);
1325+
}
1326+
12841327
if (!strcmp(cmd, "add"))
12851328
ret = cmd_dev_add(&ctx);
12861329
else if (!strcmp(cmd, "del"))

tools/testing/selftests/ublk/kublk.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@
6363
struct ublk_dev;
6464
struct ublk_queue;
6565

66+
struct stripe_ctx {
67+
/* stripe */
68+
unsigned int chunk_size;
69+
};
70+
6671
struct dev_ctx {
6772
char tgt_type[16];
6873
unsigned long flags;
@@ -75,14 +80,15 @@ struct dev_ctx {
7580
unsigned int all:1;
7681
unsigned int fg:1;
7782

78-
/* stripe */
79-
unsigned int chunk_size;
80-
8183
int _evtfd;
8284
int _shmid;
8385

8486
/* built from shmem, only for ublk_dump_dev() */
8587
struct ublk_dev *shadow_dev;
88+
89+
union {
90+
struct stripe_ctx stripe;
91+
};
8692
};
8793

8894
struct ublk_ctrl_cmd_data {
@@ -119,6 +125,14 @@ struct ublk_tgt_ops {
119125
int (*queue_io)(struct ublk_queue *, int tag);
120126
void (*tgt_io_done)(struct ublk_queue *,
121127
int tag, const struct io_uring_cqe *);
128+
129+
/*
130+
* Target specific command line handling
131+
*
132+
* each option requires argument for target command line
133+
*/
134+
void (*parse_cmd_line)(struct dev_ctx *ctx, int argc, char *argv[]);
135+
void (*usage)(const struct ublk_tgt_ops *ops);
122136
};
123137

124138
struct ublk_tgt {

tools/testing/selftests/ublk/stripe.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ static int ublk_stripe_tgt_init(const struct dev_ctx *ctx, struct ublk_dev *dev)
281281
.max_sectors = dev->dev_info.max_io_buf_bytes >> 9,
282282
},
283283
};
284-
unsigned chunk_size = ctx->chunk_size;
284+
unsigned chunk_size = ctx->stripe.chunk_size;
285285
struct stripe_conf *conf;
286286
unsigned chunk_shift;
287287
loff_t bytes = 0;
@@ -344,10 +344,36 @@ static void ublk_stripe_tgt_deinit(struct ublk_dev *dev)
344344
backing_file_tgt_deinit(dev);
345345
}
346346

347+
static void ublk_stripe_cmd_line(struct dev_ctx *ctx, int argc, char *argv[])
348+
{
349+
static const struct option longopts[] = {
350+
{ "chunk_size", 1, NULL, 0 },
351+
{ 0, 0, 0, 0 }
352+
};
353+
int option_idx, opt;
354+
355+
ctx->stripe.chunk_size = 65536;
356+
while ((opt = getopt_long(argc, argv, "",
357+
longopts, &option_idx)) != -1) {
358+
switch (opt) {
359+
case 0:
360+
if (!strcmp(longopts[option_idx].name, "chunk_size"))
361+
ctx->stripe.chunk_size = strtol(optarg, NULL, 10);
362+
}
363+
}
364+
}
365+
366+
static void ublk_stripe_usage(const struct ublk_tgt_ops *ops)
367+
{
368+
printf("\tstripe: [--chunk_size chunk_size (default 65536)]\n");
369+
}
370+
347371
const struct ublk_tgt_ops stripe_tgt_ops = {
348372
.name = "stripe",
349373
.init_tgt = ublk_stripe_tgt_init,
350374
.deinit_tgt = ublk_stripe_tgt_deinit,
351375
.queue_io = ublk_stripe_queue_io,
352376
.tgt_io_done = ublk_stripe_io_done,
377+
.parse_cmd_line = ublk_stripe_cmd_line,
378+
.usage = ublk_stripe_usage,
353379
};

0 commit comments

Comments
 (0)