spdk记录
- hello_bdev
- 命令行参数
往期文章:
spdk环境搭建
hello_bdev
代码路径:examples/bdev/hello_world/hello_bdev.c
可执行文件路径:build/examples/hello_bdev
刚开始直接执行hello_bdev显示找不到Malloc0
./build/examples/hello_bdev
[2023-05-30 20:27:02.389489] Starting SPDK v23.05-pre git sha1 ee06693c3 / DPDK 22.11.1 initialization...
[2023-05-30 20:27:02.390910] [ DPDK EAL parameters: hello_bdev --no-shconf -c 0x1 --huge-unlink --log-level=lib.eal:6 --log-level=lib.cryptodev:5 --log-level=user1:6 --iova-mode=pa --base-virtaddr=0x200000000000 --match-allocations --file-prefix=spdk_pid11584 ]
TELEMETRY: No legacy callbacks, legacy socket not created
[2023-05-30 20:27:02.511380] app.c: 738:spdk_app_start: *NOTICE*: Total cores available: 1
[2023-05-30 20:27:02.561201] reactor.c: 937:reactor_run: *NOTICE*: Reactor started on core 0
[2023-05-30 20:27:02.600284] accel_sw.c: 601:sw_accel_module_init: *NOTICE*: Accel framework software module initialized.
[2023-05-30 20:27:02.621229] hello_bdev.c: 222:hello_start: *NOTICE*: Successfully started the application
[2023-05-30 20:27:02.621612] hello_bdev.c: 231:hello_start: *NOTICE*: Opening the bdev Malloc0
[2023-05-30 20:27:02.621691] bdev.c:7681:spdk_bdev_open_ext: *NOTICE*: Currently unable to find bdev with name: Malloc0
[2023-05-30 20:27:02.621761] hello_bdev.c: 235:hello_start: *ERROR*: Could not open bdev: Malloc0
[2023-05-30 20:27:02.621852] app.c: 844:spdk_app_stop: *WARNING*: spdk_app_stop'd on non-zero
[2023-05-30 20:27:02.691191] hello_bdev.c: 308:main: *ERROR*: ERROR starting application
在网上找到了相应issue,https://github.com/spdk/spdk/issues/1550
正确的执行方式为:
./build/examples/hello_bdev -c ./examples/bdev/hello_world/bdev.json -b Malloc0
[2023-05-30 20:25:59.131197] Starting SPDK v23.05-pre git sha1 ee06693c3 / DPDK 22.11.1 initialization...
[2023-05-30 20:25:59.132037] [ DPDK EAL parameters: hello_bdev --no-shconf -c 0x1 --huge-unlink --log-level=lib.eal:6 --log-level=lib.cryptodev:5 --log-level=user1:6 --iova-mode=pa --base-virtaddr=0x200000000000 --match-allocations --file-prefix=spdk_pid11462 ]
TELEMETRY: No legacy callbacks, legacy socket not created
[2023-05-30 20:25:59.252268] app.c: 738:spdk_app_start: *NOTICE*: Total cores available: 1
[2023-05-30 20:25:59.303646] reactor.c: 937:reactor_run: *NOTICE*: Reactor started on core 0
[2023-05-30 20:25:59.359161] accel_sw.c: 601:sw_accel_module_init: *NOTICE*: Accel framework software module initialized.
[2023-05-30 20:25:59.387635] hello_bdev.c: 222:hello_start: *NOTICE*: Successfully started the application
[2023-05-30 20:25:59.388053] hello_bdev.c: 231:hello_start: *NOTICE*: Opening the bdev Malloc0
[2023-05-30 20:25:59.388153] hello_bdev.c: 244:hello_start: *NOTICE*: Opening io channel
[2023-05-30 20:25:59.388529] hello_bdev.c: 138:hello_write: *NOTICE*: Writing to the bdev
[2023-05-30 20:25:59.388757] hello_bdev.c: 117:write_complete: *NOTICE*: bdev io write completed successfully
[2023-05-30 20:25:59.388931] hello_bdev.c: 84:hello_read: *NOTICE*: Reading io
[2023-05-30 20:25:59.389019] hello_bdev.c: 65:read_complete: *NOTICE*: Read string from bdev : Hello World!
[2023-05-30 20:25:59.389128] hello_bdev.c: 74:read_complete: *NOTICE*: Stopping app
命令行参数
-b参数
static char *g_bdev_name = "Malloc0";
/*
* Usage function for printing parameters that are specific to this application
*/
static void
hello_bdev_usage(void)
{
printf(" -b <bdev> name of the bdev to use\n");
}
/*
* This function is called to parse the parameters that are specific to this application
*/
static int
hello_bdev_parse_arg(int ch, char *arg)
{
switch (ch) {
case 'b':
g_bdev_name = arg;
break;
default:
return -EINVAL;
}
return 0;
}
spdk_app_parse_args(argc, argv, &opts, "b:", NULL, hello_bdev_parse_arg, hello_bdev_usage)
hello_context.bdev_name = g_bdev_name;
可以看出,g_bdev_name本来就是Malloc0,-b Malloc0没啥用
-c参数
static void
usage(void (*app_usage)(void))
{
printf("%s [options]\n", g_executable_name);
printf("options:\n");
printf(" -c, --config <config> JSON config file (default %s)\n",
g_default_opts.json_config_file != NULL ? g_default_opts.json_config_file : "none");
-c后加json配置文件名,bdev.json文件内容如下:
{
"subsystems": [
{
"subsystem": "bdev",
"config": [
{
"method": "bdev_malloc_create",
"params": {
"name": "Malloc0",
"num_blocks": 32768,
"block_size": 512
}
}
]
}
]
}
简要看json的解析过程,全局查询json_config_file,找到spdk_subsystem_init_from_json_config函数
void
spdk_subsystem_init_from_json_config(const char *json_config_file, const char *rpc_addr,
spdk_subsystem_init_fn cb_fn, void *cb_arg,
bool stop_on_error)
{
struct load_json_config_ctx *ctx = calloc(1, sizeof(*ctx));
int rc;
assert(cb_fn);
if (!ctx) {
cb_fn(-ENOMEM, cb_arg);
return;
}
ctx->cb_fn = cb_fn;
ctx->cb_arg = cb_arg;
ctx->stop_on_error = stop_on_error;
ctx->thread = spdk_get_thread();
rc = app_json_config_read(json_config_file, ctx);
if (rc) {
goto fail;
}
/* Capture subsystems array */
rc = spdk_json_find_array(ctx->values, "subsystems", NULL, &ctx->subsystems);
switch (rc) {
case 0:
/* Get first subsystem */
ctx->subsystems_it = spdk_json_array_first(ctx->subsystems);
if (ctx->subsystems_it == NULL) {
SPDK_NOTICELOG("'subsystems' configuration is empty\n");
}
break;
case -EPROTOTYPE:
SPDK_ERRLOG("Invalid JSON configuration: not enclosed in {}.\n");
goto fail;
case -ENOENT:
SPDK_WARNLOG("No 'subsystems' key JSON configuration file.\n");
break;
case -EDOM:
SPDK_ERRLOG("Invalid JSON configuration: 'subsystems' should be an array.\n");
goto fail;
default:
SPDK_ERRLOG("Failed to parse JSON configuration.\n");
goto fail;
}
/* If rpc_addr is not an Unix socket use default address as prefix. */
if (rpc_addr == NULL || rpc_addr[0] != '/') {
rpc_addr = SPDK_DEFAULT_RPC_ADDR;
}
/* FIXME: rpc client should use socketpair() instead of this temporary socket nonsense */
rc = snprintf(ctx->rpc_socket_path_temp, sizeof(ctx->rpc_socket_path_temp), "%s.%d_config",
rpc_addr, getpid());
if (rc >= (int)sizeof(ctx->rpc_socket_path_temp)) {
SPDK_ERRLOG("Socket name create failed\n");
goto fail;
}
rc = spdk_rpc_initialize(ctx->rpc_socket_path_temp);
if (rc) {
goto fail;
}
ctx->client_conn = spdk_jsonrpc_client_connect(ctx->rpc_socket_path_temp, AF_UNIX);
if (ctx->client_conn == NULL) {
SPDK_ERRLOG("Failed to connect to '%s'\n", ctx->rpc_socket_path_temp);
goto fail;
}
rpc_client_set_timeout(ctx, RPC_CLIENT_CONNECT_TIMEOUT_US);
ctx->client_conn_poller = SPDK_POLLER_REGISTER(rpc_client_connect_poller, ctx, 100);
return;
fail:
app_json_config_load_done(ctx, -EINVAL);
}
全局查询bdev_malloc_create,找到rpc_bdev_malloc_create函数
static void
rpc_bdev_malloc_create(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct malloc_bdev_opts req = {NULL};
struct spdk_json_write_ctx *w;
struct spdk_bdev *bdev;
int rc = 0;
if (spdk_json_decode_object(params, rpc_construct_malloc_decoders,
SPDK_COUNTOF(rpc_construct_malloc_decoders),
&req)) {
SPDK_DEBUGLOG(bdev_malloc, "spdk_json_decode_object failed\n");
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"spdk_json_decode_object failed");
goto cleanup;
}
rc = create_malloc_disk(&bdev, &req);
if (rc) {
spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
goto cleanup;
}
free_rpc_construct_malloc(&req);
w = spdk_jsonrpc_begin_result(request);
spdk_json_write_string(w, spdk_bdev_get_name(bdev));
spdk_jsonrpc_end_result(request, w);
return;
cleanup:
free_rpc_construct_malloc(&req);
}
SPDK_RPC_REGISTER("bdev_malloc_create", rpc_bdev_malloc_create, SPDK_RPC_RUNTIME)
运行到该函数的回溯栈为
(gdb) bt
#0 rpc_bdev_malloc_create (request=0xcac1f474c379e400, params=0x555555cc9570) at bdev_malloc_rpc.c:49
#1 0x00005555556b0a53 in jsonrpc_handler (request=0x555555cc04e0, method=0x555555c648e0, params=0x555555c64900) at rpc.c:124
#2 0x00005555556b2c5e in jsonrpc_server_handle_request (request=0x555555cc04e0, method=0x555555c648e0, params=0x555555c64900) at jsonrpc_server_tcp.c:222
#3 0x00005555556b1665 in parse_single_request (request=0x555555cc04e0, values=0x555555c64880) at jsonrpc_server.c:75
#4 0x00005555556b1c68 in jsonrpc_parse_request (conn=0x7ffff5f7e040, json=0x7ffff5f7e058, size=172) at jsonrpc_server.c:205
#5 0x00005555556b2eaa in jsonrpc_server_conn_recv (conn=0x7ffff5f7e040) at jsonrpc_server_tcp.c:284
#6 0x00005555556b3297 in spdk_jsonrpc_server_poll (server=0x7ffff5f7e010) at jsonrpc_server_tcp.c:402
#7 0x00005555556b0d59 in spdk_rpc_accept () at rpc.c:213
#8 0x00005555556a13c4 in rpc_subsystem_poll (arg=0x0) at rpc.c:21
#9 0x00005555556a82fd in thread_execute_timed_poller (thread=0x555555c9ec00, poller=0x555555cbf2c0, now=41542509569737) at thread.c:970
#10 0x00005555556a8613 in thread_poll (thread=0x555555c9ec00, max_msgs=0, now=41542509569737) at thread.c:1060
#11 0x00005555556a8837 in spdk_thread_poll (thread=0x555555c9ec00, max_msgs=0, now=41542509569737) at thread.c:1119
#12 0x000055555566d309 in _reactor_run (reactor=0x555555c7b780) at reactor.c:914
#13 0x000055555566d3fb in reactor_run (arg=0x555555c7b780) at reactor.c:952
#14 0x000055555566d887 in spdk_reactors_start () at reactor.c:1068
#15 0x0000555555669c5d in spdk_app_start (opts_user=0x7fffffffdea0, start_fn=0x55555556e1fb <hello_start>, arg1=0x7fffffffde40) at app.c:779
#16 0x000055555556e5d9 in main (argc=5, argv=0x7fffffffe078) at hello_bdev.c:306
p req
$19 = {name = 0x555555cc9580 "Malloc0", uuid = {u = {raw = '\000' <repeats 15 times>}}, num_blocks = 32768, block_size = 512, physical_block_size = 0, optimal_io_boundary = 0, md_size = 0,
md_interleave = false, dif_type = SPDK_DIF_DISABLE, dif_is_head_of_md = false}
猜测rpc_bdev_malloc_create函数与spdk_subsystem_init_from_json_config中的
SPDK_POLLER_REGISTER(rpc_client_connect_poller, ctx, 100);有关。
有兴趣的可以继续研究rpc_bdev_malloc_create函数中的create_malloc_disk函数