4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
37 #include "spdk/string.h"
38 #include "spdk/util.h"
39 #include "spdk/histogram_data.h"
40 #include "spdk/base64.h"
42 #include "spdk/bdev_module.h"
44 struct rpc_get_bdevs_iostat_ctx
{
46 struct spdk_jsonrpc_request
*request
;
47 struct spdk_json_write_ctx
*w
;
51 spdk_rpc_get_bdevs_iostat_cb(struct spdk_bdev
*bdev
,
52 struct spdk_bdev_io_stat
*stat
, void *cb_arg
, int rc
)
54 struct rpc_get_bdevs_iostat_ctx
*ctx
= cb_arg
;
55 struct spdk_json_write_ctx
*w
= ctx
->w
;
56 const char *bdev_name
;
62 bdev_name
= spdk_bdev_get_name(bdev
);
63 if (bdev_name
!= NULL
) {
64 spdk_json_write_object_begin(w
);
66 spdk_json_write_named_string(w
, "name", bdev_name
);
68 spdk_json_write_named_uint64(w
, "bytes_read", stat
->bytes_read
);
70 spdk_json_write_named_uint64(w
, "num_read_ops", stat
->num_read_ops
);
72 spdk_json_write_named_uint64(w
, "bytes_written", stat
->bytes_written
);
74 spdk_json_write_named_uint64(w
, "num_write_ops", stat
->num_write_ops
);
76 spdk_json_write_named_uint64(w
, "bytes_unmapped", stat
->bytes_unmapped
);
78 spdk_json_write_named_uint64(w
, "num_unmap_ops", stat
->num_unmap_ops
);
80 spdk_json_write_named_uint64(w
, "read_latency_ticks", stat
->read_latency_ticks
);
82 spdk_json_write_named_uint64(w
, "write_latency_ticks", stat
->write_latency_ticks
);
84 spdk_json_write_named_uint64(w
, "unmap_latency_ticks", stat
->unmap_latency_ticks
);
86 if (spdk_bdev_get_qd_sampling_period(bdev
)) {
87 spdk_json_write_named_uint64(w
, "queue_depth_polling_period",
88 spdk_bdev_get_qd_sampling_period(bdev
));
90 spdk_json_write_named_uint64(w
, "queue_depth", spdk_bdev_get_qd(bdev
));
92 spdk_json_write_named_uint64(w
, "io_time", spdk_bdev_get_io_time(bdev
));
94 spdk_json_write_named_uint64(w
, "weighted_io_time",
95 spdk_bdev_get_weighted_io_time(bdev
));
98 spdk_json_write_object_end(w
);
103 if (--ctx
->bdev_count
== 0) {
104 spdk_json_write_array_end(ctx
->w
);
105 spdk_json_write_object_end(w
);
106 spdk_jsonrpc_end_result(ctx
->request
, ctx
->w
);
111 struct rpc_get_bdevs_iostat
{
116 free_rpc_get_bdevs_iostat(struct rpc_get_bdevs_iostat
*r
)
121 static const struct spdk_json_object_decoder rpc_get_bdevs_iostat_decoders
[] = {
122 {"name", offsetof(struct rpc_get_bdevs_iostat
, name
), spdk_json_decode_string
, true},
126 spdk_rpc_get_bdevs_iostat(struct spdk_jsonrpc_request
*request
,
127 const struct spdk_json_val
*params
)
129 struct rpc_get_bdevs_iostat req
= {};
130 struct spdk_bdev
*bdev
= NULL
;
131 struct spdk_json_write_ctx
*w
;
132 struct spdk_bdev_io_stat
*stat
;
133 struct rpc_get_bdevs_iostat_ctx
*ctx
;
135 if (params
!= NULL
) {
136 if (spdk_json_decode_object(params
, rpc_get_bdevs_iostat_decoders
,
137 SPDK_COUNTOF(rpc_get_bdevs_iostat_decoders
),
139 SPDK_ERRLOG("spdk_json_decode_object failed\n");
144 bdev
= spdk_bdev_get_by_name(req
.name
);
146 SPDK_ERRLOG("bdev '%s' does not exist\n", req
.name
);
152 free_rpc_get_bdevs_iostat(&req
);
154 ctx
= calloc(1, sizeof(struct rpc_get_bdevs_iostat_ctx
));
156 SPDK_ERRLOG("Failed to allocate rpc_get_bdevs_iostat_ctx struct\n");
157 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
, "No memory left");
161 w
= spdk_jsonrpc_begin_result(request
);
168 * Increment initial bdev_count so that it will never reach 0 in the middle
172 ctx
->request
= request
;
176 spdk_json_write_object_begin(w
);
177 spdk_json_write_named_uint64(w
, "tick_rate", spdk_get_ticks_hz());
179 spdk_json_write_named_array_begin(w
, "bdevs");
182 stat
= calloc(1, sizeof(struct spdk_bdev_io_stat
));
184 SPDK_ERRLOG("Failed to allocate rpc_get_bdevs_iostat_ctx struct\n");
187 spdk_bdev_get_device_stat(bdev
, stat
, spdk_rpc_get_bdevs_iostat_cb
, ctx
);
190 for (bdev
= spdk_bdev_first(); bdev
!= NULL
; bdev
= spdk_bdev_next(bdev
)) {
191 stat
= calloc(1, sizeof(struct spdk_bdev_io_stat
));
193 SPDK_ERRLOG("Failed to allocate spdk_bdev_io_stat struct\n");
197 spdk_bdev_get_device_stat(bdev
, stat
, spdk_rpc_get_bdevs_iostat_cb
, ctx
);
201 if (--ctx
->bdev_count
== 0) {
202 spdk_json_write_array_end(w
);
203 spdk_json_write_object_end(w
);
204 spdk_jsonrpc_end_result(request
, w
);
211 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, "Invalid parameters");
213 free_rpc_get_bdevs_iostat(&req
);
215 SPDK_RPC_REGISTER("get_bdevs_iostat", spdk_rpc_get_bdevs_iostat
, SPDK_RPC_RUNTIME
)
218 spdk_rpc_dump_bdev_info(struct spdk_json_write_ctx
*w
,
219 struct spdk_bdev
*bdev
)
221 struct spdk_bdev_alias
*tmp
;
222 uint64_t qos_limits
[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES
];
225 spdk_json_write_object_begin(w
);
227 spdk_json_write_named_string(w
, "name", spdk_bdev_get_name(bdev
));
229 spdk_json_write_named_array_begin(w
, "aliases");
231 TAILQ_FOREACH(tmp
, spdk_bdev_get_aliases(bdev
), tailq
) {
232 spdk_json_write_string(w
, tmp
->alias
);
235 spdk_json_write_array_end(w
);
237 spdk_json_write_named_string(w
, "product_name", spdk_bdev_get_product_name(bdev
));
239 spdk_json_write_named_uint32(w
, "block_size", spdk_bdev_get_block_size(bdev
));
241 spdk_json_write_named_uint64(w
, "num_blocks", spdk_bdev_get_num_blocks(bdev
));
243 if (!spdk_mem_all_zero(&bdev
->uuid
, sizeof(bdev
->uuid
))) {
244 char uuid_str
[SPDK_UUID_STRING_LEN
];
246 spdk_uuid_fmt_lower(uuid_str
, sizeof(uuid_str
), &bdev
->uuid
);
247 spdk_json_write_named_string(w
, "uuid", uuid_str
);
250 if (spdk_bdev_get_md_size(bdev
) != 0) {
251 spdk_json_write_named_uint32(w
, "md_size", spdk_bdev_get_md_size(bdev
));
252 spdk_json_write_named_bool(w
, "md_interleave", spdk_bdev_is_md_interleaved(bdev
));
253 spdk_json_write_named_uint32(w
, "dif_type", spdk_bdev_get_dif_type(bdev
));
254 if (spdk_bdev_get_dif_type(bdev
) != SPDK_DIF_DISABLE
) {
255 spdk_json_write_named_bool(w
, "dif_is_head_of_md", spdk_bdev_is_dif_head_of_md(bdev
));
256 spdk_json_write_named_object_begin(w
, "enabled_dif_check_types");
257 spdk_json_write_named_bool(w
, "reftag",
258 spdk_bdev_is_dif_check_enabled(bdev
, SPDK_DIF_CHECK_TYPE_REFTAG
));
259 spdk_json_write_named_bool(w
, "apptag",
260 spdk_bdev_is_dif_check_enabled(bdev
, SPDK_DIF_CHECK_TYPE_APPTAG
));
261 spdk_json_write_named_bool(w
, "guard",
262 spdk_bdev_is_dif_check_enabled(bdev
, SPDK_DIF_CHECK_TYPE_GUARD
));
263 spdk_json_write_object_end(w
);
267 spdk_json_write_named_object_begin(w
, "assigned_rate_limits");
268 spdk_bdev_get_qos_rate_limits(bdev
, qos_limits
);
269 for (i
= 0; i
< SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES
; i
++) {
270 spdk_json_write_named_uint64(w
, spdk_bdev_get_qos_rpc_type(i
), qos_limits
[i
]);
272 spdk_json_write_object_end(w
);
274 spdk_json_write_named_bool(w
, "claimed", (bdev
->internal
.claim_module
!= NULL
));
276 spdk_json_write_named_object_begin(w
, "supported_io_types");
277 spdk_json_write_named_bool(w
, "read",
278 spdk_bdev_io_type_supported(bdev
, SPDK_BDEV_IO_TYPE_READ
));
279 spdk_json_write_named_bool(w
, "write",
280 spdk_bdev_io_type_supported(bdev
, SPDK_BDEV_IO_TYPE_WRITE
));
281 spdk_json_write_named_bool(w
, "unmap",
282 spdk_bdev_io_type_supported(bdev
, SPDK_BDEV_IO_TYPE_UNMAP
));
283 spdk_json_write_named_bool(w
, "write_zeroes",
284 spdk_bdev_io_type_supported(bdev
, SPDK_BDEV_IO_TYPE_WRITE_ZEROES
));
285 spdk_json_write_named_bool(w
, "flush",
286 spdk_bdev_io_type_supported(bdev
, SPDK_BDEV_IO_TYPE_FLUSH
));
287 spdk_json_write_named_bool(w
, "reset",
288 spdk_bdev_io_type_supported(bdev
, SPDK_BDEV_IO_TYPE_RESET
));
289 spdk_json_write_named_bool(w
, "nvme_admin",
290 spdk_bdev_io_type_supported(bdev
, SPDK_BDEV_IO_TYPE_NVME_ADMIN
));
291 spdk_json_write_named_bool(w
, "nvme_io",
292 spdk_bdev_io_type_supported(bdev
, SPDK_BDEV_IO_TYPE_NVME_IO
));
293 spdk_json_write_object_end(w
);
295 spdk_json_write_named_object_begin(w
, "driver_specific");
296 spdk_bdev_dump_info_json(bdev
, w
);
297 spdk_json_write_object_end(w
);
299 spdk_json_write_object_end(w
);
302 struct rpc_get_bdevs
{
307 free_rpc_get_bdevs(struct rpc_get_bdevs
*r
)
312 static const struct spdk_json_object_decoder rpc_get_bdevs_decoders
[] = {
313 {"name", offsetof(struct rpc_get_bdevs
, name
), spdk_json_decode_string
, true},
317 spdk_rpc_get_bdevs(struct spdk_jsonrpc_request
*request
,
318 const struct spdk_json_val
*params
)
320 struct rpc_get_bdevs req
= {};
321 struct spdk_json_write_ctx
*w
;
322 struct spdk_bdev
*bdev
= NULL
;
324 if (params
&& spdk_json_decode_object(params
, rpc_get_bdevs_decoders
,
325 SPDK_COUNTOF(rpc_get_bdevs_decoders
),
327 SPDK_ERRLOG("spdk_json_decode_object failed\n");
332 bdev
= spdk_bdev_get_by_name(req
.name
);
334 SPDK_ERRLOG("bdev '%s' does not exist\n", req
.name
);
339 free_rpc_get_bdevs(&req
);
340 w
= spdk_jsonrpc_begin_result(request
);
345 spdk_json_write_array_begin(w
);
348 spdk_rpc_dump_bdev_info(w
, bdev
);
350 for (bdev
= spdk_bdev_first(); bdev
!= NULL
; bdev
= spdk_bdev_next(bdev
)) {
351 spdk_rpc_dump_bdev_info(w
, bdev
);
355 spdk_json_write_array_end(w
);
357 spdk_jsonrpc_end_result(request
, w
);
362 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, "Invalid parameters");
364 free_rpc_get_bdevs(&req
);
366 SPDK_RPC_REGISTER("get_bdevs", spdk_rpc_get_bdevs
, SPDK_RPC_RUNTIME
)
368 struct rpc_set_bdev_qd_sampling_period
{
374 free_rpc_set_bdev_qd_sampling_period(struct rpc_set_bdev_qd_sampling_period
*r
)
379 static const struct spdk_json_object_decoder
380 rpc_set_bdev_qd_sampling_period_decoders
[] = {
381 {"name", offsetof(struct rpc_set_bdev_qd_sampling_period
, name
), spdk_json_decode_string
},
382 {"period", offsetof(struct rpc_set_bdev_qd_sampling_period
, period
), spdk_json_decode_uint64
},
386 spdk_rpc_set_bdev_qd_sampling_period(struct spdk_jsonrpc_request
*request
,
387 const struct spdk_json_val
*params
)
389 struct rpc_set_bdev_qd_sampling_period req
= {0};
390 struct spdk_bdev
*bdev
;
391 struct spdk_json_write_ctx
*w
;
393 req
.period
= UINT64_MAX
;
395 if (spdk_json_decode_object(params
, rpc_set_bdev_qd_sampling_period_decoders
,
396 SPDK_COUNTOF(rpc_set_bdev_qd_sampling_period_decoders
),
398 SPDK_ERRLOG("spdk_json_decode_object failed\n");
403 bdev
= spdk_bdev_get_by_name(req
.name
);
405 SPDK_ERRLOG("bdev '%s' does not exist\n", req
.name
);
409 SPDK_ERRLOG("Missing name param\n");
413 if (req
.period
== UINT64_MAX
) {
414 SPDK_ERRLOG("Missing period param");
417 w
= spdk_jsonrpc_begin_result(request
);
418 spdk_bdev_set_qd_sampling_period(bdev
, req
.period
);
420 spdk_json_write_bool(w
, true);
421 spdk_jsonrpc_end_result(request
, w
);
422 free_rpc_set_bdev_qd_sampling_period(&req
);
426 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, "Invalid parameters");
427 free_rpc_set_bdev_qd_sampling_period(&req
);
430 SPDK_RPC_REGISTER("set_bdev_qd_sampling_period",
431 spdk_rpc_set_bdev_qd_sampling_period
,
434 struct rpc_set_bdev_qos_limit
{
436 uint64_t limits
[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES
];
440 free_rpc_set_bdev_qos_limit(struct rpc_set_bdev_qos_limit
*r
)
445 static const struct spdk_json_object_decoder rpc_set_bdev_qos_limit_decoders
[] = {
446 {"name", offsetof(struct rpc_set_bdev_qos_limit
, name
), spdk_json_decode_string
},
448 "rw_ios_per_sec", offsetof(struct rpc_set_bdev_qos_limit
,
449 limits
[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT
]),
450 spdk_json_decode_uint64
, true
453 "rw_mbytes_per_sec", offsetof(struct rpc_set_bdev_qos_limit
,
454 limits
[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT
]),
455 spdk_json_decode_uint64
, true
458 "r_mbytes_per_sec", offsetof(struct rpc_set_bdev_qos_limit
,
459 limits
[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT
]),
460 spdk_json_decode_uint64
, true
463 "w_mbytes_per_sec", offsetof(struct rpc_set_bdev_qos_limit
,
464 limits
[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT
]),
465 spdk_json_decode_uint64
, true
470 spdk_rpc_set_bdev_qos_limit_complete(void *cb_arg
, int status
)
472 struct spdk_jsonrpc_request
*request
= cb_arg
;
473 struct spdk_json_write_ctx
*w
;
476 spdk_jsonrpc_send_error_response_fmt(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
,
477 "Failed to configure rate limit: %s",
478 spdk_strerror(-status
));
482 w
= spdk_jsonrpc_begin_result(request
);
487 spdk_json_write_bool(w
, true);
488 spdk_jsonrpc_end_result(request
, w
);
492 spdk_rpc_set_bdev_qos_limit(struct spdk_jsonrpc_request
*request
,
493 const struct spdk_json_val
*params
)
495 struct rpc_set_bdev_qos_limit req
= {NULL
, {UINT64_MAX
, UINT64_MAX
, UINT64_MAX
, UINT64_MAX
}};
496 struct spdk_bdev
*bdev
;
499 if (spdk_json_decode_object(params
, rpc_set_bdev_qos_limit_decoders
,
500 SPDK_COUNTOF(rpc_set_bdev_qos_limit_decoders
),
502 SPDK_ERRLOG("spdk_json_decode_object failed\n");
506 bdev
= spdk_bdev_get_by_name(req
.name
);
508 SPDK_ERRLOG("bdev '%s' does not exist\n", req
.name
);
509 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
,
510 "Bdev does not exist");
514 for (i
= 0; i
< SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES
; i
++) {
515 if (req
.limits
[i
] != UINT64_MAX
) {
519 if (i
== SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES
) {
520 SPDK_ERRLOG("no rate limits specified\n");
521 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
,
522 "No rate limits specified");
526 free_rpc_set_bdev_qos_limit(&req
);
527 spdk_bdev_set_qos_rate_limits(bdev
, req
.limits
, spdk_rpc_set_bdev_qos_limit_complete
, request
);
531 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, "Invalid parameters");
533 free_rpc_set_bdev_qos_limit(&req
);
536 SPDK_RPC_REGISTER("set_bdev_qos_limit", spdk_rpc_set_bdev_qos_limit
, SPDK_RPC_RUNTIME
)
538 /* SPDK_RPC_ENABLE_BDEV_HISTOGRAM */
540 struct rpc_enable_bdev_histogram_request
{
546 free_rpc_enable_bdev_histogram_request(struct rpc_enable_bdev_histogram_request
*r
)
551 static const struct spdk_json_object_decoder rpc_enable_bdev_histogram_request_decoders
[] = {
552 {"name", offsetof(struct rpc_enable_bdev_histogram_request
, name
), spdk_json_decode_string
},
553 {"enable", offsetof(struct rpc_enable_bdev_histogram_request
, enable
), spdk_json_decode_bool
},
557 _spdk_bdev_histogram_status_cb(void *cb_arg
, int status
)
559 struct spdk_jsonrpc_request
*request
= cb_arg
;
560 struct spdk_json_write_ctx
*w
;
562 w
= spdk_jsonrpc_begin_result(request
);
567 spdk_json_write_bool(w
, status
== 0);
568 spdk_jsonrpc_end_result(request
, w
);
572 spdk_rpc_enable_bdev_histogram(struct spdk_jsonrpc_request
*request
,
573 const struct spdk_json_val
*params
)
575 struct rpc_enable_bdev_histogram_request req
= {NULL
};
576 struct spdk_bdev
*bdev
;
579 if (spdk_json_decode_object(params
, rpc_enable_bdev_histogram_request_decoders
,
580 SPDK_COUNTOF(rpc_enable_bdev_histogram_request_decoders
),
582 SPDK_ERRLOG("spdk_json_decode_object failed\n");
587 bdev
= spdk_bdev_get_by_name(req
.name
);
593 spdk_bdev_histogram_enable(bdev
, _spdk_bdev_histogram_status_cb
, request
, req
.enable
);
595 free_rpc_enable_bdev_histogram_request(&req
);
600 free_rpc_enable_bdev_histogram_request(&req
);
601 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, spdk_strerror(-rc
));
604 SPDK_RPC_REGISTER("enable_bdev_histogram", spdk_rpc_enable_bdev_histogram
, SPDK_RPC_RUNTIME
)
606 /* SPDK_RPC_GET_BDEV_HISTOGRAM */
608 struct rpc_get_bdev_histogram_request
{
612 static const struct spdk_json_object_decoder rpc_get_bdev_histogram_request_decoders
[] = {
613 {"name", offsetof(struct rpc_get_bdev_histogram_request
, name
), spdk_json_decode_string
}
617 free_rpc_get_bdev_histogram_request(struct rpc_get_bdev_histogram_request
*r
)
623 _spdk_rpc_bdev_histogram_data_cb(void *cb_arg
, int status
, struct spdk_histogram_data
*histogram
)
625 struct spdk_jsonrpc_request
*request
= cb_arg
;
626 struct spdk_json_write_ctx
*w
;
628 char *encoded_histogram
;
629 size_t src_len
, dst_len
;
633 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
634 spdk_strerror(-status
));
638 src_len
= SPDK_HISTOGRAM_NUM_BUCKETS(histogram
) * sizeof(uint64_t);
639 dst_len
= spdk_base64_get_encoded_strlen(src_len
) + 1;
641 encoded_histogram
= malloc(dst_len
);
642 if (encoded_histogram
== NULL
) {
643 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
644 spdk_strerror(ENOMEM
));
648 rc
= spdk_base64_encode(encoded_histogram
, histogram
->bucket
, src_len
);
650 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INTERNAL_ERROR
,
652 goto free_encoded_histogram
;
655 w
= spdk_jsonrpc_begin_result(request
);
657 goto free_encoded_histogram
;
660 spdk_json_write_object_begin(w
);
661 spdk_json_write_named_string(w
, "histogram", encoded_histogram
);
662 spdk_json_write_named_int64(w
, "bucket_shift", histogram
->bucket_shift
);
663 spdk_json_write_named_int64(w
, "tsc_rate", spdk_get_ticks_hz());
664 spdk_json_write_object_end(w
);
665 spdk_jsonrpc_end_result(request
, w
);
667 free_encoded_histogram
:
668 free(encoded_histogram
);
670 spdk_histogram_data_free(histogram
);
674 spdk_rpc_get_bdev_histogram(struct spdk_jsonrpc_request
*request
,
675 const struct spdk_json_val
*params
)
677 struct rpc_get_bdev_histogram_request req
= {NULL
};
678 struct spdk_histogram_data
*histogram
;
679 struct spdk_bdev
*bdev
;
682 if (spdk_json_decode_object(params
, rpc_get_bdev_histogram_request_decoders
,
683 SPDK_COUNTOF(rpc_get_bdev_histogram_request_decoders
),
685 SPDK_ERRLOG("spdk_json_decode_object failed\n");
690 bdev
= spdk_bdev_get_by_name(req
.name
);
696 histogram
= spdk_histogram_data_alloc();
697 if (histogram
== NULL
) {
702 spdk_bdev_histogram_get(bdev
, histogram
, _spdk_rpc_bdev_histogram_data_cb
, request
);
704 free_rpc_get_bdev_histogram_request(&req
);
708 free_rpc_get_bdev_histogram_request(&req
);
709 spdk_jsonrpc_send_error_response(request
, SPDK_JSONRPC_ERROR_INVALID_PARAMS
, spdk_strerror(-rc
));
712 SPDK_RPC_REGISTER("get_bdev_histogram", spdk_rpc_get_bdev_histogram
, SPDK_RPC_RUNTIME
)