xref: /spdk/lib/bdev/bdev_rpc.c (revision 1299439f3d96af5edf21bd1613c50ef2719b67dc)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/bdev.h"
35 
36 #include "spdk/env.h"
37 #include "spdk/rpc.h"
38 #include "spdk/util.h"
39 #include "spdk/string.h"
40 #include "spdk/base64.h"
41 #include "spdk/bdev_module.h"
42 
43 #include "spdk/log.h"
44 
45 struct spdk_rpc_set_bdev_opts {
46 	uint32_t bdev_io_pool_size;
47 	uint32_t bdev_io_cache_size;
48 	bool bdev_auto_examine;
49 	uint32_t small_buf_pool_size;
50 	uint32_t large_buf_pool_size;
51 };
52 
53 static const struct spdk_json_object_decoder rpc_set_bdev_opts_decoders[] = {
54 	{"bdev_io_pool_size", offsetof(struct spdk_rpc_set_bdev_opts, bdev_io_pool_size), spdk_json_decode_uint32, true},
55 	{"bdev_io_cache_size", offsetof(struct spdk_rpc_set_bdev_opts, bdev_io_cache_size), spdk_json_decode_uint32, true},
56 	{"bdev_auto_examine", offsetof(struct spdk_rpc_set_bdev_opts, bdev_auto_examine), spdk_json_decode_bool, true},
57 	{"small_buf_pool_size", offsetof(struct spdk_rpc_set_bdev_opts, small_buf_pool_size), spdk_json_decode_uint32, true},
58 	{"large_buf_pool_size", offsetof(struct spdk_rpc_set_bdev_opts, large_buf_pool_size), spdk_json_decode_uint32, true},
59 };
60 
61 static void
62 rpc_bdev_set_options(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
63 {
64 	struct spdk_rpc_set_bdev_opts rpc_opts;
65 	struct spdk_bdev_opts bdev_opts;
66 	int rc;
67 
68 	rpc_opts.bdev_io_pool_size = UINT32_MAX;
69 	rpc_opts.bdev_io_cache_size = UINT32_MAX;
70 	rpc_opts.small_buf_pool_size = UINT32_MAX;
71 	rpc_opts.large_buf_pool_size = UINT32_MAX;
72 	rpc_opts.bdev_auto_examine = true;
73 
74 	if (params != NULL) {
75 		if (spdk_json_decode_object(params, rpc_set_bdev_opts_decoders,
76 					    SPDK_COUNTOF(rpc_set_bdev_opts_decoders), &rpc_opts)) {
77 			SPDK_ERRLOG("spdk_json_decode_object() failed\n");
78 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
79 							 "Invalid parameters");
80 			return;
81 		}
82 	}
83 
84 	spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts));
85 	if (rpc_opts.bdev_io_pool_size != UINT32_MAX) {
86 		bdev_opts.bdev_io_pool_size = rpc_opts.bdev_io_pool_size;
87 	}
88 	if (rpc_opts.bdev_io_cache_size != UINT32_MAX) {
89 		bdev_opts.bdev_io_cache_size = rpc_opts.bdev_io_cache_size;
90 	}
91 	bdev_opts.bdev_auto_examine = rpc_opts.bdev_auto_examine;
92 	if (rpc_opts.small_buf_pool_size != UINT32_MAX) {
93 		bdev_opts.small_buf_pool_size = rpc_opts.small_buf_pool_size;
94 	}
95 	if (rpc_opts.large_buf_pool_size != UINT32_MAX) {
96 		bdev_opts.large_buf_pool_size = rpc_opts.large_buf_pool_size;
97 	}
98 
99 	rc = spdk_bdev_set_opts(&bdev_opts);
100 
101 	if (rc != 0) {
102 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
103 						     "Pool size %" PRIu32 " too small for cache size %" PRIu32,
104 						     bdev_opts.bdev_io_pool_size, bdev_opts.bdev_io_cache_size);
105 		return;
106 	}
107 
108 	spdk_jsonrpc_send_bool_response(request, true);
109 }
110 SPDK_RPC_REGISTER("bdev_set_options", rpc_bdev_set_options, SPDK_RPC_STARTUP)
111 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_options, set_bdev_options)
112 
113 static void
114 rpc_bdev_wait_for_examine_cpl(void *arg)
115 {
116 	struct spdk_jsonrpc_request *request = arg;
117 
118 	spdk_jsonrpc_send_bool_response(request, true);
119 }
120 
121 static void
122 rpc_bdev_wait_for_examine(struct spdk_jsonrpc_request *request,
123 			  const struct spdk_json_val *params)
124 {
125 	int rc;
126 
127 	if (params != NULL) {
128 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
129 						 "bdev_wait_for_examine requires no parameters");
130 		return;
131 	}
132 
133 	rc = spdk_bdev_wait_for_examine(rpc_bdev_wait_for_examine_cpl, request);
134 	if (rc != 0) {
135 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
136 	}
137 }
138 SPDK_RPC_REGISTER("bdev_wait_for_examine", rpc_bdev_wait_for_examine, SPDK_RPC_RUNTIME)
139 
140 struct rpc_bdev_examine {
141 	char *name;
142 };
143 
144 static void
145 free_rpc_bdev_examine(struct rpc_bdev_examine *r)
146 {
147 	free(r->name);
148 }
149 
150 static const struct spdk_json_object_decoder rpc_examine_bdev_decoders[] = {
151 	{"name", offsetof(struct rpc_bdev_examine, name), spdk_json_decode_string},
152 };
153 
154 static void
155 rpc_bdev_examine_bdev(struct spdk_jsonrpc_request *request,
156 		      const struct spdk_json_val *params)
157 {
158 	struct rpc_bdev_examine req = {NULL};
159 	int rc;
160 
161 	if (spdk_json_decode_object(params, rpc_examine_bdev_decoders,
162 				    SPDK_COUNTOF(rpc_examine_bdev_decoders),
163 				    &req)) {
164 		SPDK_ERRLOG("spdk_json_decode_object() failed\n");
165 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
166 						 "spdk_json_decode_object failed");
167 		goto cleanup;
168 	}
169 
170 	rc = spdk_bdev_examine(req.name);
171 	if (rc != 0) {
172 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
173 		goto cleanup;
174 	}
175 
176 	spdk_jsonrpc_send_bool_response(request, true);
177 
178 cleanup:
179 	free_rpc_bdev_examine(&req);
180 }
181 SPDK_RPC_REGISTER("bdev_examine", rpc_bdev_examine_bdev, SPDK_RPC_RUNTIME)
182 
183 struct rpc_bdev_get_iostat_ctx {
184 	int bdev_count;
185 	struct spdk_jsonrpc_request *request;
186 	struct spdk_json_write_ctx *w;
187 };
188 
189 static void
190 rpc_bdev_get_iostat_cb(struct spdk_bdev *bdev,
191 		       struct spdk_bdev_io_stat *stat, void *cb_arg, int rc)
192 {
193 	struct rpc_bdev_get_iostat_ctx *ctx = cb_arg;
194 	struct spdk_json_write_ctx *w = ctx->w;
195 	const char *bdev_name;
196 
197 	if (rc != 0) {
198 		goto done;
199 	}
200 
201 	bdev_name = spdk_bdev_get_name(bdev);
202 	if (bdev_name != NULL) {
203 		spdk_json_write_object_begin(w);
204 
205 		spdk_json_write_named_string(w, "name", bdev_name);
206 
207 		spdk_json_write_named_uint64(w, "bytes_read", stat->bytes_read);
208 
209 		spdk_json_write_named_uint64(w, "num_read_ops", stat->num_read_ops);
210 
211 		spdk_json_write_named_uint64(w, "bytes_written", stat->bytes_written);
212 
213 		spdk_json_write_named_uint64(w, "num_write_ops", stat->num_write_ops);
214 
215 		spdk_json_write_named_uint64(w, "bytes_unmapped", stat->bytes_unmapped);
216 
217 		spdk_json_write_named_uint64(w, "num_unmap_ops", stat->num_unmap_ops);
218 
219 		spdk_json_write_named_uint64(w, "read_latency_ticks", stat->read_latency_ticks);
220 
221 		spdk_json_write_named_uint64(w, "write_latency_ticks", stat->write_latency_ticks);
222 
223 		spdk_json_write_named_uint64(w, "unmap_latency_ticks", stat->unmap_latency_ticks);
224 
225 		if (spdk_bdev_get_qd_sampling_period(bdev)) {
226 			spdk_json_write_named_uint64(w, "queue_depth_polling_period",
227 						     spdk_bdev_get_qd_sampling_period(bdev));
228 
229 			spdk_json_write_named_uint64(w, "queue_depth", spdk_bdev_get_qd(bdev));
230 
231 			spdk_json_write_named_uint64(w, "io_time", spdk_bdev_get_io_time(bdev));
232 
233 			spdk_json_write_named_uint64(w, "weighted_io_time",
234 						     spdk_bdev_get_weighted_io_time(bdev));
235 		}
236 
237 		spdk_json_write_object_end(w);
238 	}
239 
240 done:
241 	free(stat);
242 	if (--ctx->bdev_count == 0) {
243 		spdk_json_write_array_end(ctx->w);
244 		spdk_json_write_object_end(w);
245 		spdk_jsonrpc_end_result(ctx->request, ctx->w);
246 		free(ctx);
247 	}
248 }
249 
250 struct rpc_bdev_get_iostat {
251 	char *name;
252 };
253 
254 static void
255 free_rpc_bdev_get_iostat(struct rpc_bdev_get_iostat *r)
256 {
257 	free(r->name);
258 }
259 
260 static const struct spdk_json_object_decoder rpc_bdev_get_iostat_decoders[] = {
261 	{"name", offsetof(struct rpc_bdev_get_iostat, name), spdk_json_decode_string, true},
262 };
263 
264 static void
265 rpc_bdev_get_iostat(struct spdk_jsonrpc_request *request,
266 		    const struct spdk_json_val *params)
267 {
268 	struct rpc_bdev_get_iostat req = {};
269 	struct spdk_bdev *bdev = NULL;
270 	struct spdk_json_write_ctx *w;
271 	struct spdk_bdev_io_stat *stat;
272 	struct rpc_bdev_get_iostat_ctx *ctx;
273 
274 	if (params != NULL) {
275 		if (spdk_json_decode_object(params, rpc_bdev_get_iostat_decoders,
276 					    SPDK_COUNTOF(rpc_bdev_get_iostat_decoders),
277 					    &req)) {
278 			SPDK_ERRLOG("spdk_json_decode_object failed\n");
279 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
280 							 "spdk_json_decode_object failed");
281 			free_rpc_bdev_get_iostat(&req);
282 			return;
283 		}
284 
285 		if (req.name) {
286 			bdev = spdk_bdev_get_by_name(req.name);
287 			if (bdev == NULL) {
288 				SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
289 				spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
290 				free_rpc_bdev_get_iostat(&req);
291 				return;
292 			}
293 		}
294 	}
295 
296 	free_rpc_bdev_get_iostat(&req);
297 
298 	ctx = calloc(1, sizeof(struct rpc_bdev_get_iostat_ctx));
299 	if (ctx == NULL) {
300 		SPDK_ERRLOG("Failed to allocate rpc_bdev_get_iostat_ctx struct\n");
301 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
302 		return;
303 	}
304 
305 	w = spdk_jsonrpc_begin_result(request);
306 	/*
307 	 * Increment initial bdev_count so that it will never reach 0 in the middle
308 	 * of iterating.
309 	 */
310 	ctx->bdev_count++;
311 	ctx->request = request;
312 	ctx->w = w;
313 
314 
315 	spdk_json_write_object_begin(w);
316 	spdk_json_write_named_uint64(w, "tick_rate", spdk_get_ticks_hz());
317 	spdk_json_write_named_uint64(w, "ticks", spdk_get_ticks());
318 
319 	spdk_json_write_named_array_begin(w, "bdevs");
320 
321 	if (bdev != NULL) {
322 		stat = calloc(1, sizeof(struct spdk_bdev_io_stat));
323 		if (stat == NULL) {
324 			SPDK_ERRLOG("Failed to allocate rpc_bdev_get_iostat_ctx struct\n");
325 		} else {
326 			ctx->bdev_count++;
327 			spdk_bdev_get_device_stat(bdev, stat, rpc_bdev_get_iostat_cb, ctx);
328 		}
329 	} else {
330 		for (bdev = spdk_bdev_first(); bdev != NULL; bdev = spdk_bdev_next(bdev)) {
331 			stat = calloc(1, sizeof(struct spdk_bdev_io_stat));
332 			if (stat == NULL) {
333 				SPDK_ERRLOG("Failed to allocate spdk_bdev_io_stat struct\n");
334 				break;
335 			}
336 			ctx->bdev_count++;
337 			spdk_bdev_get_device_stat(bdev, stat, rpc_bdev_get_iostat_cb, ctx);
338 		}
339 	}
340 
341 	if (--ctx->bdev_count == 0) {
342 		spdk_json_write_array_end(w);
343 		spdk_json_write_object_end(w);
344 		spdk_jsonrpc_end_result(request, w);
345 		free(ctx);
346 	}
347 }
348 SPDK_RPC_REGISTER("bdev_get_iostat", rpc_bdev_get_iostat, SPDK_RPC_RUNTIME)
349 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_iostat, get_bdevs_iostat)
350 
351 static void
352 rpc_dump_bdev_info(struct spdk_json_write_ctx *w,
353 		   struct spdk_bdev *bdev)
354 {
355 	struct spdk_bdev_alias *tmp;
356 	uint64_t qos_limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES];
357 	int i;
358 
359 	spdk_json_write_object_begin(w);
360 
361 	spdk_json_write_named_string(w, "name", spdk_bdev_get_name(bdev));
362 
363 	spdk_json_write_named_array_begin(w, "aliases");
364 
365 	TAILQ_FOREACH(tmp, spdk_bdev_get_aliases(bdev), tailq) {
366 		spdk_json_write_string(w, tmp->alias.name);
367 	}
368 
369 	spdk_json_write_array_end(w);
370 
371 	spdk_json_write_named_string(w, "product_name", spdk_bdev_get_product_name(bdev));
372 
373 	spdk_json_write_named_uint32(w, "block_size", spdk_bdev_get_block_size(bdev));
374 
375 	spdk_json_write_named_uint64(w, "num_blocks", spdk_bdev_get_num_blocks(bdev));
376 
377 	if (!spdk_mem_all_zero(&bdev->uuid, sizeof(bdev->uuid))) {
378 		char uuid_str[SPDK_UUID_STRING_LEN];
379 
380 		spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid);
381 		spdk_json_write_named_string(w, "uuid", uuid_str);
382 	}
383 
384 	if (spdk_bdev_get_md_size(bdev) != 0) {
385 		spdk_json_write_named_uint32(w, "md_size", spdk_bdev_get_md_size(bdev));
386 		spdk_json_write_named_bool(w, "md_interleave", spdk_bdev_is_md_interleaved(bdev));
387 		spdk_json_write_named_uint32(w, "dif_type", spdk_bdev_get_dif_type(bdev));
388 		if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) {
389 			spdk_json_write_named_bool(w, "dif_is_head_of_md", spdk_bdev_is_dif_head_of_md(bdev));
390 			spdk_json_write_named_object_begin(w, "enabled_dif_check_types");
391 			spdk_json_write_named_bool(w, "reftag",
392 						   spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG));
393 			spdk_json_write_named_bool(w, "apptag",
394 						   spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_APPTAG));
395 			spdk_json_write_named_bool(w, "guard",
396 						   spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD));
397 			spdk_json_write_object_end(w);
398 		}
399 	}
400 
401 	spdk_json_write_named_object_begin(w, "assigned_rate_limits");
402 	spdk_bdev_get_qos_rate_limits(bdev, qos_limits);
403 	for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) {
404 		spdk_json_write_named_uint64(w, spdk_bdev_get_qos_rpc_type(i), qos_limits[i]);
405 	}
406 	spdk_json_write_object_end(w);
407 
408 	spdk_json_write_named_bool(w, "claimed", (bdev->internal.claim_module != NULL));
409 
410 	spdk_json_write_named_bool(w, "zoned", bdev->zoned);
411 	if (bdev->zoned) {
412 		spdk_json_write_named_uint64(w, "zone_size", bdev->zone_size);
413 		spdk_json_write_named_uint64(w, "max_open_zones", bdev->max_open_zones);
414 		spdk_json_write_named_uint64(w, "optimal_open_zones", bdev->optimal_open_zones);
415 	}
416 
417 	spdk_json_write_named_object_begin(w, "supported_io_types");
418 	spdk_json_write_named_bool(w, "read",
419 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_READ));
420 	spdk_json_write_named_bool(w, "write",
421 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE));
422 	spdk_json_write_named_bool(w, "unmap",
423 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP));
424 	spdk_json_write_named_bool(w, "write_zeroes",
425 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE_ZEROES));
426 	spdk_json_write_named_bool(w, "flush",
427 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_FLUSH));
428 	spdk_json_write_named_bool(w, "reset",
429 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_RESET));
430 	spdk_json_write_named_bool(w, "nvme_admin",
431 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_ADMIN));
432 	spdk_json_write_named_bool(w, "nvme_io",
433 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_IO));
434 	spdk_json_write_object_end(w);
435 
436 	spdk_json_write_named_object_begin(w, "driver_specific");
437 	spdk_bdev_dump_info_json(bdev, w);
438 	spdk_json_write_object_end(w);
439 
440 	spdk_json_write_object_end(w);
441 }
442 
443 struct rpc_bdev_get_bdevs {
444 	char		*name;
445 	uint64_t	timeout;
446 };
447 
448 struct rpc_bdev_get_bdevs_ctx {
449 	struct rpc_bdev_get_bdevs	rpc;
450 	struct spdk_jsonrpc_request	*request;
451 	struct spdk_poller		*poller;
452 	uint64_t			timeout_ticks;
453 };
454 
455 static void
456 free_rpc_bdev_get_bdevs(struct rpc_bdev_get_bdevs *r)
457 {
458 	free(r->name);
459 }
460 
461 static const struct spdk_json_object_decoder rpc_bdev_get_bdevs_decoders[] = {
462 	{"name", offsetof(struct rpc_bdev_get_bdevs, name), spdk_json_decode_string, true},
463 	{"timeout", offsetof(struct rpc_bdev_get_bdevs, timeout), spdk_json_decode_uint64, true},
464 };
465 
466 static int
467 get_bdevs_poller(void *_ctx)
468 {
469 	struct rpc_bdev_get_bdevs_ctx *ctx = _ctx;
470 	struct spdk_json_write_ctx *w;
471 	struct spdk_bdev *bdev;
472 
473 	bdev = spdk_bdev_get_by_name(ctx->rpc.name);
474 	if (bdev == NULL && spdk_get_ticks() < ctx->timeout_ticks) {
475 		return SPDK_POLLER_BUSY;
476 	}
477 
478 	if (bdev == NULL) {
479 		SPDK_ERRLOG("Timed out while waiting for bdev '%s' to appear\n", ctx->rpc.name);
480 		spdk_jsonrpc_send_error_response(ctx->request, -ENODEV, spdk_strerror(ENODEV));
481 	} else {
482 		w = spdk_jsonrpc_begin_result(ctx->request);
483 		spdk_json_write_array_begin(w);
484 		rpc_dump_bdev_info(w, bdev);
485 		spdk_json_write_array_end(w);
486 		spdk_jsonrpc_end_result(ctx->request, w);
487 	}
488 
489 	spdk_poller_unregister(&ctx->poller);
490 	free_rpc_bdev_get_bdevs(&ctx->rpc);
491 	free(ctx);
492 
493 	return SPDK_POLLER_BUSY;
494 }
495 
496 static void
497 rpc_bdev_get_bdevs(struct spdk_jsonrpc_request *request,
498 		   const struct spdk_json_val *params)
499 {
500 	struct rpc_bdev_get_bdevs req = {};
501 	struct rpc_bdev_get_bdevs_ctx *ctx;
502 	struct spdk_json_write_ctx *w;
503 	struct spdk_bdev *bdev = NULL;
504 
505 	if (params && spdk_json_decode_object(params, rpc_bdev_get_bdevs_decoders,
506 					      SPDK_COUNTOF(rpc_bdev_get_bdevs_decoders),
507 					      &req)) {
508 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
509 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
510 						 "spdk_json_decode_object failed");
511 		free_rpc_bdev_get_bdevs(&req);
512 		return;
513 	}
514 
515 	if (req.name) {
516 		bdev = spdk_bdev_get_by_name(req.name);
517 		if (bdev == NULL) {
518 			if (req.timeout == 0) {
519 				SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
520 				spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
521 				free_rpc_bdev_get_bdevs(&req);
522 				return;
523 			}
524 
525 			ctx = calloc(1, sizeof(*ctx));
526 			if (ctx == NULL) {
527 				SPDK_ERRLOG("Failed to allocate bdev_get_bdevs context\n");
528 				spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
529 				free_rpc_bdev_get_bdevs(&req);
530 				return;
531 			}
532 
533 			ctx->poller = SPDK_POLLER_REGISTER(get_bdevs_poller, ctx, 10 * 1000);
534 			if (ctx->poller == NULL) {
535 				SPDK_ERRLOG("Failed to register bdev_get_bdevs poller\n");
536 				spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
537 				free_rpc_bdev_get_bdevs(&req);
538 				free(ctx);
539 				return;
540 			}
541 
542 			memcpy(&ctx->rpc, &req, sizeof(req));
543 			ctx->timeout_ticks = spdk_get_ticks() + req.timeout *
544 					     spdk_get_ticks_hz() / 1000ull;
545 			ctx->request = request;
546 			return;
547 		}
548 	}
549 
550 	free_rpc_bdev_get_bdevs(&req);
551 	w = spdk_jsonrpc_begin_result(request);
552 	spdk_json_write_array_begin(w);
553 
554 	if (bdev != NULL) {
555 		rpc_dump_bdev_info(w, bdev);
556 	} else {
557 		for (bdev = spdk_bdev_first(); bdev != NULL; bdev = spdk_bdev_next(bdev)) {
558 			rpc_dump_bdev_info(w, bdev);
559 		}
560 	}
561 
562 	spdk_json_write_array_end(w);
563 
564 	spdk_jsonrpc_end_result(request, w);
565 }
566 SPDK_RPC_REGISTER("bdev_get_bdevs", rpc_bdev_get_bdevs, SPDK_RPC_RUNTIME)
567 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_bdevs, get_bdevs)
568 
569 struct rpc_bdev_set_qd_sampling_period {
570 	char *name;
571 	uint64_t period;
572 };
573 
574 static void
575 free_rpc_bdev_set_qd_sampling_period(struct rpc_bdev_set_qd_sampling_period *r)
576 {
577 	free(r->name);
578 }
579 
580 static const struct spdk_json_object_decoder
581 	rpc_bdev_set_qd_sampling_period_decoders[] = {
582 	{"name", offsetof(struct rpc_bdev_set_qd_sampling_period, name), spdk_json_decode_string},
583 	{"period", offsetof(struct rpc_bdev_set_qd_sampling_period, period), spdk_json_decode_uint64},
584 };
585 
586 static void
587 rpc_bdev_set_qd_sampling_period(struct spdk_jsonrpc_request *request,
588 				const struct spdk_json_val *params)
589 {
590 	struct rpc_bdev_set_qd_sampling_period req = {0};
591 	struct spdk_bdev *bdev;
592 
593 	if (spdk_json_decode_object(params, rpc_bdev_set_qd_sampling_period_decoders,
594 				    SPDK_COUNTOF(rpc_bdev_set_qd_sampling_period_decoders),
595 				    &req)) {
596 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
597 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
598 						 "spdk_json_decode_object failed");
599 		goto cleanup;
600 	}
601 
602 	bdev = spdk_bdev_get_by_name(req.name);
603 	if (bdev == NULL) {
604 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
605 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
606 		goto cleanup;
607 	}
608 
609 	spdk_bdev_set_qd_sampling_period(bdev, req.period);
610 	spdk_jsonrpc_send_bool_response(request, true);
611 
612 cleanup:
613 	free_rpc_bdev_set_qd_sampling_period(&req);
614 }
615 SPDK_RPC_REGISTER("bdev_set_qd_sampling_period",
616 		  rpc_bdev_set_qd_sampling_period,
617 		  SPDK_RPC_RUNTIME)
618 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_qd_sampling_period,
619 				   set_bdev_qd_sampling_period)
620 
621 struct rpc_bdev_set_qos_limit {
622 	char		*name;
623 	uint64_t	limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES];
624 };
625 
626 static void
627 free_rpc_bdev_set_qos_limit(struct rpc_bdev_set_qos_limit *r)
628 {
629 	free(r->name);
630 }
631 
632 static const struct spdk_json_object_decoder rpc_bdev_set_qos_limit_decoders[] = {
633 	{"name", offsetof(struct rpc_bdev_set_qos_limit, name), spdk_json_decode_string},
634 	{
635 		"rw_ios_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
636 					   limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT]),
637 		spdk_json_decode_uint64, true
638 	},
639 	{
640 		"rw_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
641 					      limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT]),
642 		spdk_json_decode_uint64, true
643 	},
644 	{
645 		"r_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
646 					     limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT]),
647 		spdk_json_decode_uint64, true
648 	},
649 	{
650 		"w_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
651 					     limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT]),
652 		spdk_json_decode_uint64, true
653 	},
654 };
655 
656 static void
657 rpc_bdev_set_qos_limit_complete(void *cb_arg, int status)
658 {
659 	struct spdk_jsonrpc_request *request = cb_arg;
660 
661 	if (status != 0) {
662 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
663 						     "Failed to configure rate limit: %s",
664 						     spdk_strerror(-status));
665 		return;
666 	}
667 
668 	spdk_jsonrpc_send_bool_response(request, true);
669 }
670 
671 static void
672 rpc_bdev_set_qos_limit(struct spdk_jsonrpc_request *request,
673 		       const struct spdk_json_val *params)
674 {
675 	struct rpc_bdev_set_qos_limit req = {NULL, {UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX}};
676 	struct spdk_bdev *bdev;
677 	int i;
678 
679 	if (spdk_json_decode_object(params, rpc_bdev_set_qos_limit_decoders,
680 				    SPDK_COUNTOF(rpc_bdev_set_qos_limit_decoders),
681 				    &req)) {
682 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
683 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
684 						 "spdk_json_decode_object failed");
685 		goto cleanup;
686 	}
687 
688 	bdev = spdk_bdev_get_by_name(req.name);
689 	if (bdev == NULL) {
690 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
691 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
692 		goto cleanup;
693 	}
694 
695 	for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) {
696 		if (req.limits[i] != UINT64_MAX) {
697 			break;
698 		}
699 	}
700 	if (i == SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES) {
701 		SPDK_ERRLOG("no rate limits specified\n");
702 		spdk_jsonrpc_send_error_response(request, -EINVAL, "No rate limits specified");
703 		goto cleanup;
704 	}
705 
706 	spdk_bdev_set_qos_rate_limits(bdev, req.limits, rpc_bdev_set_qos_limit_complete, request);
707 
708 cleanup:
709 	free_rpc_bdev_set_qos_limit(&req);
710 }
711 
712 SPDK_RPC_REGISTER("bdev_set_qos_limit", rpc_bdev_set_qos_limit, SPDK_RPC_RUNTIME)
713 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_qos_limit, set_bdev_qos_limit)
714 
715 /* SPDK_RPC_ENABLE_BDEV_HISTOGRAM */
716 
717 struct rpc_bdev_enable_histogram_request {
718 	char *name;
719 	bool enable;
720 };
721 
722 static void
723 free_rpc_bdev_enable_histogram_request(struct rpc_bdev_enable_histogram_request *r)
724 {
725 	free(r->name);
726 }
727 
728 static const struct spdk_json_object_decoder rpc_bdev_enable_histogram_request_decoders[] = {
729 	{"name", offsetof(struct rpc_bdev_enable_histogram_request, name), spdk_json_decode_string},
730 	{"enable", offsetof(struct rpc_bdev_enable_histogram_request, enable), spdk_json_decode_bool},
731 };
732 
733 static void
734 bdev_histogram_status_cb(void *cb_arg, int status)
735 {
736 	struct spdk_jsonrpc_request *request = cb_arg;
737 
738 	spdk_jsonrpc_send_bool_response(request, status == 0);
739 }
740 
741 static void
742 rpc_bdev_enable_histogram(struct spdk_jsonrpc_request *request,
743 			  const struct spdk_json_val *params)
744 {
745 	struct rpc_bdev_enable_histogram_request req = {NULL};
746 	struct spdk_bdev *bdev;
747 
748 	if (spdk_json_decode_object(params, rpc_bdev_enable_histogram_request_decoders,
749 				    SPDK_COUNTOF(rpc_bdev_enable_histogram_request_decoders),
750 				    &req)) {
751 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
752 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
753 						 "spdk_json_decode_object failed");
754 		goto cleanup;
755 	}
756 
757 	bdev = spdk_bdev_get_by_name(req.name);
758 	if (bdev == NULL) {
759 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
760 		goto cleanup;
761 	}
762 
763 	spdk_bdev_histogram_enable(bdev, bdev_histogram_status_cb, request, req.enable);
764 
765 cleanup:
766 	free_rpc_bdev_enable_histogram_request(&req);
767 }
768 
769 SPDK_RPC_REGISTER("bdev_enable_histogram", rpc_bdev_enable_histogram, SPDK_RPC_RUNTIME)
770 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_enable_histogram, enable_bdev_histogram)
771 
772 /* SPDK_RPC_GET_BDEV_HISTOGRAM */
773 
774 struct rpc_bdev_get_histogram_request {
775 	char *name;
776 };
777 
778 static const struct spdk_json_object_decoder rpc_bdev_get_histogram_request_decoders[] = {
779 	{"name", offsetof(struct rpc_bdev_get_histogram_request, name), spdk_json_decode_string}
780 };
781 
782 static void
783 free_rpc_bdev_get_histogram_request(struct rpc_bdev_get_histogram_request *r)
784 {
785 	free(r->name);
786 }
787 
788 static void
789 _rpc_bdev_histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram)
790 {
791 	struct spdk_jsonrpc_request *request = cb_arg;
792 	struct spdk_json_write_ctx *w;
793 	int rc;
794 	char *encoded_histogram;
795 	size_t src_len, dst_len;
796 
797 
798 	if (status != 0) {
799 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
800 						 spdk_strerror(-status));
801 		goto invalid;
802 	}
803 
804 	src_len = SPDK_HISTOGRAM_NUM_BUCKETS(histogram) * sizeof(uint64_t);
805 	dst_len = spdk_base64_get_encoded_strlen(src_len) + 1;
806 
807 	encoded_histogram = malloc(dst_len);
808 	if (encoded_histogram == NULL) {
809 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
810 						 spdk_strerror(ENOMEM));
811 		goto invalid;
812 	}
813 
814 	rc = spdk_base64_encode(encoded_histogram, histogram->bucket, src_len);
815 	if (rc != 0) {
816 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
817 						 spdk_strerror(-rc));
818 		goto free_encoded_histogram;
819 	}
820 
821 	w = spdk_jsonrpc_begin_result(request);
822 	spdk_json_write_object_begin(w);
823 	spdk_json_write_named_string(w, "histogram", encoded_histogram);
824 	spdk_json_write_named_int64(w, "bucket_shift", histogram->bucket_shift);
825 	spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz());
826 	spdk_json_write_object_end(w);
827 	spdk_jsonrpc_end_result(request, w);
828 
829 free_encoded_histogram:
830 	free(encoded_histogram);
831 invalid:
832 	spdk_histogram_data_free(histogram);
833 }
834 
835 static void
836 rpc_bdev_get_histogram(struct spdk_jsonrpc_request *request,
837 		       const struct spdk_json_val *params)
838 {
839 	struct rpc_bdev_get_histogram_request req = {NULL};
840 	struct spdk_histogram_data *histogram;
841 	struct spdk_bdev *bdev;
842 
843 	if (spdk_json_decode_object(params, rpc_bdev_get_histogram_request_decoders,
844 				    SPDK_COUNTOF(rpc_bdev_get_histogram_request_decoders),
845 				    &req)) {
846 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
847 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
848 						 "spdk_json_decode_object failed");
849 		goto cleanup;
850 	}
851 
852 	bdev = spdk_bdev_get_by_name(req.name);
853 	if (bdev == NULL) {
854 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
855 		goto cleanup;
856 	}
857 
858 	histogram = spdk_histogram_data_alloc();
859 	if (histogram == NULL) {
860 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
861 		goto cleanup;
862 	}
863 
864 	spdk_bdev_histogram_get(bdev, histogram, _rpc_bdev_histogram_data_cb, request);
865 
866 cleanup:
867 	free_rpc_bdev_get_histogram_request(&req);
868 }
869 
870 SPDK_RPC_REGISTER("bdev_get_histogram", rpc_bdev_get_histogram, SPDK_RPC_RUNTIME)
871 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_histogram, get_bdev_histogram)
872