xref: /spdk/lib/bdev/bdev_rpc.c (revision 63e0c25dad5f2793fdb9ff9b1e6ce516673dc6aa)
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