1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2a6dbe372Spaul luse * Copyright (C) 2018 Intel Corporation. 3edc8c91aSSeth Howell * All rights reserved. 44bb902a6SMike Gerdts * Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5edc8c91aSSeth Howell */ 6edc8c91aSSeth Howell 7edc8c91aSSeth Howell #include "spdk/bdev.h" 8edc8c91aSSeth Howell 9ebc227d9SJim Harris #include "spdk/env.h" 10edc8c91aSSeth Howell #include "spdk/rpc.h" 11edc8c91aSSeth Howell #include "spdk/util.h" 12edc8c91aSSeth Howell #include "spdk/string.h" 13ebc227d9SJim Harris #include "spdk/base64.h" 14ebc227d9SJim Harris #include "spdk/bdev_module.h" 153185d3c9SAlexey Marchuk #include "spdk/dma.h" 16edc8c91aSSeth Howell 174e8e97c8STomasz Zawadzki #include "spdk/log.h" 18edc8c91aSSeth Howell 1924eab325SShuhei Matsumoto #include "bdev_internal.h" 2024eab325SShuhei Matsumoto 21f41248ffSShuhei Matsumoto static void 22f41248ffSShuhei Matsumoto dummy_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx) 23f41248ffSShuhei Matsumoto { 24f41248ffSShuhei Matsumoto } 25f41248ffSShuhei Matsumoto 26edc8c91aSSeth Howell static const struct spdk_json_object_decoder rpc_set_bdev_opts_decoders[] = { 27411613feSKonrad Sztyber {"bdev_io_pool_size", offsetof(struct spdk_bdev_opts, bdev_io_pool_size), spdk_json_decode_uint32, true}, 28411613feSKonrad Sztyber {"bdev_io_cache_size", offsetof(struct spdk_bdev_opts, bdev_io_cache_size), spdk_json_decode_uint32, true}, 29411613feSKonrad Sztyber {"bdev_auto_examine", offsetof(struct spdk_bdev_opts, bdev_auto_examine), spdk_json_decode_bool, true}, 309b21ca0cSKonrad Sztyber {"iobuf_small_cache_size", offsetof(struct spdk_bdev_opts, iobuf_small_cache_size), spdk_json_decode_uint32, true}, 319b21ca0cSKonrad Sztyber {"iobuf_large_cache_size", offsetof(struct spdk_bdev_opts, iobuf_large_cache_size), spdk_json_decode_uint32, true}, 32edc8c91aSSeth Howell }; 33edc8c91aSSeth Howell 34edc8c91aSSeth Howell static void 353456377bSSeth Howell rpc_bdev_set_options(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 36edc8c91aSSeth Howell { 37411613feSKonrad Sztyber struct spdk_bdev_opts opts; 38edc8c91aSSeth Howell int rc; 39edc8c91aSSeth Howell 40411613feSKonrad Sztyber spdk_bdev_get_opts(&opts, sizeof(opts)); 41edc8c91aSSeth Howell if (params != NULL) { 42edc8c91aSSeth Howell if (spdk_json_decode_object(params, rpc_set_bdev_opts_decoders, 43411613feSKonrad Sztyber SPDK_COUNTOF(rpc_set_bdev_opts_decoders), &opts)) { 44edc8c91aSSeth Howell SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 45edc8c91aSSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 46edc8c91aSSeth Howell "Invalid parameters"); 47edc8c91aSSeth Howell return; 48edc8c91aSSeth Howell } 49edc8c91aSSeth Howell } 50edc8c91aSSeth Howell 51411613feSKonrad Sztyber rc = spdk_bdev_set_opts(&opts); 52edc8c91aSSeth Howell if (rc != 0) { 53edc8c91aSSeth Howell spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 54edc8c91aSSeth Howell "Pool size %" PRIu32 " too small for cache size %" PRIu32, 55411613feSKonrad Sztyber opts.bdev_io_pool_size, opts.bdev_io_cache_size); 56edc8c91aSSeth Howell return; 57edc8c91aSSeth Howell } 58edc8c91aSSeth Howell 59d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 60edc8c91aSSeth Howell } 613456377bSSeth Howell SPDK_RPC_REGISTER("bdev_set_options", rpc_bdev_set_options, SPDK_RPC_STARTUP) 622d30df9bSyupeng 6377b6f4bcSTomasz Zawadzki static void 6477b6f4bcSTomasz Zawadzki rpc_bdev_wait_for_examine_cpl(void *arg) 6577b6f4bcSTomasz Zawadzki { 6677b6f4bcSTomasz Zawadzki struct spdk_jsonrpc_request *request = arg; 6777b6f4bcSTomasz Zawadzki 6877b6f4bcSTomasz Zawadzki spdk_jsonrpc_send_bool_response(request, true); 6977b6f4bcSTomasz Zawadzki } 7077b6f4bcSTomasz Zawadzki 7177b6f4bcSTomasz Zawadzki static void 7277b6f4bcSTomasz Zawadzki rpc_bdev_wait_for_examine(struct spdk_jsonrpc_request *request, 7377b6f4bcSTomasz Zawadzki const struct spdk_json_val *params) 7477b6f4bcSTomasz Zawadzki { 7577b6f4bcSTomasz Zawadzki int rc; 7677b6f4bcSTomasz Zawadzki 7777b6f4bcSTomasz Zawadzki if (params != NULL) { 7877b6f4bcSTomasz Zawadzki spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 7977b6f4bcSTomasz Zawadzki "bdev_wait_for_examine requires no parameters"); 8077b6f4bcSTomasz Zawadzki return; 8177b6f4bcSTomasz Zawadzki } 8277b6f4bcSTomasz Zawadzki 8377b6f4bcSTomasz Zawadzki rc = spdk_bdev_wait_for_examine(rpc_bdev_wait_for_examine_cpl, request); 8477b6f4bcSTomasz Zawadzki if (rc != 0) { 8577b6f4bcSTomasz Zawadzki spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 8677b6f4bcSTomasz Zawadzki } 8777b6f4bcSTomasz Zawadzki } 8877b6f4bcSTomasz Zawadzki SPDK_RPC_REGISTER("bdev_wait_for_examine", rpc_bdev_wait_for_examine, SPDK_RPC_RUNTIME) 8977b6f4bcSTomasz Zawadzki 902d30df9bSyupeng struct rpc_bdev_examine { 912d30df9bSyupeng char *name; 922d30df9bSyupeng }; 932d30df9bSyupeng 942d30df9bSyupeng static void 952d30df9bSyupeng free_rpc_bdev_examine(struct rpc_bdev_examine *r) 962d30df9bSyupeng { 972d30df9bSyupeng free(r->name); 982d30df9bSyupeng } 992d30df9bSyupeng 1002d30df9bSyupeng static const struct spdk_json_object_decoder rpc_examine_bdev_decoders[] = { 1012d30df9bSyupeng {"name", offsetof(struct rpc_bdev_examine, name), spdk_json_decode_string}, 1022d30df9bSyupeng }; 1032d30df9bSyupeng 1042d30df9bSyupeng static void 1052d30df9bSyupeng rpc_bdev_examine_bdev(struct spdk_jsonrpc_request *request, 1062d30df9bSyupeng const struct spdk_json_val *params) 1072d30df9bSyupeng { 1082d30df9bSyupeng struct rpc_bdev_examine req = {NULL}; 1092d30df9bSyupeng int rc; 1102d30df9bSyupeng 1112d30df9bSyupeng if (spdk_json_decode_object(params, rpc_examine_bdev_decoders, 1122d30df9bSyupeng SPDK_COUNTOF(rpc_examine_bdev_decoders), 1132d30df9bSyupeng &req)) { 1142d30df9bSyupeng SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 1152d30df9bSyupeng spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1162d30df9bSyupeng "spdk_json_decode_object failed"); 1172d30df9bSyupeng goto cleanup; 1182d30df9bSyupeng } 1192d30df9bSyupeng 1202d30df9bSyupeng rc = spdk_bdev_examine(req.name); 1212d30df9bSyupeng if (rc != 0) { 1222d30df9bSyupeng spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1232d30df9bSyupeng goto cleanup; 1242d30df9bSyupeng } 125d73077b8Syidong0635 126d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 1272d30df9bSyupeng 1282d30df9bSyupeng cleanup: 1292d30df9bSyupeng free_rpc_bdev_examine(&req); 1302d30df9bSyupeng } 1312d30df9bSyupeng SPDK_RPC_REGISTER("bdev_examine", rpc_bdev_examine_bdev, SPDK_RPC_RUNTIME) 132ebc227d9SJim Harris 1337c687dfcSShuhei Matsumoto struct rpc_get_iostat_ctx { 134ebc227d9SJim Harris int bdev_count; 1350d29a988SShuhei Matsumoto int rc; 136ebc227d9SJim Harris struct spdk_jsonrpc_request *request; 137ebc227d9SJim Harris struct spdk_json_write_ctx *w; 138e28e2479SGangCao bool per_channel; 139*63e0c25dSVasilii Ivanov enum spdk_bdev_reset_stat_mode reset_mode; 140ebc227d9SJim Harris }; 141ebc227d9SJim Harris 1427c687dfcSShuhei Matsumoto struct bdev_get_iostat_ctx { 14304786a73SShuhei Matsumoto struct spdk_bdev_io_stat *stat; 1447c687dfcSShuhei Matsumoto struct rpc_get_iostat_ctx *rpc_ctx; 1450d29a988SShuhei Matsumoto struct spdk_bdev_desc *desc; 1460d29a988SShuhei Matsumoto }; 1470d29a988SShuhei Matsumoto 1480d29a988SShuhei Matsumoto static void 149139940d6SShuhei Matsumoto rpc_get_iostat_started(struct rpc_get_iostat_ctx *rpc_ctx) 1500d29a988SShuhei Matsumoto { 1517c687dfcSShuhei Matsumoto rpc_ctx->w = spdk_jsonrpc_begin_result(rpc_ctx->request); 1520d29a988SShuhei Matsumoto 1537c687dfcSShuhei Matsumoto spdk_json_write_object_begin(rpc_ctx->w); 1547c687dfcSShuhei Matsumoto spdk_json_write_named_uint64(rpc_ctx->w, "tick_rate", spdk_get_ticks_hz()); 1557c687dfcSShuhei Matsumoto spdk_json_write_named_uint64(rpc_ctx->w, "ticks", spdk_get_ticks()); 156db3869d1SShuhei Matsumoto } 157db3869d1SShuhei Matsumoto 158db3869d1SShuhei Matsumoto static void 1597c687dfcSShuhei Matsumoto rpc_get_iostat_done(struct rpc_get_iostat_ctx *rpc_ctx) 1600d29a988SShuhei Matsumoto { 1617c687dfcSShuhei Matsumoto if (--rpc_ctx->bdev_count != 0) { 1620d29a988SShuhei Matsumoto return; 1630d29a988SShuhei Matsumoto } 1640d29a988SShuhei Matsumoto 1657c687dfcSShuhei Matsumoto if (rpc_ctx->rc == 0) { 1667c687dfcSShuhei Matsumoto spdk_json_write_array_end(rpc_ctx->w); 1677c687dfcSShuhei Matsumoto spdk_json_write_object_end(rpc_ctx->w); 1687c687dfcSShuhei Matsumoto spdk_jsonrpc_end_result(rpc_ctx->request, rpc_ctx->w); 1690d29a988SShuhei Matsumoto } else { 1700d29a988SShuhei Matsumoto /* Return error response after processing all specified bdevs 1710d29a988SShuhei Matsumoto * completed or failed. 1720d29a988SShuhei Matsumoto */ 1737c687dfcSShuhei Matsumoto spdk_jsonrpc_send_error_response(rpc_ctx->request, rpc_ctx->rc, 1747c687dfcSShuhei Matsumoto spdk_strerror(-rpc_ctx->rc)); 1750d29a988SShuhei Matsumoto } 1760d29a988SShuhei Matsumoto 1777c687dfcSShuhei Matsumoto free(rpc_ctx); 1780d29a988SShuhei Matsumoto } 1790d29a988SShuhei Matsumoto 1802356d1d6SShuhei Matsumoto static struct bdev_get_iostat_ctx * 18153a9a8c4SShuhei Matsumoto bdev_iostat_ctx_alloc(bool iostat_ext) 1822356d1d6SShuhei Matsumoto { 18304786a73SShuhei Matsumoto struct bdev_get_iostat_ctx *ctx; 18404786a73SShuhei Matsumoto 18504786a73SShuhei Matsumoto ctx = calloc(1, sizeof(struct bdev_get_iostat_ctx)); 18604786a73SShuhei Matsumoto if (ctx == NULL) { 18704786a73SShuhei Matsumoto return NULL; 18804786a73SShuhei Matsumoto } 18904786a73SShuhei Matsumoto 19053a9a8c4SShuhei Matsumoto ctx->stat = bdev_alloc_io_stat(iostat_ext); 19104786a73SShuhei Matsumoto if (ctx->stat == NULL) { 19204786a73SShuhei Matsumoto free(ctx); 19304786a73SShuhei Matsumoto return NULL; 19404786a73SShuhei Matsumoto } 19504786a73SShuhei Matsumoto 19604786a73SShuhei Matsumoto return ctx; 1972356d1d6SShuhei Matsumoto } 1982356d1d6SShuhei Matsumoto 1992356d1d6SShuhei Matsumoto static void 2002356d1d6SShuhei Matsumoto bdev_iostat_ctx_free(struct bdev_get_iostat_ctx *ctx) 2012356d1d6SShuhei Matsumoto { 202c134d11cSShuhei Matsumoto bdev_free_io_stat(ctx->stat); 2032356d1d6SShuhei Matsumoto free(ctx); 2042356d1d6SShuhei Matsumoto } 2052356d1d6SShuhei Matsumoto 206ebc227d9SJim Harris static void 2077c687dfcSShuhei Matsumoto bdev_get_iostat_done(struct spdk_bdev *bdev, struct spdk_bdev_io_stat *stat, 2087c687dfcSShuhei Matsumoto void *cb_arg, int rc) 209ebc227d9SJim Harris { 2107c687dfcSShuhei Matsumoto struct bdev_get_iostat_ctx *bdev_ctx = cb_arg; 2117c687dfcSShuhei Matsumoto struct rpc_get_iostat_ctx *rpc_ctx = bdev_ctx->rpc_ctx; 2127c687dfcSShuhei Matsumoto struct spdk_json_write_ctx *w = rpc_ctx->w; 213ebc227d9SJim Harris 2147c687dfcSShuhei Matsumoto if (rc != 0 || rpc_ctx->rc != 0) { 2157c687dfcSShuhei Matsumoto if (rpc_ctx->rc == 0) { 2167c687dfcSShuhei Matsumoto rpc_ctx->rc = rc; 2170d29a988SShuhei Matsumoto } 218ebc227d9SJim Harris goto done; 219ebc227d9SJim Harris } 220ebc227d9SJim Harris 22104786a73SShuhei Matsumoto assert(stat == bdev_ctx->stat); 2220d29a988SShuhei Matsumoto 223ebc227d9SJim Harris spdk_json_write_object_begin(w); 224ebc227d9SJim Harris 225e28e2479SGangCao spdk_json_write_named_string(w, "name", spdk_bdev_get_name(bdev)); 226e28e2479SGangCao 2278ddc102aSRichael Zhuang spdk_bdev_dump_io_stat_json(stat, w); 228ebc227d9SJim Harris 229ebc227d9SJim Harris if (spdk_bdev_get_qd_sampling_period(bdev)) { 230ebc227d9SJim Harris spdk_json_write_named_uint64(w, "queue_depth_polling_period", 231ebc227d9SJim Harris spdk_bdev_get_qd_sampling_period(bdev)); 232ebc227d9SJim Harris 233ebc227d9SJim Harris spdk_json_write_named_uint64(w, "queue_depth", spdk_bdev_get_qd(bdev)); 234ebc227d9SJim Harris 235ebc227d9SJim Harris spdk_json_write_named_uint64(w, "io_time", spdk_bdev_get_io_time(bdev)); 236ebc227d9SJim Harris 237ebc227d9SJim Harris spdk_json_write_named_uint64(w, "weighted_io_time", 238ebc227d9SJim Harris spdk_bdev_get_weighted_io_time(bdev)); 239ebc227d9SJim Harris } 240ebc227d9SJim Harris 2418c439a67SShuhei Matsumoto if (bdev->fn_table->dump_device_stat_json) { 2428c439a67SShuhei Matsumoto spdk_json_write_named_object_begin(w, "driver_specific"); 2438c439a67SShuhei Matsumoto bdev->fn_table->dump_device_stat_json(bdev->ctxt, w); 2448c439a67SShuhei Matsumoto spdk_json_write_object_end(w); 2458c439a67SShuhei Matsumoto } 2468c439a67SShuhei Matsumoto 247ebc227d9SJim Harris spdk_json_write_object_end(w); 248ebc227d9SJim Harris 249ebc227d9SJim Harris done: 2507c687dfcSShuhei Matsumoto rpc_get_iostat_done(rpc_ctx); 2510d29a988SShuhei Matsumoto 2527c687dfcSShuhei Matsumoto spdk_bdev_close(bdev_ctx->desc); 2532356d1d6SShuhei Matsumoto bdev_iostat_ctx_free(bdev_ctx); 254ebc227d9SJim Harris } 255ebc227d9SJim Harris 2560d29a988SShuhei Matsumoto static int 2577c687dfcSShuhei Matsumoto bdev_get_iostat(void *ctx, struct spdk_bdev *bdev) 2580d29a988SShuhei Matsumoto { 2597c687dfcSShuhei Matsumoto struct rpc_get_iostat_ctx *rpc_ctx = ctx; 2607c687dfcSShuhei Matsumoto struct bdev_get_iostat_ctx *bdev_ctx; 2610d29a988SShuhei Matsumoto int rc; 2620d29a988SShuhei Matsumoto 26353a9a8c4SShuhei Matsumoto bdev_ctx = bdev_iostat_ctx_alloc(true); 2647c687dfcSShuhei Matsumoto if (bdev_ctx == NULL) { 2657c687dfcSShuhei Matsumoto SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 2660d29a988SShuhei Matsumoto return -ENOMEM; 2670d29a988SShuhei Matsumoto } 2680d29a988SShuhei Matsumoto 2697c687dfcSShuhei Matsumoto rc = spdk_bdev_open_ext(spdk_bdev_get_name(bdev), false, dummy_bdev_event_cb, NULL, 2707c687dfcSShuhei Matsumoto &bdev_ctx->desc); 2710d29a988SShuhei Matsumoto if (rc != 0) { 2722356d1d6SShuhei Matsumoto bdev_iostat_ctx_free(bdev_ctx); 2730d29a988SShuhei Matsumoto SPDK_ERRLOG("Failed to open bdev\n"); 2740d29a988SShuhei Matsumoto return rc; 2750d29a988SShuhei Matsumoto } 2760d29a988SShuhei Matsumoto 2777c687dfcSShuhei Matsumoto rpc_ctx->bdev_count++; 2787c687dfcSShuhei Matsumoto bdev_ctx->rpc_ctx = rpc_ctx; 279*63e0c25dSVasilii Ivanov spdk_bdev_get_device_stat(bdev, bdev_ctx->stat, rpc_ctx->reset_mode, bdev_get_iostat_done, 280*63e0c25dSVasilii Ivanov bdev_ctx); 2810d29a988SShuhei Matsumoto 2820d29a988SShuhei Matsumoto return 0; 2830d29a988SShuhei Matsumoto } 2840d29a988SShuhei Matsumoto 285ebc227d9SJim Harris static void 2867c687dfcSShuhei Matsumoto bdev_get_per_channel_stat_done(struct spdk_bdev *bdev, void *ctx, int status) 287e28e2479SGangCao { 2887c687dfcSShuhei Matsumoto struct bdev_get_iostat_ctx *bdev_ctx = ctx; 289e28e2479SGangCao 2907c687dfcSShuhei Matsumoto rpc_get_iostat_done(bdev_ctx->rpc_ctx); 291e28e2479SGangCao 2927c687dfcSShuhei Matsumoto spdk_bdev_close(bdev_ctx->desc); 293e28e2479SGangCao 2942356d1d6SShuhei Matsumoto bdev_iostat_ctx_free(bdev_ctx); 295e28e2479SGangCao } 296e28e2479SGangCao 297e28e2479SGangCao static void 2987c687dfcSShuhei Matsumoto bdev_get_per_channel_stat(struct spdk_bdev_channel_iter *i, struct spdk_bdev *bdev, 299e28e2479SGangCao struct spdk_io_channel *ch, void *ctx) 300e28e2479SGangCao { 3017c687dfcSShuhei Matsumoto struct bdev_get_iostat_ctx *bdev_ctx = ctx; 3027c687dfcSShuhei Matsumoto struct spdk_json_write_ctx *w = bdev_ctx->rpc_ctx->w; 303e28e2479SGangCao 304*63e0c25dSVasilii Ivanov spdk_bdev_get_io_stat(bdev, ch, bdev_ctx->stat, bdev_ctx->rpc_ctx->reset_mode); 305e28e2479SGangCao 306e28e2479SGangCao spdk_json_write_object_begin(w); 307e28e2479SGangCao spdk_json_write_named_uint64(w, "thread_id", spdk_thread_get_id(spdk_get_thread())); 3088ddc102aSRichael Zhuang spdk_bdev_dump_io_stat_json(bdev_ctx->stat, w); 309e28e2479SGangCao spdk_json_write_object_end(w); 310e28e2479SGangCao 311e28e2479SGangCao spdk_bdev_for_each_channel_continue(i, 0); 312e28e2479SGangCao } 313e28e2479SGangCao 314038fb903SShuhei Matsumoto struct rpc_bdev_get_iostat { 315038fb903SShuhei Matsumoto char *name; 316038fb903SShuhei Matsumoto bool per_channel; 317*63e0c25dSVasilii Ivanov enum spdk_bdev_reset_stat_mode reset_mode; 318038fb903SShuhei Matsumoto }; 319038fb903SShuhei Matsumoto 320038fb903SShuhei Matsumoto static void 321038fb903SShuhei Matsumoto free_rpc_bdev_get_iostat(struct rpc_bdev_get_iostat *r) 322038fb903SShuhei Matsumoto { 323038fb903SShuhei Matsumoto free(r->name); 324038fb903SShuhei Matsumoto } 325038fb903SShuhei Matsumoto 326*63e0c25dSVasilii Ivanov static int 327*63e0c25dSVasilii Ivanov rpc_decode_reset_iostat_mode(const struct spdk_json_val *val, void *out) 328*63e0c25dSVasilii Ivanov { 329*63e0c25dSVasilii Ivanov enum spdk_bdev_reset_stat_mode *mode = out; 330*63e0c25dSVasilii Ivanov 331*63e0c25dSVasilii Ivanov if (spdk_json_strequal(val, "all") == true) { 332*63e0c25dSVasilii Ivanov *mode = SPDK_BDEV_RESET_STAT_ALL; 333*63e0c25dSVasilii Ivanov } else if (spdk_json_strequal(val, "maxmin") == true) { 334*63e0c25dSVasilii Ivanov *mode = SPDK_BDEV_RESET_STAT_MAXMIN; 335*63e0c25dSVasilii Ivanov } else if (spdk_json_strequal(val, "none") == true) { 336*63e0c25dSVasilii Ivanov *mode = SPDK_BDEV_RESET_STAT_NONE; 337*63e0c25dSVasilii Ivanov } else { 338*63e0c25dSVasilii Ivanov SPDK_NOTICELOG("Invalid parameter value: mode\n"); 339*63e0c25dSVasilii Ivanov return -EINVAL; 340*63e0c25dSVasilii Ivanov } 341*63e0c25dSVasilii Ivanov 342*63e0c25dSVasilii Ivanov return 0; 343*63e0c25dSVasilii Ivanov } 344*63e0c25dSVasilii Ivanov 345038fb903SShuhei Matsumoto static const struct spdk_json_object_decoder rpc_bdev_get_iostat_decoders[] = { 346038fb903SShuhei Matsumoto {"name", offsetof(struct rpc_bdev_get_iostat, name), spdk_json_decode_string, true}, 347038fb903SShuhei Matsumoto {"per_channel", offsetof(struct rpc_bdev_get_iostat, per_channel), spdk_json_decode_bool, true}, 348*63e0c25dSVasilii Ivanov {"reset_mode", offsetof(struct rpc_bdev_get_iostat, reset_mode), rpc_decode_reset_iostat_mode, true}, 349038fb903SShuhei Matsumoto }; 350038fb903SShuhei Matsumoto 351e28e2479SGangCao static void 352ebc227d9SJim Harris rpc_bdev_get_iostat(struct spdk_jsonrpc_request *request, 353ebc227d9SJim Harris const struct spdk_json_val *params) 354ebc227d9SJim Harris { 355*63e0c25dSVasilii Ivanov struct rpc_bdev_get_iostat req = { .reset_mode = SPDK_BDEV_RESET_STAT_NONE }; 3560d29a988SShuhei Matsumoto struct spdk_bdev_desc *desc = NULL; 3577c687dfcSShuhei Matsumoto struct rpc_get_iostat_ctx *rpc_ctx; 3587c687dfcSShuhei Matsumoto struct bdev_get_iostat_ctx *bdev_ctx; 359139940d6SShuhei Matsumoto struct spdk_bdev *bdev; 3600d29a988SShuhei Matsumoto int rc; 361ebc227d9SJim Harris 362ebc227d9SJim Harris if (params != NULL) { 363ebc227d9SJim Harris if (spdk_json_decode_object(params, rpc_bdev_get_iostat_decoders, 364ebc227d9SJim Harris SPDK_COUNTOF(rpc_bdev_get_iostat_decoders), 365ebc227d9SJim Harris &req)) { 366ebc227d9SJim Harris SPDK_ERRLOG("spdk_json_decode_object failed\n"); 367ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 368ebc227d9SJim Harris "spdk_json_decode_object failed"); 369ebc227d9SJim Harris free_rpc_bdev_get_iostat(&req); 370ebc227d9SJim Harris return; 371ebc227d9SJim Harris } 372ebc227d9SJim Harris 373e28e2479SGangCao if (req.per_channel == true && !req.name) { 374e28e2479SGangCao SPDK_ERRLOG("Bdev name is required for per channel IO statistics\n"); 375e28e2479SGangCao spdk_jsonrpc_send_error_response(request, -EINVAL, spdk_strerror(EINVAL)); 376e28e2479SGangCao free_rpc_bdev_get_iostat(&req); 377e28e2479SGangCao return; 378e28e2479SGangCao } 379e28e2479SGangCao 380ebc227d9SJim Harris if (req.name) { 3810d29a988SShuhei Matsumoto rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 3820d29a988SShuhei Matsumoto if (rc != 0) { 3830d29a988SShuhei Matsumoto SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 3840d29a988SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 385ebc227d9SJim Harris free_rpc_bdev_get_iostat(&req); 386ebc227d9SJim Harris return; 387ebc227d9SJim Harris } 388ebc227d9SJim Harris } 389ebc227d9SJim Harris } 390ebc227d9SJim Harris 391ebc227d9SJim Harris free_rpc_bdev_get_iostat(&req); 392ebc227d9SJim Harris 3937c687dfcSShuhei Matsumoto rpc_ctx = calloc(1, sizeof(struct rpc_get_iostat_ctx)); 3947c687dfcSShuhei Matsumoto if (rpc_ctx == NULL) { 3957c687dfcSShuhei Matsumoto SPDK_ERRLOG("Failed to allocate rpc_iostat_ctx struct\n"); 396ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 397ebc227d9SJim Harris return; 398ebc227d9SJim Harris } 399ebc227d9SJim Harris 400ebc227d9SJim Harris /* 401ebc227d9SJim Harris * Increment initial bdev_count so that it will never reach 0 in the middle 402ebc227d9SJim Harris * of iterating. 403ebc227d9SJim Harris */ 4047c687dfcSShuhei Matsumoto rpc_ctx->bdev_count++; 4057c687dfcSShuhei Matsumoto rpc_ctx->request = request; 4067c687dfcSShuhei Matsumoto rpc_ctx->per_channel = req.per_channel; 407*63e0c25dSVasilii Ivanov rpc_ctx->reset_mode = req.reset_mode; 408ebc227d9SJim Harris 4090d29a988SShuhei Matsumoto if (desc != NULL) { 410139940d6SShuhei Matsumoto bdev = spdk_bdev_desc_get_bdev(desc); 411139940d6SShuhei Matsumoto 41253a9a8c4SShuhei Matsumoto bdev_ctx = bdev_iostat_ctx_alloc(req.per_channel == false); 4137c687dfcSShuhei Matsumoto if (bdev_ctx == NULL) { 4147c687dfcSShuhei Matsumoto SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 4157c687dfcSShuhei Matsumoto rpc_ctx->rc = -ENOMEM; 416ebc227d9SJim Harris 4170d29a988SShuhei Matsumoto spdk_bdev_close(desc); 418ebc227d9SJim Harris } else { 4197c687dfcSShuhei Matsumoto bdev_ctx->desc = desc; 4200d29a988SShuhei Matsumoto 4217c687dfcSShuhei Matsumoto rpc_ctx->bdev_count++; 4227c687dfcSShuhei Matsumoto bdev_ctx->rpc_ctx = rpc_ctx; 423e28e2479SGangCao if (req.per_channel == false) { 424*63e0c25dSVasilii Ivanov spdk_bdev_get_device_stat(bdev, bdev_ctx->stat, rpc_ctx->reset_mode, 425*63e0c25dSVasilii Ivanov bdev_get_iostat_done, bdev_ctx); 426e28e2479SGangCao } else { 427139940d6SShuhei Matsumoto /* If per_channel is true, there is no failure after here and 428139940d6SShuhei Matsumoto * we have to start RPC response before executing 429139940d6SShuhei Matsumoto * spdk_bdev_for_each_channel(). 430139940d6SShuhei Matsumoto */ 431139940d6SShuhei Matsumoto rpc_get_iostat_started(rpc_ctx); 432139940d6SShuhei Matsumoto spdk_json_write_named_string(rpc_ctx->w, "name", spdk_bdev_get_name(bdev)); 433139940d6SShuhei Matsumoto spdk_json_write_named_array_begin(rpc_ctx->w, "channels"); 434139940d6SShuhei Matsumoto 435139940d6SShuhei Matsumoto spdk_bdev_for_each_channel(bdev, 4367c687dfcSShuhei Matsumoto bdev_get_per_channel_stat, 4377c687dfcSShuhei Matsumoto bdev_ctx, 4387c687dfcSShuhei Matsumoto bdev_get_per_channel_stat_done); 439139940d6SShuhei Matsumoto 440139940d6SShuhei Matsumoto rpc_get_iostat_done(rpc_ctx); 441139940d6SShuhei Matsumoto return; 442e28e2479SGangCao } 443ebc227d9SJim Harris } 444ebc227d9SJim Harris } else { 4457c687dfcSShuhei Matsumoto rc = spdk_for_each_bdev(rpc_ctx, bdev_get_iostat); 4467c687dfcSShuhei Matsumoto if (rc != 0 && rpc_ctx->rc == 0) { 4477c687dfcSShuhei Matsumoto rpc_ctx->rc = rc; 448ebc227d9SJim Harris } 449ebc227d9SJim Harris } 450ebc227d9SJim Harris 4517c687dfcSShuhei Matsumoto if (rpc_ctx->rc == 0) { 452139940d6SShuhei Matsumoto /* We want to fail the RPC for all failures. If per_channel is false, 453139940d6SShuhei Matsumoto * it is enough to defer starting RPC response until it is ensured that 454e28e2479SGangCao * all spdk_bdev_for_each_channel() calls will succeed or there is no bdev. 4550d29a988SShuhei Matsumoto */ 456139940d6SShuhei Matsumoto rpc_get_iostat_started(rpc_ctx); 457139940d6SShuhei Matsumoto spdk_json_write_named_array_begin(rpc_ctx->w, "bdevs"); 458ebc227d9SJim Harris } 4590d29a988SShuhei Matsumoto 4607c687dfcSShuhei Matsumoto rpc_get_iostat_done(rpc_ctx); 461ebc227d9SJim Harris } 462ebc227d9SJim Harris SPDK_RPC_REGISTER("bdev_get_iostat", rpc_bdev_get_iostat, SPDK_RPC_RUNTIME) 463ebc227d9SJim Harris 464cf4e8664SShuhei Matsumoto struct rpc_reset_iostat_ctx { 465cf4e8664SShuhei Matsumoto int bdev_count; 466cf4e8664SShuhei Matsumoto int rc; 467cf4e8664SShuhei Matsumoto struct spdk_jsonrpc_request *request; 468cf4e8664SShuhei Matsumoto struct spdk_json_write_ctx *w; 4698ddc102aSRichael Zhuang enum spdk_bdev_reset_stat_mode mode; 470cf4e8664SShuhei Matsumoto }; 471cf4e8664SShuhei Matsumoto 472cf4e8664SShuhei Matsumoto struct bdev_reset_iostat_ctx { 473cf4e8664SShuhei Matsumoto struct rpc_reset_iostat_ctx *rpc_ctx; 474cf4e8664SShuhei Matsumoto struct spdk_bdev_desc *desc; 475cf4e8664SShuhei Matsumoto }; 476cf4e8664SShuhei Matsumoto 477cf4e8664SShuhei Matsumoto static void 478cf4e8664SShuhei Matsumoto rpc_reset_iostat_done(struct rpc_reset_iostat_ctx *rpc_ctx) 479cf4e8664SShuhei Matsumoto { 480cf4e8664SShuhei Matsumoto if (--rpc_ctx->bdev_count != 0) { 481cf4e8664SShuhei Matsumoto return; 482cf4e8664SShuhei Matsumoto } 483cf4e8664SShuhei Matsumoto 484cf4e8664SShuhei Matsumoto if (rpc_ctx->rc == 0) { 485cf4e8664SShuhei Matsumoto spdk_jsonrpc_send_bool_response(rpc_ctx->request, true); 486cf4e8664SShuhei Matsumoto } else { 487cf4e8664SShuhei Matsumoto spdk_jsonrpc_send_error_response(rpc_ctx->request, rpc_ctx->rc, 488cf4e8664SShuhei Matsumoto spdk_strerror(-rpc_ctx->rc)); 489cf4e8664SShuhei Matsumoto } 490cf4e8664SShuhei Matsumoto 491cf4e8664SShuhei Matsumoto free(rpc_ctx); 492cf4e8664SShuhei Matsumoto } 493cf4e8664SShuhei Matsumoto 494cf4e8664SShuhei Matsumoto static void 495cf4e8664SShuhei Matsumoto bdev_reset_iostat_done(struct spdk_bdev *bdev, void *cb_arg, int rc) 496cf4e8664SShuhei Matsumoto { 497cf4e8664SShuhei Matsumoto struct bdev_reset_iostat_ctx *bdev_ctx = cb_arg; 498cf4e8664SShuhei Matsumoto struct rpc_reset_iostat_ctx *rpc_ctx = bdev_ctx->rpc_ctx; 499cf4e8664SShuhei Matsumoto 500cf4e8664SShuhei Matsumoto if (rc != 0 || rpc_ctx->rc != 0) { 501cf4e8664SShuhei Matsumoto if (rpc_ctx->rc == 0) { 502cf4e8664SShuhei Matsumoto rpc_ctx->rc = rc; 503cf4e8664SShuhei Matsumoto } 504cf4e8664SShuhei Matsumoto } 505cf4e8664SShuhei Matsumoto 506cf4e8664SShuhei Matsumoto rpc_reset_iostat_done(rpc_ctx); 507cf4e8664SShuhei Matsumoto 508cf4e8664SShuhei Matsumoto spdk_bdev_close(bdev_ctx->desc); 509cf4e8664SShuhei Matsumoto free(bdev_ctx); 510cf4e8664SShuhei Matsumoto } 511cf4e8664SShuhei Matsumoto 512cf4e8664SShuhei Matsumoto static int 513cf4e8664SShuhei Matsumoto bdev_reset_iostat(void *ctx, struct spdk_bdev *bdev) 514cf4e8664SShuhei Matsumoto { 515cf4e8664SShuhei Matsumoto struct rpc_reset_iostat_ctx *rpc_ctx = ctx; 516cf4e8664SShuhei Matsumoto struct bdev_reset_iostat_ctx *bdev_ctx; 517cf4e8664SShuhei Matsumoto int rc; 518cf4e8664SShuhei Matsumoto 519cf4e8664SShuhei Matsumoto bdev_ctx = calloc(1, sizeof(struct bdev_reset_iostat_ctx)); 520cf4e8664SShuhei Matsumoto if (bdev_ctx == NULL) { 521cf4e8664SShuhei Matsumoto SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 522cf4e8664SShuhei Matsumoto return -ENOMEM; 523cf4e8664SShuhei Matsumoto } 524cf4e8664SShuhei Matsumoto 525cf4e8664SShuhei Matsumoto rc = spdk_bdev_open_ext(spdk_bdev_get_name(bdev), false, dummy_bdev_event_cb, NULL, 526cf4e8664SShuhei Matsumoto &bdev_ctx->desc); 527cf4e8664SShuhei Matsumoto if (rc != 0) { 528cf4e8664SShuhei Matsumoto free(bdev_ctx); 529cf4e8664SShuhei Matsumoto SPDK_ERRLOG("Failed to open bdev\n"); 530cf4e8664SShuhei Matsumoto return rc; 531cf4e8664SShuhei Matsumoto } 532cf4e8664SShuhei Matsumoto 5338c439a67SShuhei Matsumoto if (bdev->fn_table->reset_device_stat) { 5348c439a67SShuhei Matsumoto bdev->fn_table->reset_device_stat(bdev->ctxt); 5358c439a67SShuhei Matsumoto } 5368c439a67SShuhei Matsumoto 537cf4e8664SShuhei Matsumoto rpc_ctx->bdev_count++; 538cf4e8664SShuhei Matsumoto bdev_ctx->rpc_ctx = rpc_ctx; 539d7ad7bcaSShuhei Matsumoto bdev_reset_device_stat(bdev, rpc_ctx->mode, bdev_reset_iostat_done, bdev_ctx); 540cf4e8664SShuhei Matsumoto 541cf4e8664SShuhei Matsumoto return 0; 542cf4e8664SShuhei Matsumoto } 543cf4e8664SShuhei Matsumoto 544cf4e8664SShuhei Matsumoto struct rpc_bdev_reset_iostat { 545cf4e8664SShuhei Matsumoto char *name; 5468ddc102aSRichael Zhuang enum spdk_bdev_reset_stat_mode mode; 547cf4e8664SShuhei Matsumoto }; 548cf4e8664SShuhei Matsumoto 549cf4e8664SShuhei Matsumoto static void 550cf4e8664SShuhei Matsumoto free_rpc_bdev_reset_iostat(struct rpc_bdev_reset_iostat *r) 551cf4e8664SShuhei Matsumoto { 552cf4e8664SShuhei Matsumoto free(r->name); 553cf4e8664SShuhei Matsumoto } 554cf4e8664SShuhei Matsumoto 555cf4e8664SShuhei Matsumoto static const struct spdk_json_object_decoder rpc_bdev_reset_iostat_decoders[] = { 556cf4e8664SShuhei Matsumoto {"name", offsetof(struct rpc_bdev_reset_iostat, name), spdk_json_decode_string, true}, 557d7ad7bcaSShuhei Matsumoto {"mode", offsetof(struct rpc_bdev_reset_iostat, mode), rpc_decode_reset_iostat_mode, true}, 558cf4e8664SShuhei Matsumoto }; 559cf4e8664SShuhei Matsumoto 560cf4e8664SShuhei Matsumoto static void 561cf4e8664SShuhei Matsumoto rpc_bdev_reset_iostat(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 562cf4e8664SShuhei Matsumoto { 563567d6b53SRichael Zhuang struct rpc_bdev_reset_iostat req = { .mode = SPDK_BDEV_RESET_STAT_ALL, }; 564cf4e8664SShuhei Matsumoto struct spdk_bdev_desc *desc = NULL; 565cf4e8664SShuhei Matsumoto struct rpc_reset_iostat_ctx *rpc_ctx; 566cf4e8664SShuhei Matsumoto struct bdev_reset_iostat_ctx *bdev_ctx; 567cf4e8664SShuhei Matsumoto int rc; 568cf4e8664SShuhei Matsumoto 569cf4e8664SShuhei Matsumoto if (params != NULL) { 570cf4e8664SShuhei Matsumoto if (spdk_json_decode_object(params, rpc_bdev_reset_iostat_decoders, 571cf4e8664SShuhei Matsumoto SPDK_COUNTOF(rpc_bdev_reset_iostat_decoders), 572cf4e8664SShuhei Matsumoto &req)) { 573cf4e8664SShuhei Matsumoto SPDK_ERRLOG("spdk_json_decode_object failed\n"); 574cf4e8664SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 575cf4e8664SShuhei Matsumoto "spdk_json_decode_object failed"); 576cf4e8664SShuhei Matsumoto free_rpc_bdev_reset_iostat(&req); 577cf4e8664SShuhei Matsumoto return; 578cf4e8664SShuhei Matsumoto } 579cf4e8664SShuhei Matsumoto 580*63e0c25dSVasilii Ivanov if (req.mode == SPDK_BDEV_RESET_STAT_NONE) { 581*63e0c25dSVasilii Ivanov SPDK_NOTICELOG("bdev_reset_iostat called with mode none, aborting operation\n"); 582*63e0c25dSVasilii Ivanov spdk_jsonrpc_send_bool_response(request, true); 583*63e0c25dSVasilii Ivanov free_rpc_bdev_reset_iostat(&req); 584*63e0c25dSVasilii Ivanov return; 585*63e0c25dSVasilii Ivanov } 586*63e0c25dSVasilii Ivanov 587cf4e8664SShuhei Matsumoto if (req.name) { 588cf4e8664SShuhei Matsumoto rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 589cf4e8664SShuhei Matsumoto if (rc != 0) { 590cf4e8664SShuhei Matsumoto SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 591cf4e8664SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 592cf4e8664SShuhei Matsumoto free_rpc_bdev_reset_iostat(&req); 593cf4e8664SShuhei Matsumoto return; 594cf4e8664SShuhei Matsumoto } 595cf4e8664SShuhei Matsumoto } 596cf4e8664SShuhei Matsumoto } 597cf4e8664SShuhei Matsumoto 598cf4e8664SShuhei Matsumoto 599cf4e8664SShuhei Matsumoto rpc_ctx = calloc(1, sizeof(struct rpc_reset_iostat_ctx)); 600cf4e8664SShuhei Matsumoto if (rpc_ctx == NULL) { 601cf4e8664SShuhei Matsumoto SPDK_ERRLOG("Failed to allocate rpc_iostat_ctx struct\n"); 602cf4e8664SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 603d7ad7bcaSShuhei Matsumoto free_rpc_bdev_reset_iostat(&req); 604cf4e8664SShuhei Matsumoto return; 605cf4e8664SShuhei Matsumoto } 606cf4e8664SShuhei Matsumoto 607cf4e8664SShuhei Matsumoto /* 608cf4e8664SShuhei Matsumoto * Increment initial bdev_count so that it will never reach 0 in the middle 609cf4e8664SShuhei Matsumoto * of iterating. 610cf4e8664SShuhei Matsumoto */ 611cf4e8664SShuhei Matsumoto rpc_ctx->bdev_count++; 612cf4e8664SShuhei Matsumoto rpc_ctx->request = request; 613d7ad7bcaSShuhei Matsumoto rpc_ctx->mode = req.mode; 614d7ad7bcaSShuhei Matsumoto 615d7ad7bcaSShuhei Matsumoto free_rpc_bdev_reset_iostat(&req); 616cf4e8664SShuhei Matsumoto 617cf4e8664SShuhei Matsumoto if (desc != NULL) { 618cf4e8664SShuhei Matsumoto bdev_ctx = calloc(1, sizeof(struct bdev_reset_iostat_ctx)); 619cf4e8664SShuhei Matsumoto if (bdev_ctx == NULL) { 620cf4e8664SShuhei Matsumoto SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 621cf4e8664SShuhei Matsumoto rpc_ctx->rc = -ENOMEM; 622cf4e8664SShuhei Matsumoto 623cf4e8664SShuhei Matsumoto spdk_bdev_close(desc); 624cf4e8664SShuhei Matsumoto } else { 625cf4e8664SShuhei Matsumoto bdev_ctx->desc = desc; 626cf4e8664SShuhei Matsumoto 627cf4e8664SShuhei Matsumoto rpc_ctx->bdev_count++; 628cf4e8664SShuhei Matsumoto bdev_ctx->rpc_ctx = rpc_ctx; 629d7ad7bcaSShuhei Matsumoto bdev_reset_device_stat(spdk_bdev_desc_get_bdev(desc), rpc_ctx->mode, 630cf4e8664SShuhei Matsumoto bdev_reset_iostat_done, bdev_ctx); 631cf4e8664SShuhei Matsumoto } 632cf4e8664SShuhei Matsumoto } else { 633cf4e8664SShuhei Matsumoto rc = spdk_for_each_bdev(rpc_ctx, bdev_reset_iostat); 634cf4e8664SShuhei Matsumoto if (rc != 0 && rpc_ctx->rc == 0) { 635cf4e8664SShuhei Matsumoto rpc_ctx->rc = rc; 636cf4e8664SShuhei Matsumoto } 637cf4e8664SShuhei Matsumoto } 638cf4e8664SShuhei Matsumoto 639cf4e8664SShuhei Matsumoto rpc_reset_iostat_done(rpc_ctx); 640cf4e8664SShuhei Matsumoto } 641cf4e8664SShuhei Matsumoto SPDK_RPC_REGISTER("bdev_reset_iostat", rpc_bdev_reset_iostat, SPDK_RPC_RUNTIME) 642cf4e8664SShuhei Matsumoto 6430d29a988SShuhei Matsumoto static int 6440d29a988SShuhei Matsumoto rpc_dump_bdev_info(void *ctx, struct spdk_bdev *bdev) 645ebc227d9SJim Harris { 6460d29a988SShuhei Matsumoto struct spdk_json_write_ctx *w = ctx; 647ebc227d9SJim Harris struct spdk_bdev_alias *tmp; 648ebc227d9SJim Harris uint64_t qos_limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES]; 6493185d3c9SAlexey Marchuk struct spdk_memory_domain **domains; 6503886567dSAtul Malakar enum spdk_bdev_io_type io_type; 6513886567dSAtul Malakar const char *name = NULL; 6523185d3c9SAlexey Marchuk int i, rc; 653ebc227d9SJim Harris 654ebc227d9SJim Harris spdk_json_write_object_begin(w); 655ebc227d9SJim Harris 656ebc227d9SJim Harris spdk_json_write_named_string(w, "name", spdk_bdev_get_name(bdev)); 657ebc227d9SJim Harris 658ebc227d9SJim Harris spdk_json_write_named_array_begin(w, "aliases"); 659ebc227d9SJim Harris 660ebc227d9SJim Harris TAILQ_FOREACH(tmp, spdk_bdev_get_aliases(bdev), tailq) { 661eabe783cSJiewei Ke spdk_json_write_string(w, tmp->alias.name); 662ebc227d9SJim Harris } 663ebc227d9SJim Harris 664ebc227d9SJim Harris spdk_json_write_array_end(w); 665ebc227d9SJim Harris 666ebc227d9SJim Harris spdk_json_write_named_string(w, "product_name", spdk_bdev_get_product_name(bdev)); 667ebc227d9SJim Harris spdk_json_write_named_uint32(w, "block_size", spdk_bdev_get_block_size(bdev)); 668ebc227d9SJim Harris spdk_json_write_named_uint64(w, "num_blocks", spdk_bdev_get_num_blocks(bdev)); 6698cffbe01SKonrad Sztyber spdk_json_write_named_uuid(w, "uuid", &bdev->uuid); 670fee788f6SJim Harris if (bdev->numa.id_valid) { 671fee788f6SJim Harris spdk_json_write_named_int32(w, "numa_id", bdev->numa.id); 672fee788f6SJim Harris } 673ebc227d9SJim Harris 674ebc227d9SJim Harris if (spdk_bdev_get_md_size(bdev) != 0) { 675ebc227d9SJim Harris spdk_json_write_named_uint32(w, "md_size", spdk_bdev_get_md_size(bdev)); 676ebc227d9SJim Harris spdk_json_write_named_bool(w, "md_interleave", spdk_bdev_is_md_interleaved(bdev)); 677ebc227d9SJim Harris spdk_json_write_named_uint32(w, "dif_type", spdk_bdev_get_dif_type(bdev)); 678ebc227d9SJim Harris if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) { 679ebc227d9SJim Harris spdk_json_write_named_bool(w, "dif_is_head_of_md", spdk_bdev_is_dif_head_of_md(bdev)); 680ebc227d9SJim Harris spdk_json_write_named_object_begin(w, "enabled_dif_check_types"); 681ebc227d9SJim Harris spdk_json_write_named_bool(w, "reftag", 682ebc227d9SJim Harris spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG)); 683ebc227d9SJim Harris spdk_json_write_named_bool(w, "apptag", 684ebc227d9SJim Harris spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_APPTAG)); 685ebc227d9SJim Harris spdk_json_write_named_bool(w, "guard", 686ebc227d9SJim Harris spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD)); 687ebc227d9SJim Harris spdk_json_write_object_end(w); 688cdc37d69SShuhei Matsumoto 689cdc37d69SShuhei Matsumoto spdk_json_write_named_uint32(w, "dif_pi_format", spdk_bdev_get_dif_pi_format(bdev)); 690ebc227d9SJim Harris } 691ebc227d9SJim Harris } 692ebc227d9SJim Harris 693ebc227d9SJim Harris spdk_json_write_named_object_begin(w, "assigned_rate_limits"); 694ebc227d9SJim Harris spdk_bdev_get_qos_rate_limits(bdev, qos_limits); 695ebc227d9SJim Harris for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) { 696ebc227d9SJim Harris spdk_json_write_named_uint64(w, spdk_bdev_get_qos_rpc_type(i), qos_limits[i]); 697ebc227d9SJim Harris } 698ebc227d9SJim Harris spdk_json_write_object_end(w); 699ebc227d9SJim Harris 7004bb902a6SMike Gerdts spdk_json_write_named_bool(w, "claimed", 7014bb902a6SMike Gerdts (bdev->internal.claim_type != SPDK_BDEV_CLAIM_NONE)); 702a7eb6187SMike Gerdts if (bdev->internal.claim_type != SPDK_BDEV_CLAIM_NONE) { 703a7eb6187SMike Gerdts spdk_json_write_named_string(w, "claim_type", 704a7eb6187SMike Gerdts spdk_bdev_claim_get_name(bdev->internal.claim_type)); 705a7eb6187SMike Gerdts } 706ebc227d9SJim Harris 707ebc227d9SJim Harris spdk_json_write_named_bool(w, "zoned", bdev->zoned); 708ebc227d9SJim Harris if (bdev->zoned) { 709ebc227d9SJim Harris spdk_json_write_named_uint64(w, "zone_size", bdev->zone_size); 710ebc227d9SJim Harris spdk_json_write_named_uint64(w, "max_open_zones", bdev->max_open_zones); 711ebc227d9SJim Harris spdk_json_write_named_uint64(w, "optimal_open_zones", bdev->optimal_open_zones); 712ebc227d9SJim Harris } 713ebc227d9SJim Harris 714ebc227d9SJim Harris spdk_json_write_named_object_begin(w, "supported_io_types"); 7153886567dSAtul Malakar for (io_type = SPDK_BDEV_IO_TYPE_READ; io_type < SPDK_BDEV_NUM_IO_TYPES; ++io_type) { 7163886567dSAtul Malakar name = spdk_bdev_get_io_type_name(io_type); 7173886567dSAtul Malakar spdk_json_write_named_bool(w, name, spdk_bdev_io_type_supported(bdev, io_type)); 7183886567dSAtul Malakar } 719ebc227d9SJim Harris spdk_json_write_object_end(w); 720ebc227d9SJim Harris 7213185d3c9SAlexey Marchuk rc = spdk_bdev_get_memory_domains(bdev, NULL, 0); 7223185d3c9SAlexey Marchuk if (rc > 0) { 7233185d3c9SAlexey Marchuk domains = calloc(rc, sizeof(struct spdk_memory_domain *)); 7243185d3c9SAlexey Marchuk if (domains) { 7253185d3c9SAlexey Marchuk i = spdk_bdev_get_memory_domains(bdev, domains, rc); 7263185d3c9SAlexey Marchuk if (i == rc) { 7273185d3c9SAlexey Marchuk spdk_json_write_named_array_begin(w, "memory_domains"); 7283185d3c9SAlexey Marchuk for (i = 0; i < rc; i++) { 7293185d3c9SAlexey Marchuk spdk_json_write_object_begin(w); 7303185d3c9SAlexey Marchuk spdk_json_write_named_string(w, "dma_device_id", spdk_memory_domain_get_dma_device_id(domains[i])); 7313185d3c9SAlexey Marchuk spdk_json_write_named_int32(w, "dma_device_type", 7323185d3c9SAlexey Marchuk spdk_memory_domain_get_dma_device_type(domains[i])); 7333185d3c9SAlexey Marchuk spdk_json_write_object_end(w); 7343185d3c9SAlexey Marchuk } 7353185d3c9SAlexey Marchuk spdk_json_write_array_end(w); 7363185d3c9SAlexey Marchuk } else { 7373185d3c9SAlexey Marchuk SPDK_ERRLOG("Unexpected number of memory domains %d (should be %d)\n", i, rc); 7383185d3c9SAlexey Marchuk } 7393185d3c9SAlexey Marchuk 7403185d3c9SAlexey Marchuk free(domains); 7413185d3c9SAlexey Marchuk } else { 7423185d3c9SAlexey Marchuk SPDK_ERRLOG("Memory allocation failed\n"); 7433185d3c9SAlexey Marchuk } 7443185d3c9SAlexey Marchuk } 7453185d3c9SAlexey Marchuk 746ebc227d9SJim Harris spdk_json_write_named_object_begin(w, "driver_specific"); 747ebc227d9SJim Harris spdk_bdev_dump_info_json(bdev, w); 748ebc227d9SJim Harris spdk_json_write_object_end(w); 749ebc227d9SJim Harris 750ebc227d9SJim Harris spdk_json_write_object_end(w); 7510d29a988SShuhei Matsumoto 7520d29a988SShuhei Matsumoto return 0; 753ebc227d9SJim Harris } 754ebc227d9SJim Harris 755ebc227d9SJim Harris struct rpc_bdev_get_bdevs { 756ebc227d9SJim Harris char *name; 757fa649869SKonrad Sztyber uint64_t timeout; 758fa649869SKonrad Sztyber }; 759fa649869SKonrad Sztyber 760ebc227d9SJim Harris static void 761ebc227d9SJim Harris free_rpc_bdev_get_bdevs(struct rpc_bdev_get_bdevs *r) 762ebc227d9SJim Harris { 763ebc227d9SJim Harris free(r->name); 764ebc227d9SJim Harris } 765ebc227d9SJim Harris 766ebc227d9SJim Harris static const struct spdk_json_object_decoder rpc_bdev_get_bdevs_decoders[] = { 767ebc227d9SJim Harris {"name", offsetof(struct rpc_bdev_get_bdevs, name), spdk_json_decode_string, true}, 768fa649869SKonrad Sztyber {"timeout", offsetof(struct rpc_bdev_get_bdevs, timeout), spdk_json_decode_uint64, true}, 769ebc227d9SJim Harris }; 770ebc227d9SJim Harris 77138df3ad5SShuhei Matsumoto static void 77238df3ad5SShuhei Matsumoto rpc_bdev_get_bdev_cb(struct spdk_bdev_desc *desc, int rc, void *cb_arg) 773fa649869SKonrad Sztyber { 77438df3ad5SShuhei Matsumoto struct spdk_jsonrpc_request *request = cb_arg; 775fa649869SKonrad Sztyber struct spdk_json_write_ctx *w; 776fa649869SKonrad Sztyber 77738df3ad5SShuhei Matsumoto if (rc == 0) { 77838df3ad5SShuhei Matsumoto w = spdk_jsonrpc_begin_result(request); 779fa649869SKonrad Sztyber 780fa649869SKonrad Sztyber spdk_json_write_array_begin(w); 7810d29a988SShuhei Matsumoto rpc_dump_bdev_info(w, spdk_bdev_desc_get_bdev(desc)); 782fa649869SKonrad Sztyber spdk_json_write_array_end(w); 78338df3ad5SShuhei Matsumoto spdk_jsonrpc_end_result(request, w); 7840d29a988SShuhei Matsumoto 7850d29a988SShuhei Matsumoto spdk_bdev_close(desc); 78638df3ad5SShuhei Matsumoto } else { 78738df3ad5SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 788fa649869SKonrad Sztyber } 789fa649869SKonrad Sztyber } 790fa649869SKonrad Sztyber 791ebc227d9SJim Harris static void 792ebc227d9SJim Harris rpc_bdev_get_bdevs(struct spdk_jsonrpc_request *request, 793ebc227d9SJim Harris const struct spdk_json_val *params) 794ebc227d9SJim Harris { 795ebc227d9SJim Harris struct rpc_bdev_get_bdevs req = {}; 79638df3ad5SShuhei Matsumoto struct spdk_bdev_open_async_opts opts = {}; 797ebc227d9SJim Harris struct spdk_json_write_ctx *w; 7980d29a988SShuhei Matsumoto int rc; 799ebc227d9SJim Harris 800ebc227d9SJim Harris if (params && spdk_json_decode_object(params, rpc_bdev_get_bdevs_decoders, 801ebc227d9SJim Harris SPDK_COUNTOF(rpc_bdev_get_bdevs_decoders), 802ebc227d9SJim Harris &req)) { 803ebc227d9SJim Harris SPDK_ERRLOG("spdk_json_decode_object failed\n"); 804ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 805ebc227d9SJim Harris "spdk_json_decode_object failed"); 806ebc227d9SJim Harris free_rpc_bdev_get_bdevs(&req); 807ebc227d9SJim Harris return; 808ebc227d9SJim Harris } 809ebc227d9SJim Harris 810ebc227d9SJim Harris if (req.name) { 81138df3ad5SShuhei Matsumoto opts.size = sizeof(opts); 81238df3ad5SShuhei Matsumoto opts.timeout_ms = req.timeout; 81338df3ad5SShuhei Matsumoto 81438df3ad5SShuhei Matsumoto rc = spdk_bdev_open_async(req.name, false, dummy_bdev_event_cb, NULL, &opts, 81538df3ad5SShuhei Matsumoto rpc_bdev_get_bdev_cb, request); 8160d29a988SShuhei Matsumoto if (rc != 0) { 81738df3ad5SShuhei Matsumoto SPDK_ERRLOG("spdk_bdev_open_async failed for '%s': rc=%d\n", req.name, rc); 81838df3ad5SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 81938df3ad5SShuhei Matsumoto } 82038df3ad5SShuhei Matsumoto 821ebc227d9SJim Harris free_rpc_bdev_get_bdevs(&req); 822ebc227d9SJim Harris return; 823ebc227d9SJim Harris } 824fa649869SKonrad Sztyber 825fa649869SKonrad Sztyber free_rpc_bdev_get_bdevs(&req); 826fa649869SKonrad Sztyber 827ebc227d9SJim Harris w = spdk_jsonrpc_begin_result(request); 828ebc227d9SJim Harris spdk_json_write_array_begin(w); 829ebc227d9SJim Harris 8300d29a988SShuhei Matsumoto spdk_for_each_bdev(w, rpc_dump_bdev_info); 831ebc227d9SJim Harris 832ebc227d9SJim Harris spdk_json_write_array_end(w); 833ebc227d9SJim Harris 834ebc227d9SJim Harris spdk_jsonrpc_end_result(request, w); 835ebc227d9SJim Harris } 836ebc227d9SJim Harris SPDK_RPC_REGISTER("bdev_get_bdevs", rpc_bdev_get_bdevs, SPDK_RPC_RUNTIME) 837ebc227d9SJim Harris 838ebc227d9SJim Harris struct rpc_bdev_set_qd_sampling_period { 839ebc227d9SJim Harris char *name; 840ebc227d9SJim Harris uint64_t period; 841ebc227d9SJim Harris }; 842ebc227d9SJim Harris 843ebc227d9SJim Harris static void 844ebc227d9SJim Harris free_rpc_bdev_set_qd_sampling_period(struct rpc_bdev_set_qd_sampling_period *r) 845ebc227d9SJim Harris { 846ebc227d9SJim Harris free(r->name); 847ebc227d9SJim Harris } 848ebc227d9SJim Harris 849ebc227d9SJim Harris static const struct spdk_json_object_decoder 850ebc227d9SJim Harris rpc_bdev_set_qd_sampling_period_decoders[] = { 851ebc227d9SJim Harris {"name", offsetof(struct rpc_bdev_set_qd_sampling_period, name), spdk_json_decode_string}, 852ebc227d9SJim Harris {"period", offsetof(struct rpc_bdev_set_qd_sampling_period, period), spdk_json_decode_uint64}, 853ebc227d9SJim Harris }; 854ebc227d9SJim Harris 855ebc227d9SJim Harris static void 856ebc227d9SJim Harris rpc_bdev_set_qd_sampling_period(struct spdk_jsonrpc_request *request, 857ebc227d9SJim Harris const struct spdk_json_val *params) 858ebc227d9SJim Harris { 859ebc227d9SJim Harris struct rpc_bdev_set_qd_sampling_period req = {0}; 860f41248ffSShuhei Matsumoto struct spdk_bdev_desc *desc; 861f41248ffSShuhei Matsumoto int rc; 862ebc227d9SJim Harris 863ebc227d9SJim Harris if (spdk_json_decode_object(params, rpc_bdev_set_qd_sampling_period_decoders, 864ebc227d9SJim Harris SPDK_COUNTOF(rpc_bdev_set_qd_sampling_period_decoders), 865ebc227d9SJim Harris &req)) { 866ebc227d9SJim Harris SPDK_ERRLOG("spdk_json_decode_object failed\n"); 867ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 868ebc227d9SJim Harris "spdk_json_decode_object failed"); 869ebc227d9SJim Harris goto cleanup; 870ebc227d9SJim Harris } 871ebc227d9SJim Harris 872f41248ffSShuhei Matsumoto rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 873f41248ffSShuhei Matsumoto if (rc != 0) { 874f41248ffSShuhei Matsumoto SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 875f41248ffSShuhei Matsumoto spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 876ebc227d9SJim Harris goto cleanup; 877ebc227d9SJim Harris } 878ebc227d9SJim Harris 879f41248ffSShuhei Matsumoto spdk_bdev_set_qd_sampling_period(spdk_bdev_desc_get_bdev(desc), req.period); 880d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 881ebc227d9SJim Harris 882f41248ffSShuhei Matsumoto spdk_bdev_close(desc); 883f41248ffSShuhei Matsumoto 884ebc227d9SJim Harris cleanup: 885ebc227d9SJim Harris free_rpc_bdev_set_qd_sampling_period(&req); 886ebc227d9SJim Harris } 887ebc227d9SJim Harris SPDK_RPC_REGISTER("bdev_set_qd_sampling_period", 888ebc227d9SJim Harris rpc_bdev_set_qd_sampling_period, 889ebc227d9SJim Harris SPDK_RPC_RUNTIME) 890ebc227d9SJim Harris 891ebc227d9SJim Harris struct rpc_bdev_set_qos_limit { 892ebc227d9SJim Harris char *name; 893ebc227d9SJim Harris uint64_t limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES]; 894ebc227d9SJim Harris }; 895ebc227d9SJim Harris 896ebc227d9SJim Harris static void 897ebc227d9SJim Harris free_rpc_bdev_set_qos_limit(struct rpc_bdev_set_qos_limit *r) 898ebc227d9SJim Harris { 899ebc227d9SJim Harris free(r->name); 900ebc227d9SJim Harris } 901ebc227d9SJim Harris 902ebc227d9SJim Harris static const struct spdk_json_object_decoder rpc_bdev_set_qos_limit_decoders[] = { 903ebc227d9SJim Harris {"name", offsetof(struct rpc_bdev_set_qos_limit, name), spdk_json_decode_string}, 904ebc227d9SJim Harris { 905ebc227d9SJim Harris "rw_ios_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 906ebc227d9SJim Harris limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT]), 907ebc227d9SJim Harris spdk_json_decode_uint64, true 908ebc227d9SJim Harris }, 909ebc227d9SJim Harris { 910ebc227d9SJim Harris "rw_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 911ebc227d9SJim Harris limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT]), 912ebc227d9SJim Harris spdk_json_decode_uint64, true 913ebc227d9SJim Harris }, 914ebc227d9SJim Harris { 915ebc227d9SJim Harris "r_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 916ebc227d9SJim Harris limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT]), 917ebc227d9SJim Harris spdk_json_decode_uint64, true 918ebc227d9SJim Harris }, 919ebc227d9SJim Harris { 920ebc227d9SJim Harris "w_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 921ebc227d9SJim Harris limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT]), 922ebc227d9SJim Harris spdk_json_decode_uint64, true 923ebc227d9SJim Harris }, 924ebc227d9SJim Harris }; 925ebc227d9SJim Harris 926ebc227d9SJim Harris static void 927ebc227d9SJim Harris rpc_bdev_set_qos_limit_complete(void *cb_arg, int status) 928ebc227d9SJim Harris { 929ebc227d9SJim Harris struct spdk_jsonrpc_request *request = cb_arg; 930ebc227d9SJim Harris 931ebc227d9SJim Harris if (status != 0) { 932ebc227d9SJim Harris spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 933ebc227d9SJim Harris "Failed to configure rate limit: %s", 934ebc227d9SJim Harris spdk_strerror(-status)); 935ebc227d9SJim Harris return; 936ebc227d9SJim Harris } 937ebc227d9SJim Harris 938d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 939ebc227d9SJim Harris } 940ebc227d9SJim Harris 941ebc227d9SJim Harris static void 942ebc227d9SJim Harris rpc_bdev_set_qos_limit(struct spdk_jsonrpc_request *request, 943ebc227d9SJim Harris const struct spdk_json_val *params) 944ebc227d9SJim Harris { 945ebc227d9SJim Harris struct rpc_bdev_set_qos_limit req = {NULL, {UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX}}; 946f41248ffSShuhei Matsumoto struct spdk_bdev_desc *desc; 947f41248ffSShuhei Matsumoto int i, rc; 948ebc227d9SJim Harris 949ebc227d9SJim Harris if (spdk_json_decode_object(params, rpc_bdev_set_qos_limit_decoders, 950ebc227d9SJim Harris SPDK_COUNTOF(rpc_bdev_set_qos_limit_decoders), 951ebc227d9SJim Harris &req)) { 952ebc227d9SJim Harris SPDK_ERRLOG("spdk_json_decode_object failed\n"); 953ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 954ebc227d9SJim Harris "spdk_json_decode_object failed"); 955ebc227d9SJim Harris goto cleanup; 956ebc227d9SJim Harris } 957ebc227d9SJim Harris 958f41248ffSShuhei Matsumoto rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 959f41248ffSShuhei Matsumoto if (rc != 0) { 960f41248ffSShuhei Matsumoto SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 961f41248ffSShuhei Matsumoto spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 962ebc227d9SJim Harris goto cleanup; 963ebc227d9SJim Harris } 964ebc227d9SJim Harris 965ebc227d9SJim Harris for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) { 966ebc227d9SJim Harris if (req.limits[i] != UINT64_MAX) { 967ebc227d9SJim Harris break; 968ebc227d9SJim Harris } 969ebc227d9SJim Harris } 970ebc227d9SJim Harris if (i == SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES) { 971ebc227d9SJim Harris SPDK_ERRLOG("no rate limits specified\n"); 972f41248ffSShuhei Matsumoto spdk_bdev_close(desc); 973ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, -EINVAL, "No rate limits specified"); 974ebc227d9SJim Harris goto cleanup; 975ebc227d9SJim Harris } 976ebc227d9SJim Harris 977f41248ffSShuhei Matsumoto spdk_bdev_set_qos_rate_limits(spdk_bdev_desc_get_bdev(desc), req.limits, 978f41248ffSShuhei Matsumoto rpc_bdev_set_qos_limit_complete, request); 979f41248ffSShuhei Matsumoto 980f41248ffSShuhei Matsumoto spdk_bdev_close(desc); 981ebc227d9SJim Harris 982ebc227d9SJim Harris cleanup: 983ebc227d9SJim Harris free_rpc_bdev_set_qos_limit(&req); 984ebc227d9SJim Harris } 985ebc227d9SJim Harris 986ebc227d9SJim Harris SPDK_RPC_REGISTER("bdev_set_qos_limit", rpc_bdev_set_qos_limit, SPDK_RPC_RUNTIME) 987ebc227d9SJim Harris 988ebc227d9SJim Harris /* SPDK_RPC_ENABLE_BDEV_HISTOGRAM */ 989ebc227d9SJim Harris 990ebc227d9SJim Harris struct rpc_bdev_enable_histogram_request { 991ebc227d9SJim Harris char *name; 992ebc227d9SJim Harris bool enable; 993f3cef5e1SAtul Malakar char *opc; 994ebc227d9SJim Harris }; 995ebc227d9SJim Harris 996ebc227d9SJim Harris static void 997ebc227d9SJim Harris free_rpc_bdev_enable_histogram_request(struct rpc_bdev_enable_histogram_request *r) 998ebc227d9SJim Harris { 999ebc227d9SJim Harris free(r->name); 1000f3cef5e1SAtul Malakar free(r->opc); 1001ebc227d9SJim Harris } 1002ebc227d9SJim Harris 1003ebc227d9SJim Harris static const struct spdk_json_object_decoder rpc_bdev_enable_histogram_request_decoders[] = { 1004ebc227d9SJim Harris {"name", offsetof(struct rpc_bdev_enable_histogram_request, name), spdk_json_decode_string}, 1005ebc227d9SJim Harris {"enable", offsetof(struct rpc_bdev_enable_histogram_request, enable), spdk_json_decode_bool}, 1006f3cef5e1SAtul Malakar {"opc", offsetof(struct rpc_bdev_enable_histogram_request, opc), spdk_json_decode_string, true}, 1007ebc227d9SJim Harris }; 1008ebc227d9SJim Harris 1009ebc227d9SJim Harris static void 1010ebc227d9SJim Harris bdev_histogram_status_cb(void *cb_arg, int status) 1011ebc227d9SJim Harris { 1012ebc227d9SJim Harris struct spdk_jsonrpc_request *request = cb_arg; 1013ebc227d9SJim Harris 1014a6b0b5b0SShuhei Matsumoto if (status == 0) { 1015a6b0b5b0SShuhei Matsumoto spdk_jsonrpc_send_bool_response(request, true); 1016a6b0b5b0SShuhei Matsumoto } else { 1017a6b0b5b0SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, status, spdk_strerror(-status)); 1018a6b0b5b0SShuhei Matsumoto } 1019ebc227d9SJim Harris } 1020ebc227d9SJim Harris 1021ebc227d9SJim Harris static void 1022ebc227d9SJim Harris rpc_bdev_enable_histogram(struct spdk_jsonrpc_request *request, 1023ebc227d9SJim Harris const struct spdk_json_val *params) 1024ebc227d9SJim Harris { 1025ebc227d9SJim Harris struct rpc_bdev_enable_histogram_request req = {NULL}; 1026f41248ffSShuhei Matsumoto struct spdk_bdev_desc *desc; 1027f41248ffSShuhei Matsumoto int rc; 1028f3cef5e1SAtul Malakar struct spdk_bdev_enable_histogram_opts opts = {}; 1029f3cef5e1SAtul Malakar int io_type = 0; 1030ebc227d9SJim Harris 1031ebc227d9SJim Harris if (spdk_json_decode_object(params, rpc_bdev_enable_histogram_request_decoders, 1032ebc227d9SJim Harris SPDK_COUNTOF(rpc_bdev_enable_histogram_request_decoders), 1033ebc227d9SJim Harris &req)) { 1034ebc227d9SJim Harris SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1035ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1036ebc227d9SJim Harris "spdk_json_decode_object failed"); 1037ebc227d9SJim Harris goto cleanup; 1038ebc227d9SJim Harris } 1039ebc227d9SJim Harris 1040f41248ffSShuhei Matsumoto rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 1041f41248ffSShuhei Matsumoto if (rc != 0) { 1042f41248ffSShuhei Matsumoto spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1043ebc227d9SJim Harris goto cleanup; 1044ebc227d9SJim Harris } 1045ebc227d9SJim Harris 1046f3cef5e1SAtul Malakar spdk_bdev_enable_histogram_opts_init(&opts, sizeof(opts)); 1047f3cef5e1SAtul Malakar 1048f3cef5e1SAtul Malakar if (req.opc != NULL) { 1049f3cef5e1SAtul Malakar io_type = spdk_bdev_get_io_type(req.opc); 1050f3cef5e1SAtul Malakar if (io_type == -1) { 1051f3cef5e1SAtul Malakar SPDK_ERRLOG("Invalid IO type\n"); 1052f3cef5e1SAtul Malakar spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1053f3cef5e1SAtul Malakar "Invalid Io type"); 1054f3cef5e1SAtul Malakar goto cleanup; 1055f3cef5e1SAtul Malakar } 1056f3cef5e1SAtul Malakar opts.io_type = (uint8_t) io_type; 1057f3cef5e1SAtul Malakar } 1058f3cef5e1SAtul Malakar 1059f3cef5e1SAtul Malakar spdk_bdev_histogram_enable_ext(spdk_bdev_desc_get_bdev(desc), bdev_histogram_status_cb, 1060f3cef5e1SAtul Malakar request, req.enable, &opts); 1061f41248ffSShuhei Matsumoto 1062f41248ffSShuhei Matsumoto spdk_bdev_close(desc); 1063ebc227d9SJim Harris 1064ebc227d9SJim Harris cleanup: 1065ebc227d9SJim Harris free_rpc_bdev_enable_histogram_request(&req); 1066ebc227d9SJim Harris } 1067ebc227d9SJim Harris 1068ebc227d9SJim Harris SPDK_RPC_REGISTER("bdev_enable_histogram", rpc_bdev_enable_histogram, SPDK_RPC_RUNTIME) 1069ebc227d9SJim Harris 1070ebc227d9SJim Harris /* SPDK_RPC_GET_BDEV_HISTOGRAM */ 1071ebc227d9SJim Harris 1072ebc227d9SJim Harris struct rpc_bdev_get_histogram_request { 1073ebc227d9SJim Harris char *name; 1074ebc227d9SJim Harris }; 1075ebc227d9SJim Harris 1076ebc227d9SJim Harris static const struct spdk_json_object_decoder rpc_bdev_get_histogram_request_decoders[] = { 1077ebc227d9SJim Harris {"name", offsetof(struct rpc_bdev_get_histogram_request, name), spdk_json_decode_string} 1078ebc227d9SJim Harris }; 1079ebc227d9SJim Harris 1080ebc227d9SJim Harris static void 1081ebc227d9SJim Harris free_rpc_bdev_get_histogram_request(struct rpc_bdev_get_histogram_request *r) 1082ebc227d9SJim Harris { 1083ebc227d9SJim Harris free(r->name); 1084ebc227d9SJim Harris } 1085ebc227d9SJim Harris 1086ebc227d9SJim Harris static void 1087ebc227d9SJim Harris _rpc_bdev_histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram) 1088ebc227d9SJim Harris { 1089ebc227d9SJim Harris struct spdk_jsonrpc_request *request = cb_arg; 1090ebc227d9SJim Harris struct spdk_json_write_ctx *w; 1091ebc227d9SJim Harris int rc; 1092ebc227d9SJim Harris char *encoded_histogram; 1093ebc227d9SJim Harris size_t src_len, dst_len; 1094ebc227d9SJim Harris 1095ebc227d9SJim Harris 1096ebc227d9SJim Harris if (status != 0) { 1097ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1098ebc227d9SJim Harris spdk_strerror(-status)); 1099ebc227d9SJim Harris goto invalid; 1100ebc227d9SJim Harris } 1101ebc227d9SJim Harris 1102ebc227d9SJim Harris src_len = SPDK_HISTOGRAM_NUM_BUCKETS(histogram) * sizeof(uint64_t); 1103ebc227d9SJim Harris dst_len = spdk_base64_get_encoded_strlen(src_len) + 1; 1104ebc227d9SJim Harris 1105ebc227d9SJim Harris encoded_histogram = malloc(dst_len); 1106ebc227d9SJim Harris if (encoded_histogram == NULL) { 1107ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1108ebc227d9SJim Harris spdk_strerror(ENOMEM)); 1109ebc227d9SJim Harris goto invalid; 1110ebc227d9SJim Harris } 1111ebc227d9SJim Harris 1112ebc227d9SJim Harris rc = spdk_base64_encode(encoded_histogram, histogram->bucket, src_len); 1113ebc227d9SJim Harris if (rc != 0) { 1114ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1115ebc227d9SJim Harris spdk_strerror(-rc)); 1116ebc227d9SJim Harris goto free_encoded_histogram; 1117ebc227d9SJim Harris } 1118ebc227d9SJim Harris 1119ebc227d9SJim Harris w = spdk_jsonrpc_begin_result(request); 1120ebc227d9SJim Harris spdk_json_write_object_begin(w); 1121ebc227d9SJim Harris spdk_json_write_named_string(w, "histogram", encoded_histogram); 1122ebc227d9SJim Harris spdk_json_write_named_int64(w, "bucket_shift", histogram->bucket_shift); 1123ebc227d9SJim Harris spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz()); 1124ebc227d9SJim Harris spdk_json_write_object_end(w); 1125ebc227d9SJim Harris spdk_jsonrpc_end_result(request, w); 1126ebc227d9SJim Harris 1127ebc227d9SJim Harris free_encoded_histogram: 1128ebc227d9SJim Harris free(encoded_histogram); 1129ebc227d9SJim Harris invalid: 1130ebc227d9SJim Harris spdk_histogram_data_free(histogram); 1131ebc227d9SJim Harris } 1132ebc227d9SJim Harris 1133ebc227d9SJim Harris static void 1134ebc227d9SJim Harris rpc_bdev_get_histogram(struct spdk_jsonrpc_request *request, 1135ebc227d9SJim Harris const struct spdk_json_val *params) 1136ebc227d9SJim Harris { 1137ebc227d9SJim Harris struct rpc_bdev_get_histogram_request req = {NULL}; 1138ebc227d9SJim Harris struct spdk_histogram_data *histogram; 1139f41248ffSShuhei Matsumoto struct spdk_bdev_desc *desc; 1140f41248ffSShuhei Matsumoto int rc; 1141ebc227d9SJim Harris 1142ebc227d9SJim Harris if (spdk_json_decode_object(params, rpc_bdev_get_histogram_request_decoders, 1143ebc227d9SJim Harris SPDK_COUNTOF(rpc_bdev_get_histogram_request_decoders), 1144ebc227d9SJim Harris &req)) { 1145ebc227d9SJim Harris SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1146ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1147ebc227d9SJim Harris "spdk_json_decode_object failed"); 1148ebc227d9SJim Harris goto cleanup; 1149ebc227d9SJim Harris } 1150ebc227d9SJim Harris 1151f41248ffSShuhei Matsumoto rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 1152f41248ffSShuhei Matsumoto if (rc != 0) { 1153f41248ffSShuhei Matsumoto spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1154ebc227d9SJim Harris goto cleanup; 1155ebc227d9SJim Harris } 1156ebc227d9SJim Harris 1157ebc227d9SJim Harris histogram = spdk_histogram_data_alloc(); 1158ebc227d9SJim Harris if (histogram == NULL) { 1159f41248ffSShuhei Matsumoto spdk_bdev_close(desc); 1160ebc227d9SJim Harris spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1161ebc227d9SJim Harris goto cleanup; 1162ebc227d9SJim Harris } 1163ebc227d9SJim Harris 1164f41248ffSShuhei Matsumoto spdk_bdev_histogram_get(spdk_bdev_desc_get_bdev(desc), histogram, 1165f41248ffSShuhei Matsumoto _rpc_bdev_histogram_data_cb, request); 1166f41248ffSShuhei Matsumoto 1167f41248ffSShuhei Matsumoto spdk_bdev_close(desc); 1168ebc227d9SJim Harris 1169ebc227d9SJim Harris cleanup: 1170ebc227d9SJim Harris free_rpc_bdev_get_histogram_request(&req); 1171ebc227d9SJim Harris } 1172ebc227d9SJim Harris 1173ebc227d9SJim Harris SPDK_RPC_REGISTER("bdev_get_histogram", rpc_bdev_get_histogram, SPDK_RPC_RUNTIME) 1174