xref: /spdk/lib/bdev/bdev_rpc.c (revision 3de9887d6d0ef46706c3f8807e6ffbeb73107510)
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 struct rpc_bdev_examine {
114 	char *name;
115 };
116 
117 static void
118 free_rpc_bdev_examine(struct rpc_bdev_examine *r)
119 {
120 	free(r->name);
121 }
122 
123 static const struct spdk_json_object_decoder rpc_examine_bdev_decoders[] = {
124 	{"name", offsetof(struct rpc_bdev_examine, name), spdk_json_decode_string},
125 };
126 
127 static void
128 rpc_bdev_examine_bdev(struct spdk_jsonrpc_request *request,
129 		      const struct spdk_json_val *params)
130 {
131 	struct rpc_bdev_examine req = {NULL};
132 	int rc;
133 
134 	if (spdk_json_decode_object(params, rpc_examine_bdev_decoders,
135 				    SPDK_COUNTOF(rpc_examine_bdev_decoders),
136 				    &req)) {
137 		SPDK_ERRLOG("spdk_json_decode_object() failed\n");
138 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
139 						 "spdk_json_decode_object failed");
140 		goto cleanup;
141 	}
142 
143 	rc = spdk_bdev_examine(req.name);
144 	if (rc != 0) {
145 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
146 		goto cleanup;
147 	}
148 
149 	spdk_jsonrpc_send_bool_response(request, true);
150 
151 cleanup:
152 	free_rpc_bdev_examine(&req);
153 }
154 SPDK_RPC_REGISTER("bdev_examine", rpc_bdev_examine_bdev, SPDK_RPC_RUNTIME)
155 
156 struct rpc_bdev_get_iostat_ctx {
157 	int bdev_count;
158 	struct spdk_jsonrpc_request *request;
159 	struct spdk_json_write_ctx *w;
160 };
161 
162 static void
163 rpc_bdev_get_iostat_cb(struct spdk_bdev *bdev,
164 		       struct spdk_bdev_io_stat *stat, void *cb_arg, int rc)
165 {
166 	struct rpc_bdev_get_iostat_ctx *ctx = cb_arg;
167 	struct spdk_json_write_ctx *w = ctx->w;
168 	const char *bdev_name;
169 
170 	if (rc != 0) {
171 		goto done;
172 	}
173 
174 	bdev_name = spdk_bdev_get_name(bdev);
175 	if (bdev_name != NULL) {
176 		spdk_json_write_object_begin(w);
177 
178 		spdk_json_write_named_string(w, "name", bdev_name);
179 
180 		spdk_json_write_named_uint64(w, "bytes_read", stat->bytes_read);
181 
182 		spdk_json_write_named_uint64(w, "num_read_ops", stat->num_read_ops);
183 
184 		spdk_json_write_named_uint64(w, "bytes_written", stat->bytes_written);
185 
186 		spdk_json_write_named_uint64(w, "num_write_ops", stat->num_write_ops);
187 
188 		spdk_json_write_named_uint64(w, "bytes_unmapped", stat->bytes_unmapped);
189 
190 		spdk_json_write_named_uint64(w, "num_unmap_ops", stat->num_unmap_ops);
191 
192 		spdk_json_write_named_uint64(w, "read_latency_ticks", stat->read_latency_ticks);
193 
194 		spdk_json_write_named_uint64(w, "write_latency_ticks", stat->write_latency_ticks);
195 
196 		spdk_json_write_named_uint64(w, "unmap_latency_ticks", stat->unmap_latency_ticks);
197 
198 		if (spdk_bdev_get_qd_sampling_period(bdev)) {
199 			spdk_json_write_named_uint64(w, "queue_depth_polling_period",
200 						     spdk_bdev_get_qd_sampling_period(bdev));
201 
202 			spdk_json_write_named_uint64(w, "queue_depth", spdk_bdev_get_qd(bdev));
203 
204 			spdk_json_write_named_uint64(w, "io_time", spdk_bdev_get_io_time(bdev));
205 
206 			spdk_json_write_named_uint64(w, "weighted_io_time",
207 						     spdk_bdev_get_weighted_io_time(bdev));
208 		}
209 
210 		spdk_json_write_object_end(w);
211 	}
212 
213 done:
214 	free(stat);
215 	if (--ctx->bdev_count == 0) {
216 		spdk_json_write_array_end(ctx->w);
217 		spdk_json_write_object_end(w);
218 		spdk_jsonrpc_end_result(ctx->request, ctx->w);
219 		free(ctx);
220 	}
221 }
222 
223 struct rpc_bdev_get_iostat {
224 	char *name;
225 };
226 
227 static void
228 free_rpc_bdev_get_iostat(struct rpc_bdev_get_iostat *r)
229 {
230 	free(r->name);
231 }
232 
233 static const struct spdk_json_object_decoder rpc_bdev_get_iostat_decoders[] = {
234 	{"name", offsetof(struct rpc_bdev_get_iostat, name), spdk_json_decode_string, true},
235 };
236 
237 static void
238 rpc_bdev_get_iostat(struct spdk_jsonrpc_request *request,
239 		    const struct spdk_json_val *params)
240 {
241 	struct rpc_bdev_get_iostat req = {};
242 	struct spdk_bdev *bdev = NULL;
243 	struct spdk_json_write_ctx *w;
244 	struct spdk_bdev_io_stat *stat;
245 	struct rpc_bdev_get_iostat_ctx *ctx;
246 
247 	if (params != NULL) {
248 		if (spdk_json_decode_object(params, rpc_bdev_get_iostat_decoders,
249 					    SPDK_COUNTOF(rpc_bdev_get_iostat_decoders),
250 					    &req)) {
251 			SPDK_ERRLOG("spdk_json_decode_object failed\n");
252 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
253 							 "spdk_json_decode_object failed");
254 			free_rpc_bdev_get_iostat(&req);
255 			return;
256 		}
257 
258 		if (req.name) {
259 			bdev = spdk_bdev_get_by_name(req.name);
260 			if (bdev == NULL) {
261 				SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
262 				spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
263 				free_rpc_bdev_get_iostat(&req);
264 				return;
265 			}
266 		}
267 	}
268 
269 	free_rpc_bdev_get_iostat(&req);
270 
271 	ctx = calloc(1, sizeof(struct rpc_bdev_get_iostat_ctx));
272 	if (ctx == NULL) {
273 		SPDK_ERRLOG("Failed to allocate rpc_bdev_get_iostat_ctx struct\n");
274 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
275 		return;
276 	}
277 
278 	w = spdk_jsonrpc_begin_result(request);
279 	/*
280 	 * Increment initial bdev_count so that it will never reach 0 in the middle
281 	 * of iterating.
282 	 */
283 	ctx->bdev_count++;
284 	ctx->request = request;
285 	ctx->w = w;
286 
287 
288 	spdk_json_write_object_begin(w);
289 	spdk_json_write_named_uint64(w, "tick_rate", spdk_get_ticks_hz());
290 	spdk_json_write_named_uint64(w, "ticks", spdk_get_ticks());
291 
292 	spdk_json_write_named_array_begin(w, "bdevs");
293 
294 	if (bdev != NULL) {
295 		stat = calloc(1, sizeof(struct spdk_bdev_io_stat));
296 		if (stat == NULL) {
297 			SPDK_ERRLOG("Failed to allocate rpc_bdev_get_iostat_ctx struct\n");
298 		} else {
299 			ctx->bdev_count++;
300 			spdk_bdev_get_device_stat(bdev, stat, rpc_bdev_get_iostat_cb, ctx);
301 		}
302 	} else {
303 		for (bdev = spdk_bdev_first(); bdev != NULL; bdev = spdk_bdev_next(bdev)) {
304 			stat = calloc(1, sizeof(struct spdk_bdev_io_stat));
305 			if (stat == NULL) {
306 				SPDK_ERRLOG("Failed to allocate spdk_bdev_io_stat struct\n");
307 				break;
308 			}
309 			ctx->bdev_count++;
310 			spdk_bdev_get_device_stat(bdev, stat, rpc_bdev_get_iostat_cb, ctx);
311 		}
312 	}
313 
314 	if (--ctx->bdev_count == 0) {
315 		spdk_json_write_array_end(w);
316 		spdk_json_write_object_end(w);
317 		spdk_jsonrpc_end_result(request, w);
318 		free(ctx);
319 	}
320 }
321 SPDK_RPC_REGISTER("bdev_get_iostat", rpc_bdev_get_iostat, SPDK_RPC_RUNTIME)
322 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_iostat, get_bdevs_iostat)
323 
324 static void
325 rpc_dump_bdev_info(struct spdk_json_write_ctx *w,
326 		   struct spdk_bdev *bdev)
327 {
328 	struct spdk_bdev_alias *tmp;
329 	uint64_t qos_limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES];
330 	int i;
331 
332 	spdk_json_write_object_begin(w);
333 
334 	spdk_json_write_named_string(w, "name", spdk_bdev_get_name(bdev));
335 
336 	spdk_json_write_named_array_begin(w, "aliases");
337 
338 	TAILQ_FOREACH(tmp, spdk_bdev_get_aliases(bdev), tailq) {
339 		spdk_json_write_string(w, tmp->alias);
340 	}
341 
342 	spdk_json_write_array_end(w);
343 
344 	spdk_json_write_named_string(w, "product_name", spdk_bdev_get_product_name(bdev));
345 
346 	spdk_json_write_named_uint32(w, "block_size", spdk_bdev_get_block_size(bdev));
347 
348 	spdk_json_write_named_uint64(w, "num_blocks", spdk_bdev_get_num_blocks(bdev));
349 
350 	if (!spdk_mem_all_zero(&bdev->uuid, sizeof(bdev->uuid))) {
351 		char uuid_str[SPDK_UUID_STRING_LEN];
352 
353 		spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid);
354 		spdk_json_write_named_string(w, "uuid", uuid_str);
355 	}
356 
357 	if (spdk_bdev_get_md_size(bdev) != 0) {
358 		spdk_json_write_named_uint32(w, "md_size", spdk_bdev_get_md_size(bdev));
359 		spdk_json_write_named_bool(w, "md_interleave", spdk_bdev_is_md_interleaved(bdev));
360 		spdk_json_write_named_uint32(w, "dif_type", spdk_bdev_get_dif_type(bdev));
361 		if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) {
362 			spdk_json_write_named_bool(w, "dif_is_head_of_md", spdk_bdev_is_dif_head_of_md(bdev));
363 			spdk_json_write_named_object_begin(w, "enabled_dif_check_types");
364 			spdk_json_write_named_bool(w, "reftag",
365 						   spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG));
366 			spdk_json_write_named_bool(w, "apptag",
367 						   spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_APPTAG));
368 			spdk_json_write_named_bool(w, "guard",
369 						   spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD));
370 			spdk_json_write_object_end(w);
371 		}
372 	}
373 
374 	spdk_json_write_named_object_begin(w, "assigned_rate_limits");
375 	spdk_bdev_get_qos_rate_limits(bdev, qos_limits);
376 	for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) {
377 		spdk_json_write_named_uint64(w, spdk_bdev_get_qos_rpc_type(i), qos_limits[i]);
378 	}
379 	spdk_json_write_object_end(w);
380 
381 	spdk_json_write_named_bool(w, "claimed", (bdev->internal.claim_module != NULL));
382 
383 	spdk_json_write_named_bool(w, "zoned", bdev->zoned);
384 	if (bdev->zoned) {
385 		spdk_json_write_named_uint64(w, "zone_size", bdev->zone_size);
386 		spdk_json_write_named_uint64(w, "max_open_zones", bdev->max_open_zones);
387 		spdk_json_write_named_uint64(w, "optimal_open_zones", bdev->optimal_open_zones);
388 	}
389 
390 	spdk_json_write_named_object_begin(w, "supported_io_types");
391 	spdk_json_write_named_bool(w, "read",
392 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_READ));
393 	spdk_json_write_named_bool(w, "write",
394 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE));
395 	spdk_json_write_named_bool(w, "unmap",
396 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP));
397 	spdk_json_write_named_bool(w, "write_zeroes",
398 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE_ZEROES));
399 	spdk_json_write_named_bool(w, "flush",
400 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_FLUSH));
401 	spdk_json_write_named_bool(w, "reset",
402 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_RESET));
403 	spdk_json_write_named_bool(w, "nvme_admin",
404 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_ADMIN));
405 	spdk_json_write_named_bool(w, "nvme_io",
406 				   spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_IO));
407 	spdk_json_write_object_end(w);
408 
409 	spdk_json_write_named_object_begin(w, "driver_specific");
410 	spdk_bdev_dump_info_json(bdev, w);
411 	spdk_json_write_object_end(w);
412 
413 	spdk_json_write_object_end(w);
414 }
415 
416 struct rpc_bdev_get_bdevs {
417 	char *name;
418 };
419 
420 static void
421 free_rpc_bdev_get_bdevs(struct rpc_bdev_get_bdevs *r)
422 {
423 	free(r->name);
424 }
425 
426 static const struct spdk_json_object_decoder rpc_bdev_get_bdevs_decoders[] = {
427 	{"name", offsetof(struct rpc_bdev_get_bdevs, name), spdk_json_decode_string, true},
428 };
429 
430 static void
431 rpc_bdev_get_bdevs(struct spdk_jsonrpc_request *request,
432 		   const struct spdk_json_val *params)
433 {
434 	struct rpc_bdev_get_bdevs req = {};
435 	struct spdk_json_write_ctx *w;
436 	struct spdk_bdev *bdev = NULL;
437 
438 	if (params && spdk_json_decode_object(params, rpc_bdev_get_bdevs_decoders,
439 					      SPDK_COUNTOF(rpc_bdev_get_bdevs_decoders),
440 					      &req)) {
441 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
442 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
443 						 "spdk_json_decode_object failed");
444 		free_rpc_bdev_get_bdevs(&req);
445 		return;
446 	}
447 
448 	if (req.name) {
449 		bdev = spdk_bdev_get_by_name(req.name);
450 		if (bdev == NULL) {
451 			SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
452 			spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
453 			free_rpc_bdev_get_bdevs(&req);
454 			return;
455 		}
456 	}
457 
458 	free_rpc_bdev_get_bdevs(&req);
459 	w = spdk_jsonrpc_begin_result(request);
460 	spdk_json_write_array_begin(w);
461 
462 	if (bdev != NULL) {
463 		rpc_dump_bdev_info(w, bdev);
464 	} else {
465 		for (bdev = spdk_bdev_first(); bdev != NULL; bdev = spdk_bdev_next(bdev)) {
466 			rpc_dump_bdev_info(w, bdev);
467 		}
468 	}
469 
470 	spdk_json_write_array_end(w);
471 
472 	spdk_jsonrpc_end_result(request, w);
473 }
474 SPDK_RPC_REGISTER("bdev_get_bdevs", rpc_bdev_get_bdevs, SPDK_RPC_RUNTIME)
475 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_bdevs, get_bdevs)
476 
477 struct rpc_bdev_set_qd_sampling_period {
478 	char *name;
479 	uint64_t period;
480 };
481 
482 static void
483 free_rpc_bdev_set_qd_sampling_period(struct rpc_bdev_set_qd_sampling_period *r)
484 {
485 	free(r->name);
486 }
487 
488 static const struct spdk_json_object_decoder
489 	rpc_bdev_set_qd_sampling_period_decoders[] = {
490 	{"name", offsetof(struct rpc_bdev_set_qd_sampling_period, name), spdk_json_decode_string},
491 	{"period", offsetof(struct rpc_bdev_set_qd_sampling_period, period), spdk_json_decode_uint64},
492 };
493 
494 static void
495 rpc_bdev_set_qd_sampling_period(struct spdk_jsonrpc_request *request,
496 				const struct spdk_json_val *params)
497 {
498 	struct rpc_bdev_set_qd_sampling_period req = {0};
499 	struct spdk_bdev *bdev;
500 
501 	if (spdk_json_decode_object(params, rpc_bdev_set_qd_sampling_period_decoders,
502 				    SPDK_COUNTOF(rpc_bdev_set_qd_sampling_period_decoders),
503 				    &req)) {
504 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
505 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
506 						 "spdk_json_decode_object failed");
507 		goto cleanup;
508 	}
509 
510 	bdev = spdk_bdev_get_by_name(req.name);
511 	if (bdev == NULL) {
512 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
513 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
514 		goto cleanup;
515 	}
516 
517 	spdk_bdev_set_qd_sampling_period(bdev, req.period);
518 	spdk_jsonrpc_send_bool_response(request, true);
519 
520 cleanup:
521 	free_rpc_bdev_set_qd_sampling_period(&req);
522 }
523 SPDK_RPC_REGISTER("bdev_set_qd_sampling_period",
524 		  rpc_bdev_set_qd_sampling_period,
525 		  SPDK_RPC_RUNTIME)
526 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_qd_sampling_period,
527 				   set_bdev_qd_sampling_period)
528 
529 struct rpc_bdev_set_qos_limit {
530 	char		*name;
531 	uint64_t	limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES];
532 };
533 
534 static void
535 free_rpc_bdev_set_qos_limit(struct rpc_bdev_set_qos_limit *r)
536 {
537 	free(r->name);
538 }
539 
540 static const struct spdk_json_object_decoder rpc_bdev_set_qos_limit_decoders[] = {
541 	{"name", offsetof(struct rpc_bdev_set_qos_limit, name), spdk_json_decode_string},
542 	{
543 		"rw_ios_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
544 					   limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT]),
545 		spdk_json_decode_uint64, true
546 	},
547 	{
548 		"rw_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
549 					      limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT]),
550 		spdk_json_decode_uint64, true
551 	},
552 	{
553 		"r_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
554 					     limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT]),
555 		spdk_json_decode_uint64, true
556 	},
557 	{
558 		"w_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
559 					     limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT]),
560 		spdk_json_decode_uint64, true
561 	},
562 };
563 
564 static void
565 rpc_bdev_set_qos_limit_complete(void *cb_arg, int status)
566 {
567 	struct spdk_jsonrpc_request *request = cb_arg;
568 
569 	if (status != 0) {
570 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
571 						     "Failed to configure rate limit: %s",
572 						     spdk_strerror(-status));
573 		return;
574 	}
575 
576 	spdk_jsonrpc_send_bool_response(request, true);
577 }
578 
579 static void
580 rpc_bdev_set_qos_limit(struct spdk_jsonrpc_request *request,
581 		       const struct spdk_json_val *params)
582 {
583 	struct rpc_bdev_set_qos_limit req = {NULL, {UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX}};
584 	struct spdk_bdev *bdev;
585 	int i;
586 
587 	if (spdk_json_decode_object(params, rpc_bdev_set_qos_limit_decoders,
588 				    SPDK_COUNTOF(rpc_bdev_set_qos_limit_decoders),
589 				    &req)) {
590 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
591 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
592 						 "spdk_json_decode_object failed");
593 		goto cleanup;
594 	}
595 
596 	bdev = spdk_bdev_get_by_name(req.name);
597 	if (bdev == NULL) {
598 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
599 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
600 		goto cleanup;
601 	}
602 
603 	for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) {
604 		if (req.limits[i] != UINT64_MAX) {
605 			break;
606 		}
607 	}
608 	if (i == SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES) {
609 		SPDK_ERRLOG("no rate limits specified\n");
610 		spdk_jsonrpc_send_error_response(request, -EINVAL, "No rate limits specified");
611 		goto cleanup;
612 	}
613 
614 	spdk_bdev_set_qos_rate_limits(bdev, req.limits, rpc_bdev_set_qos_limit_complete, request);
615 
616 cleanup:
617 	free_rpc_bdev_set_qos_limit(&req);
618 }
619 
620 SPDK_RPC_REGISTER("bdev_set_qos_limit", rpc_bdev_set_qos_limit, SPDK_RPC_RUNTIME)
621 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_qos_limit, set_bdev_qos_limit)
622 
623 /* SPDK_RPC_ENABLE_BDEV_HISTOGRAM */
624 
625 struct rpc_bdev_enable_histogram_request {
626 	char *name;
627 	bool enable;
628 };
629 
630 static void
631 free_rpc_bdev_enable_histogram_request(struct rpc_bdev_enable_histogram_request *r)
632 {
633 	free(r->name);
634 }
635 
636 static const struct spdk_json_object_decoder rpc_bdev_enable_histogram_request_decoders[] = {
637 	{"name", offsetof(struct rpc_bdev_enable_histogram_request, name), spdk_json_decode_string},
638 	{"enable", offsetof(struct rpc_bdev_enable_histogram_request, enable), spdk_json_decode_bool},
639 };
640 
641 static void
642 bdev_histogram_status_cb(void *cb_arg, int status)
643 {
644 	struct spdk_jsonrpc_request *request = cb_arg;
645 
646 	spdk_jsonrpc_send_bool_response(request, status == 0);
647 }
648 
649 static void
650 rpc_bdev_enable_histogram(struct spdk_jsonrpc_request *request,
651 			  const struct spdk_json_val *params)
652 {
653 	struct rpc_bdev_enable_histogram_request req = {NULL};
654 	struct spdk_bdev *bdev;
655 
656 	if (spdk_json_decode_object(params, rpc_bdev_enable_histogram_request_decoders,
657 				    SPDK_COUNTOF(rpc_bdev_enable_histogram_request_decoders),
658 				    &req)) {
659 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
660 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
661 						 "spdk_json_decode_object failed");
662 		goto cleanup;
663 	}
664 
665 	bdev = spdk_bdev_get_by_name(req.name);
666 	if (bdev == NULL) {
667 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
668 		goto cleanup;
669 	}
670 
671 	spdk_bdev_histogram_enable(bdev, bdev_histogram_status_cb, request, req.enable);
672 
673 cleanup:
674 	free_rpc_bdev_enable_histogram_request(&req);
675 }
676 
677 SPDK_RPC_REGISTER("bdev_enable_histogram", rpc_bdev_enable_histogram, SPDK_RPC_RUNTIME)
678 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_enable_histogram, enable_bdev_histogram)
679 
680 /* SPDK_RPC_GET_BDEV_HISTOGRAM */
681 
682 struct rpc_bdev_get_histogram_request {
683 	char *name;
684 };
685 
686 static const struct spdk_json_object_decoder rpc_bdev_get_histogram_request_decoders[] = {
687 	{"name", offsetof(struct rpc_bdev_get_histogram_request, name), spdk_json_decode_string}
688 };
689 
690 static void
691 free_rpc_bdev_get_histogram_request(struct rpc_bdev_get_histogram_request *r)
692 {
693 	free(r->name);
694 }
695 
696 static void
697 _rpc_bdev_histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram)
698 {
699 	struct spdk_jsonrpc_request *request = cb_arg;
700 	struct spdk_json_write_ctx *w;
701 	int rc;
702 	char *encoded_histogram;
703 	size_t src_len, dst_len;
704 
705 
706 	if (status != 0) {
707 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
708 						 spdk_strerror(-status));
709 		goto invalid;
710 	}
711 
712 	src_len = SPDK_HISTOGRAM_NUM_BUCKETS(histogram) * sizeof(uint64_t);
713 	dst_len = spdk_base64_get_encoded_strlen(src_len) + 1;
714 
715 	encoded_histogram = malloc(dst_len);
716 	if (encoded_histogram == NULL) {
717 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
718 						 spdk_strerror(ENOMEM));
719 		goto invalid;
720 	}
721 
722 	rc = spdk_base64_encode(encoded_histogram, histogram->bucket, src_len);
723 	if (rc != 0) {
724 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
725 						 spdk_strerror(-rc));
726 		goto free_encoded_histogram;
727 	}
728 
729 	w = spdk_jsonrpc_begin_result(request);
730 	spdk_json_write_object_begin(w);
731 	spdk_json_write_named_string(w, "histogram", encoded_histogram);
732 	spdk_json_write_named_int64(w, "bucket_shift", histogram->bucket_shift);
733 	spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz());
734 	spdk_json_write_object_end(w);
735 	spdk_jsonrpc_end_result(request, w);
736 
737 free_encoded_histogram:
738 	free(encoded_histogram);
739 invalid:
740 	spdk_histogram_data_free(histogram);
741 }
742 
743 static void
744 rpc_bdev_get_histogram(struct spdk_jsonrpc_request *request,
745 		       const struct spdk_json_val *params)
746 {
747 	struct rpc_bdev_get_histogram_request req = {NULL};
748 	struct spdk_histogram_data *histogram;
749 	struct spdk_bdev *bdev;
750 
751 	if (spdk_json_decode_object(params, rpc_bdev_get_histogram_request_decoders,
752 				    SPDK_COUNTOF(rpc_bdev_get_histogram_request_decoders),
753 				    &req)) {
754 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
755 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
756 						 "spdk_json_decode_object failed");
757 		goto cleanup;
758 	}
759 
760 	bdev = spdk_bdev_get_by_name(req.name);
761 	if (bdev == NULL) {
762 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
763 		goto cleanup;
764 	}
765 
766 	histogram = spdk_histogram_data_alloc();
767 	if (histogram == NULL) {
768 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
769 		goto cleanup;
770 	}
771 
772 	spdk_bdev_histogram_get(bdev, histogram, _rpc_bdev_histogram_data_cb, request);
773 
774 cleanup:
775 	free_rpc_bdev_get_histogram_request(&req);
776 }
777 
778 SPDK_RPC_REGISTER("bdev_get_histogram", rpc_bdev_get_histogram, SPDK_RPC_RUNTIME)
779 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_histogram, get_bdev_histogram)
780