xref: /spdk/lib/bdev/bdev_rpc.c (revision b30d57cdad6d2bc75cc1e4e2ebbcebcb0d98dcfa)
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);
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 };
446 
447 static void
448 free_rpc_bdev_get_bdevs(struct rpc_bdev_get_bdevs *r)
449 {
450 	free(r->name);
451 }
452 
453 static const struct spdk_json_object_decoder rpc_bdev_get_bdevs_decoders[] = {
454 	{"name", offsetof(struct rpc_bdev_get_bdevs, name), spdk_json_decode_string, true},
455 };
456 
457 static void
458 rpc_bdev_get_bdevs(struct spdk_jsonrpc_request *request,
459 		   const struct spdk_json_val *params)
460 {
461 	struct rpc_bdev_get_bdevs req = {};
462 	struct spdk_json_write_ctx *w;
463 	struct spdk_bdev *bdev = NULL;
464 
465 	if (params && spdk_json_decode_object(params, rpc_bdev_get_bdevs_decoders,
466 					      SPDK_COUNTOF(rpc_bdev_get_bdevs_decoders),
467 					      &req)) {
468 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
469 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
470 						 "spdk_json_decode_object failed");
471 		free_rpc_bdev_get_bdevs(&req);
472 		return;
473 	}
474 
475 	if (req.name) {
476 		bdev = spdk_bdev_get_by_name(req.name);
477 		if (bdev == NULL) {
478 			SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
479 			spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
480 			free_rpc_bdev_get_bdevs(&req);
481 			return;
482 		}
483 	}
484 
485 	free_rpc_bdev_get_bdevs(&req);
486 	w = spdk_jsonrpc_begin_result(request);
487 	spdk_json_write_array_begin(w);
488 
489 	if (bdev != NULL) {
490 		rpc_dump_bdev_info(w, bdev);
491 	} else {
492 		for (bdev = spdk_bdev_first(); bdev != NULL; bdev = spdk_bdev_next(bdev)) {
493 			rpc_dump_bdev_info(w, bdev);
494 		}
495 	}
496 
497 	spdk_json_write_array_end(w);
498 
499 	spdk_jsonrpc_end_result(request, w);
500 }
501 SPDK_RPC_REGISTER("bdev_get_bdevs", rpc_bdev_get_bdevs, SPDK_RPC_RUNTIME)
502 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_bdevs, get_bdevs)
503 
504 struct rpc_bdev_set_qd_sampling_period {
505 	char *name;
506 	uint64_t period;
507 };
508 
509 static void
510 free_rpc_bdev_set_qd_sampling_period(struct rpc_bdev_set_qd_sampling_period *r)
511 {
512 	free(r->name);
513 }
514 
515 static const struct spdk_json_object_decoder
516 	rpc_bdev_set_qd_sampling_period_decoders[] = {
517 	{"name", offsetof(struct rpc_bdev_set_qd_sampling_period, name), spdk_json_decode_string},
518 	{"period", offsetof(struct rpc_bdev_set_qd_sampling_period, period), spdk_json_decode_uint64},
519 };
520 
521 static void
522 rpc_bdev_set_qd_sampling_period(struct spdk_jsonrpc_request *request,
523 				const struct spdk_json_val *params)
524 {
525 	struct rpc_bdev_set_qd_sampling_period req = {0};
526 	struct spdk_bdev *bdev;
527 
528 	if (spdk_json_decode_object(params, rpc_bdev_set_qd_sampling_period_decoders,
529 				    SPDK_COUNTOF(rpc_bdev_set_qd_sampling_period_decoders),
530 				    &req)) {
531 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
532 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
533 						 "spdk_json_decode_object failed");
534 		goto cleanup;
535 	}
536 
537 	bdev = spdk_bdev_get_by_name(req.name);
538 	if (bdev == NULL) {
539 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
540 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
541 		goto cleanup;
542 	}
543 
544 	spdk_bdev_set_qd_sampling_period(bdev, req.period);
545 	spdk_jsonrpc_send_bool_response(request, true);
546 
547 cleanup:
548 	free_rpc_bdev_set_qd_sampling_period(&req);
549 }
550 SPDK_RPC_REGISTER("bdev_set_qd_sampling_period",
551 		  rpc_bdev_set_qd_sampling_period,
552 		  SPDK_RPC_RUNTIME)
553 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_qd_sampling_period,
554 				   set_bdev_qd_sampling_period)
555 
556 struct rpc_bdev_set_qos_limit {
557 	char		*name;
558 	uint64_t	limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES];
559 };
560 
561 static void
562 free_rpc_bdev_set_qos_limit(struct rpc_bdev_set_qos_limit *r)
563 {
564 	free(r->name);
565 }
566 
567 static const struct spdk_json_object_decoder rpc_bdev_set_qos_limit_decoders[] = {
568 	{"name", offsetof(struct rpc_bdev_set_qos_limit, name), spdk_json_decode_string},
569 	{
570 		"rw_ios_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
571 					   limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT]),
572 		spdk_json_decode_uint64, true
573 	},
574 	{
575 		"rw_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
576 					      limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT]),
577 		spdk_json_decode_uint64, true
578 	},
579 	{
580 		"r_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
581 					     limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT]),
582 		spdk_json_decode_uint64, true
583 	},
584 	{
585 		"w_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit,
586 					     limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT]),
587 		spdk_json_decode_uint64, true
588 	},
589 };
590 
591 static void
592 rpc_bdev_set_qos_limit_complete(void *cb_arg, int status)
593 {
594 	struct spdk_jsonrpc_request *request = cb_arg;
595 
596 	if (status != 0) {
597 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
598 						     "Failed to configure rate limit: %s",
599 						     spdk_strerror(-status));
600 		return;
601 	}
602 
603 	spdk_jsonrpc_send_bool_response(request, true);
604 }
605 
606 static void
607 rpc_bdev_set_qos_limit(struct spdk_jsonrpc_request *request,
608 		       const struct spdk_json_val *params)
609 {
610 	struct rpc_bdev_set_qos_limit req = {NULL, {UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX}};
611 	struct spdk_bdev *bdev;
612 	int i;
613 
614 	if (spdk_json_decode_object(params, rpc_bdev_set_qos_limit_decoders,
615 				    SPDK_COUNTOF(rpc_bdev_set_qos_limit_decoders),
616 				    &req)) {
617 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
618 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
619 						 "spdk_json_decode_object failed");
620 		goto cleanup;
621 	}
622 
623 	bdev = spdk_bdev_get_by_name(req.name);
624 	if (bdev == NULL) {
625 		SPDK_ERRLOG("bdev '%s' does not exist\n", req.name);
626 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
627 		goto cleanup;
628 	}
629 
630 	for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) {
631 		if (req.limits[i] != UINT64_MAX) {
632 			break;
633 		}
634 	}
635 	if (i == SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES) {
636 		SPDK_ERRLOG("no rate limits specified\n");
637 		spdk_jsonrpc_send_error_response(request, -EINVAL, "No rate limits specified");
638 		goto cleanup;
639 	}
640 
641 	spdk_bdev_set_qos_rate_limits(bdev, req.limits, rpc_bdev_set_qos_limit_complete, request);
642 
643 cleanup:
644 	free_rpc_bdev_set_qos_limit(&req);
645 }
646 
647 SPDK_RPC_REGISTER("bdev_set_qos_limit", rpc_bdev_set_qos_limit, SPDK_RPC_RUNTIME)
648 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_qos_limit, set_bdev_qos_limit)
649 
650 /* SPDK_RPC_ENABLE_BDEV_HISTOGRAM */
651 
652 struct rpc_bdev_enable_histogram_request {
653 	char *name;
654 	bool enable;
655 };
656 
657 static void
658 free_rpc_bdev_enable_histogram_request(struct rpc_bdev_enable_histogram_request *r)
659 {
660 	free(r->name);
661 }
662 
663 static const struct spdk_json_object_decoder rpc_bdev_enable_histogram_request_decoders[] = {
664 	{"name", offsetof(struct rpc_bdev_enable_histogram_request, name), spdk_json_decode_string},
665 	{"enable", offsetof(struct rpc_bdev_enable_histogram_request, enable), spdk_json_decode_bool},
666 };
667 
668 static void
669 bdev_histogram_status_cb(void *cb_arg, int status)
670 {
671 	struct spdk_jsonrpc_request *request = cb_arg;
672 
673 	spdk_jsonrpc_send_bool_response(request, status == 0);
674 }
675 
676 static void
677 rpc_bdev_enable_histogram(struct spdk_jsonrpc_request *request,
678 			  const struct spdk_json_val *params)
679 {
680 	struct rpc_bdev_enable_histogram_request req = {NULL};
681 	struct spdk_bdev *bdev;
682 
683 	if (spdk_json_decode_object(params, rpc_bdev_enable_histogram_request_decoders,
684 				    SPDK_COUNTOF(rpc_bdev_enable_histogram_request_decoders),
685 				    &req)) {
686 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
687 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
688 						 "spdk_json_decode_object failed");
689 		goto cleanup;
690 	}
691 
692 	bdev = spdk_bdev_get_by_name(req.name);
693 	if (bdev == NULL) {
694 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
695 		goto cleanup;
696 	}
697 
698 	spdk_bdev_histogram_enable(bdev, bdev_histogram_status_cb, request, req.enable);
699 
700 cleanup:
701 	free_rpc_bdev_enable_histogram_request(&req);
702 }
703 
704 SPDK_RPC_REGISTER("bdev_enable_histogram", rpc_bdev_enable_histogram, SPDK_RPC_RUNTIME)
705 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_enable_histogram, enable_bdev_histogram)
706 
707 /* SPDK_RPC_GET_BDEV_HISTOGRAM */
708 
709 struct rpc_bdev_get_histogram_request {
710 	char *name;
711 };
712 
713 static const struct spdk_json_object_decoder rpc_bdev_get_histogram_request_decoders[] = {
714 	{"name", offsetof(struct rpc_bdev_get_histogram_request, name), spdk_json_decode_string}
715 };
716 
717 static void
718 free_rpc_bdev_get_histogram_request(struct rpc_bdev_get_histogram_request *r)
719 {
720 	free(r->name);
721 }
722 
723 static void
724 _rpc_bdev_histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram)
725 {
726 	struct spdk_jsonrpc_request *request = cb_arg;
727 	struct spdk_json_write_ctx *w;
728 	int rc;
729 	char *encoded_histogram;
730 	size_t src_len, dst_len;
731 
732 
733 	if (status != 0) {
734 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
735 						 spdk_strerror(-status));
736 		goto invalid;
737 	}
738 
739 	src_len = SPDK_HISTOGRAM_NUM_BUCKETS(histogram) * sizeof(uint64_t);
740 	dst_len = spdk_base64_get_encoded_strlen(src_len) + 1;
741 
742 	encoded_histogram = malloc(dst_len);
743 	if (encoded_histogram == NULL) {
744 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
745 						 spdk_strerror(ENOMEM));
746 		goto invalid;
747 	}
748 
749 	rc = spdk_base64_encode(encoded_histogram, histogram->bucket, src_len);
750 	if (rc != 0) {
751 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
752 						 spdk_strerror(-rc));
753 		goto free_encoded_histogram;
754 	}
755 
756 	w = spdk_jsonrpc_begin_result(request);
757 	spdk_json_write_object_begin(w);
758 	spdk_json_write_named_string(w, "histogram", encoded_histogram);
759 	spdk_json_write_named_int64(w, "bucket_shift", histogram->bucket_shift);
760 	spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz());
761 	spdk_json_write_object_end(w);
762 	spdk_jsonrpc_end_result(request, w);
763 
764 free_encoded_histogram:
765 	free(encoded_histogram);
766 invalid:
767 	spdk_histogram_data_free(histogram);
768 }
769 
770 static void
771 rpc_bdev_get_histogram(struct spdk_jsonrpc_request *request,
772 		       const struct spdk_json_val *params)
773 {
774 	struct rpc_bdev_get_histogram_request req = {NULL};
775 	struct spdk_histogram_data *histogram;
776 	struct spdk_bdev *bdev;
777 
778 	if (spdk_json_decode_object(params, rpc_bdev_get_histogram_request_decoders,
779 				    SPDK_COUNTOF(rpc_bdev_get_histogram_request_decoders),
780 				    &req)) {
781 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
782 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
783 						 "spdk_json_decode_object failed");
784 		goto cleanup;
785 	}
786 
787 	bdev = spdk_bdev_get_by_name(req.name);
788 	if (bdev == NULL) {
789 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
790 		goto cleanup;
791 	}
792 
793 	histogram = spdk_histogram_data_alloc();
794 	if (histogram == NULL) {
795 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
796 		goto cleanup;
797 	}
798 
799 	spdk_bdev_histogram_get(bdev, histogram, _rpc_bdev_histogram_data_cb, request);
800 
801 cleanup:
802 	free_rpc_bdev_get_histogram_request(&req);
803 }
804 
805 SPDK_RPC_REGISTER("bdev_get_histogram", rpc_bdev_get_histogram, SPDK_RPC_RUNTIME)
806 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_histogram, get_bdev_histogram)
807