1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2018 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/bdev.h" 7 8 #include "spdk/env.h" 9 #include "spdk/rpc.h" 10 #include "spdk/util.h" 11 #include "spdk/string.h" 12 #include "spdk/base64.h" 13 #include "spdk/bdev_module.h" 14 #include "spdk/dma.h" 15 16 #include "spdk/log.h" 17 18 #include "bdev_internal.h" 19 20 static void 21 dummy_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx) 22 { 23 } 24 25 struct spdk_rpc_set_bdev_opts { 26 uint32_t bdev_io_pool_size; 27 uint32_t bdev_io_cache_size; 28 bool bdev_auto_examine; 29 uint32_t small_buf_pool_size; 30 uint32_t large_buf_pool_size; 31 }; 32 33 static const struct spdk_json_object_decoder rpc_set_bdev_opts_decoders[] = { 34 {"bdev_io_pool_size", offsetof(struct spdk_rpc_set_bdev_opts, bdev_io_pool_size), spdk_json_decode_uint32, true}, 35 {"bdev_io_cache_size", offsetof(struct spdk_rpc_set_bdev_opts, bdev_io_cache_size), spdk_json_decode_uint32, true}, 36 {"bdev_auto_examine", offsetof(struct spdk_rpc_set_bdev_opts, bdev_auto_examine), spdk_json_decode_bool, true}, 37 {"small_buf_pool_size", offsetof(struct spdk_rpc_set_bdev_opts, small_buf_pool_size), spdk_json_decode_uint32, true}, 38 {"large_buf_pool_size", offsetof(struct spdk_rpc_set_bdev_opts, large_buf_pool_size), spdk_json_decode_uint32, true}, 39 }; 40 41 static void 42 rpc_bdev_set_options(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 43 { 44 struct spdk_rpc_set_bdev_opts rpc_opts; 45 struct spdk_bdev_opts bdev_opts; 46 int rc; 47 48 rpc_opts.bdev_io_pool_size = UINT32_MAX; 49 rpc_opts.bdev_io_cache_size = UINT32_MAX; 50 rpc_opts.small_buf_pool_size = UINT32_MAX; 51 rpc_opts.large_buf_pool_size = UINT32_MAX; 52 rpc_opts.bdev_auto_examine = true; 53 54 if (params != NULL) { 55 if (spdk_json_decode_object(params, rpc_set_bdev_opts_decoders, 56 SPDK_COUNTOF(rpc_set_bdev_opts_decoders), &rpc_opts)) { 57 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 58 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 59 "Invalid parameters"); 60 return; 61 } 62 } 63 64 spdk_bdev_get_opts(&bdev_opts, sizeof(bdev_opts)); 65 if (rpc_opts.bdev_io_pool_size != UINT32_MAX) { 66 bdev_opts.bdev_io_pool_size = rpc_opts.bdev_io_pool_size; 67 } 68 if (rpc_opts.bdev_io_cache_size != UINT32_MAX) { 69 bdev_opts.bdev_io_cache_size = rpc_opts.bdev_io_cache_size; 70 } 71 bdev_opts.bdev_auto_examine = rpc_opts.bdev_auto_examine; 72 if (rpc_opts.small_buf_pool_size != UINT32_MAX) { 73 bdev_opts.small_buf_pool_size = rpc_opts.small_buf_pool_size; 74 } 75 if (rpc_opts.large_buf_pool_size != UINT32_MAX) { 76 bdev_opts.large_buf_pool_size = rpc_opts.large_buf_pool_size; 77 } 78 79 rc = spdk_bdev_set_opts(&bdev_opts); 80 81 if (rc != 0) { 82 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 83 "Pool size %" PRIu32 " too small for cache size %" PRIu32, 84 bdev_opts.bdev_io_pool_size, bdev_opts.bdev_io_cache_size); 85 return; 86 } 87 88 spdk_jsonrpc_send_bool_response(request, true); 89 } 90 SPDK_RPC_REGISTER("bdev_set_options", rpc_bdev_set_options, SPDK_RPC_STARTUP) 91 92 static void 93 rpc_bdev_wait_for_examine_cpl(void *arg) 94 { 95 struct spdk_jsonrpc_request *request = arg; 96 97 spdk_jsonrpc_send_bool_response(request, true); 98 } 99 100 static void 101 rpc_bdev_wait_for_examine(struct spdk_jsonrpc_request *request, 102 const struct spdk_json_val *params) 103 { 104 int rc; 105 106 if (params != NULL) { 107 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 108 "bdev_wait_for_examine requires no parameters"); 109 return; 110 } 111 112 rc = spdk_bdev_wait_for_examine(rpc_bdev_wait_for_examine_cpl, request); 113 if (rc != 0) { 114 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 115 } 116 } 117 SPDK_RPC_REGISTER("bdev_wait_for_examine", rpc_bdev_wait_for_examine, SPDK_RPC_RUNTIME) 118 119 struct rpc_bdev_examine { 120 char *name; 121 }; 122 123 static void 124 free_rpc_bdev_examine(struct rpc_bdev_examine *r) 125 { 126 free(r->name); 127 } 128 129 static const struct spdk_json_object_decoder rpc_examine_bdev_decoders[] = { 130 {"name", offsetof(struct rpc_bdev_examine, name), spdk_json_decode_string}, 131 }; 132 133 static void 134 rpc_bdev_examine_bdev(struct spdk_jsonrpc_request *request, 135 const struct spdk_json_val *params) 136 { 137 struct rpc_bdev_examine req = {NULL}; 138 int rc; 139 140 if (spdk_json_decode_object(params, rpc_examine_bdev_decoders, 141 SPDK_COUNTOF(rpc_examine_bdev_decoders), 142 &req)) { 143 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 144 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 145 "spdk_json_decode_object failed"); 146 goto cleanup; 147 } 148 149 rc = spdk_bdev_examine(req.name); 150 if (rc != 0) { 151 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 152 goto cleanup; 153 } 154 155 spdk_jsonrpc_send_bool_response(request, true); 156 157 cleanup: 158 free_rpc_bdev_examine(&req); 159 } 160 SPDK_RPC_REGISTER("bdev_examine", rpc_bdev_examine_bdev, SPDK_RPC_RUNTIME) 161 162 struct rpc_get_iostat_ctx { 163 int bdev_count; 164 int rc; 165 struct spdk_jsonrpc_request *request; 166 struct spdk_json_write_ctx *w; 167 bool per_channel; 168 }; 169 170 struct bdev_get_iostat_ctx { 171 struct spdk_bdev_io_stat *stat; 172 struct rpc_get_iostat_ctx *rpc_ctx; 173 struct spdk_bdev_desc *desc; 174 }; 175 176 static void 177 rpc_get_iostat_started(struct rpc_get_iostat_ctx *rpc_ctx, struct spdk_bdev_desc *desc) 178 { 179 struct spdk_bdev *bdev; 180 181 rpc_ctx->w = spdk_jsonrpc_begin_result(rpc_ctx->request); 182 183 spdk_json_write_object_begin(rpc_ctx->w); 184 spdk_json_write_named_uint64(rpc_ctx->w, "tick_rate", spdk_get_ticks_hz()); 185 spdk_json_write_named_uint64(rpc_ctx->w, "ticks", spdk_get_ticks()); 186 187 if (rpc_ctx->per_channel == false) { 188 spdk_json_write_named_array_begin(rpc_ctx->w, "bdevs"); 189 } else { 190 bdev = spdk_bdev_desc_get_bdev(desc); 191 192 spdk_json_write_named_string(rpc_ctx->w, "name", spdk_bdev_get_name(bdev)); 193 spdk_json_write_named_array_begin(rpc_ctx->w, "channels"); 194 } 195 } 196 197 static void 198 rpc_get_iostat_done(struct rpc_get_iostat_ctx *rpc_ctx) 199 { 200 if (--rpc_ctx->bdev_count != 0) { 201 return; 202 } 203 204 if (rpc_ctx->rc == 0) { 205 spdk_json_write_array_end(rpc_ctx->w); 206 spdk_json_write_object_end(rpc_ctx->w); 207 spdk_jsonrpc_end_result(rpc_ctx->request, rpc_ctx->w); 208 } else { 209 /* Return error response after processing all specified bdevs 210 * completed or failed. 211 */ 212 spdk_jsonrpc_send_error_response(rpc_ctx->request, rpc_ctx->rc, 213 spdk_strerror(-rpc_ctx->rc)); 214 } 215 216 free(rpc_ctx); 217 } 218 219 static struct bdev_get_iostat_ctx * 220 bdev_iostat_ctx_alloc(void) 221 { 222 struct bdev_get_iostat_ctx *ctx; 223 224 ctx = calloc(1, sizeof(struct bdev_get_iostat_ctx)); 225 if (ctx == NULL) { 226 return NULL; 227 } 228 229 ctx->stat = bdev_io_stat_alloc(); 230 if (ctx->stat == NULL) { 231 free(ctx); 232 return NULL; 233 } 234 235 return ctx; 236 } 237 238 static void 239 bdev_iostat_ctx_free(struct bdev_get_iostat_ctx *ctx) 240 { 241 bdev_io_stat_free(ctx->stat); 242 free(ctx); 243 } 244 245 static void 246 bdev_get_iostat_done(struct spdk_bdev *bdev, struct spdk_bdev_io_stat *stat, 247 void *cb_arg, int rc) 248 { 249 struct bdev_get_iostat_ctx *bdev_ctx = cb_arg; 250 struct rpc_get_iostat_ctx *rpc_ctx = bdev_ctx->rpc_ctx; 251 struct spdk_json_write_ctx *w = rpc_ctx->w; 252 253 if (rc != 0 || rpc_ctx->rc != 0) { 254 if (rpc_ctx->rc == 0) { 255 rpc_ctx->rc = rc; 256 } 257 goto done; 258 } 259 260 assert(stat == bdev_ctx->stat); 261 262 spdk_json_write_object_begin(w); 263 264 spdk_json_write_named_string(w, "name", spdk_bdev_get_name(bdev)); 265 266 bdev_io_stat_dump_json(stat, w); 267 268 if (spdk_bdev_get_qd_sampling_period(bdev)) { 269 spdk_json_write_named_uint64(w, "queue_depth_polling_period", 270 spdk_bdev_get_qd_sampling_period(bdev)); 271 272 spdk_json_write_named_uint64(w, "queue_depth", spdk_bdev_get_qd(bdev)); 273 274 spdk_json_write_named_uint64(w, "io_time", spdk_bdev_get_io_time(bdev)); 275 276 spdk_json_write_named_uint64(w, "weighted_io_time", 277 spdk_bdev_get_weighted_io_time(bdev)); 278 } 279 280 spdk_json_write_object_end(w); 281 282 done: 283 rpc_get_iostat_done(rpc_ctx); 284 285 spdk_bdev_close(bdev_ctx->desc); 286 bdev_iostat_ctx_free(bdev_ctx); 287 } 288 289 static int 290 bdev_get_iostat(void *ctx, struct spdk_bdev *bdev) 291 { 292 struct rpc_get_iostat_ctx *rpc_ctx = ctx; 293 struct bdev_get_iostat_ctx *bdev_ctx; 294 int rc; 295 296 bdev_ctx = bdev_iostat_ctx_alloc(); 297 if (bdev_ctx == NULL) { 298 SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 299 return -ENOMEM; 300 } 301 302 rc = spdk_bdev_open_ext(spdk_bdev_get_name(bdev), false, dummy_bdev_event_cb, NULL, 303 &bdev_ctx->desc); 304 if (rc != 0) { 305 bdev_iostat_ctx_free(bdev_ctx); 306 SPDK_ERRLOG("Failed to open bdev\n"); 307 return rc; 308 } 309 310 rpc_ctx->bdev_count++; 311 bdev_ctx->rpc_ctx = rpc_ctx; 312 spdk_bdev_get_device_stat(bdev, bdev_ctx->stat, bdev_get_iostat_done, bdev_ctx); 313 314 return 0; 315 } 316 317 static void 318 bdev_get_per_channel_stat_done(struct spdk_bdev *bdev, void *ctx, int status) 319 { 320 struct bdev_get_iostat_ctx *bdev_ctx = ctx; 321 322 rpc_get_iostat_done(bdev_ctx->rpc_ctx); 323 324 spdk_bdev_close(bdev_ctx->desc); 325 326 bdev_iostat_ctx_free(bdev_ctx); 327 } 328 329 static void 330 bdev_get_per_channel_stat(struct spdk_bdev_channel_iter *i, struct spdk_bdev *bdev, 331 struct spdk_io_channel *ch, void *ctx) 332 { 333 struct bdev_get_iostat_ctx *bdev_ctx = ctx; 334 struct spdk_json_write_ctx *w = bdev_ctx->rpc_ctx->w; 335 336 spdk_bdev_get_io_stat(bdev, ch, bdev_ctx->stat); 337 338 spdk_json_write_object_begin(w); 339 spdk_json_write_named_uint64(w, "thread_id", spdk_thread_get_id(spdk_get_thread())); 340 bdev_io_stat_dump_json(bdev_ctx->stat, w); 341 spdk_json_write_object_end(w); 342 343 spdk_bdev_for_each_channel_continue(i, 0); 344 } 345 346 struct rpc_bdev_get_iostat { 347 char *name; 348 bool per_channel; 349 }; 350 351 static void 352 free_rpc_bdev_get_iostat(struct rpc_bdev_get_iostat *r) 353 { 354 free(r->name); 355 } 356 357 static const struct spdk_json_object_decoder rpc_bdev_get_iostat_decoders[] = { 358 {"name", offsetof(struct rpc_bdev_get_iostat, name), spdk_json_decode_string, true}, 359 {"per_channel", offsetof(struct rpc_bdev_get_iostat, per_channel), spdk_json_decode_bool, true}, 360 }; 361 362 static void 363 rpc_bdev_get_iostat(struct spdk_jsonrpc_request *request, 364 const struct spdk_json_val *params) 365 { 366 struct rpc_bdev_get_iostat req = {}; 367 struct spdk_bdev_desc *desc = NULL; 368 struct rpc_get_iostat_ctx *rpc_ctx; 369 struct bdev_get_iostat_ctx *bdev_ctx; 370 int rc; 371 372 if (params != NULL) { 373 if (spdk_json_decode_object(params, rpc_bdev_get_iostat_decoders, 374 SPDK_COUNTOF(rpc_bdev_get_iostat_decoders), 375 &req)) { 376 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 377 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 378 "spdk_json_decode_object failed"); 379 free_rpc_bdev_get_iostat(&req); 380 return; 381 } 382 383 if (req.per_channel == true && !req.name) { 384 SPDK_ERRLOG("Bdev name is required for per channel IO statistics\n"); 385 spdk_jsonrpc_send_error_response(request, -EINVAL, spdk_strerror(EINVAL)); 386 free_rpc_bdev_get_iostat(&req); 387 return; 388 } 389 390 if (req.name) { 391 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 392 if (rc != 0) { 393 SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 394 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 395 free_rpc_bdev_get_iostat(&req); 396 return; 397 } 398 } 399 } 400 401 free_rpc_bdev_get_iostat(&req); 402 403 rpc_ctx = calloc(1, sizeof(struct rpc_get_iostat_ctx)); 404 if (rpc_ctx == NULL) { 405 SPDK_ERRLOG("Failed to allocate rpc_iostat_ctx struct\n"); 406 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 407 return; 408 } 409 410 /* 411 * Increment initial bdev_count so that it will never reach 0 in the middle 412 * of iterating. 413 */ 414 rpc_ctx->bdev_count++; 415 rpc_ctx->request = request; 416 rpc_ctx->per_channel = req.per_channel; 417 418 if (desc != NULL) { 419 bdev_ctx = bdev_iostat_ctx_alloc(); 420 if (bdev_ctx == NULL) { 421 SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 422 rpc_ctx->rc = -ENOMEM; 423 424 spdk_bdev_close(desc); 425 } else { 426 bdev_ctx->desc = desc; 427 428 rpc_ctx->bdev_count++; 429 bdev_ctx->rpc_ctx = rpc_ctx; 430 if (req.per_channel == false) { 431 spdk_bdev_get_device_stat(spdk_bdev_desc_get_bdev(desc), bdev_ctx->stat, 432 bdev_get_iostat_done, bdev_ctx); 433 } else { 434 spdk_bdev_for_each_channel(spdk_bdev_desc_get_bdev(desc), 435 bdev_get_per_channel_stat, 436 bdev_ctx, 437 bdev_get_per_channel_stat_done); 438 } 439 } 440 } else { 441 rc = spdk_for_each_bdev(rpc_ctx, bdev_get_iostat); 442 if (rc != 0 && rpc_ctx->rc == 0) { 443 rpc_ctx->rc = rc; 444 } 445 } 446 447 if (rpc_ctx->rc == 0) { 448 /* We want to fail the RPC for all failures. The callback function to 449 * spdk_bdev_for_each_channel() is executed after stack unwinding if 450 * successful. Hence defer starting RPC response until it is ensured that 451 * all spdk_bdev_for_each_channel() calls will succeed or there is no bdev. 452 */ 453 rpc_get_iostat_started(rpc_ctx, desc); 454 } 455 456 rpc_get_iostat_done(rpc_ctx); 457 } 458 SPDK_RPC_REGISTER("bdev_get_iostat", rpc_bdev_get_iostat, SPDK_RPC_RUNTIME) 459 460 struct rpc_reset_iostat_ctx { 461 int bdev_count; 462 int rc; 463 struct spdk_jsonrpc_request *request; 464 struct spdk_json_write_ctx *w; 465 enum bdev_reset_stat_mode mode; 466 }; 467 468 struct bdev_reset_iostat_ctx { 469 struct rpc_reset_iostat_ctx *rpc_ctx; 470 struct spdk_bdev_desc *desc; 471 }; 472 473 static void 474 rpc_reset_iostat_done(struct rpc_reset_iostat_ctx *rpc_ctx) 475 { 476 if (--rpc_ctx->bdev_count != 0) { 477 return; 478 } 479 480 if (rpc_ctx->rc == 0) { 481 spdk_jsonrpc_send_bool_response(rpc_ctx->request, true); 482 } else { 483 spdk_jsonrpc_send_error_response(rpc_ctx->request, rpc_ctx->rc, 484 spdk_strerror(-rpc_ctx->rc)); 485 } 486 487 free(rpc_ctx); 488 } 489 490 static void 491 bdev_reset_iostat_done(struct spdk_bdev *bdev, void *cb_arg, int rc) 492 { 493 struct bdev_reset_iostat_ctx *bdev_ctx = cb_arg; 494 struct rpc_reset_iostat_ctx *rpc_ctx = bdev_ctx->rpc_ctx; 495 496 if (rc != 0 || rpc_ctx->rc != 0) { 497 if (rpc_ctx->rc == 0) { 498 rpc_ctx->rc = rc; 499 } 500 } 501 502 rpc_reset_iostat_done(rpc_ctx); 503 504 spdk_bdev_close(bdev_ctx->desc); 505 free(bdev_ctx); 506 } 507 508 static int 509 bdev_reset_iostat(void *ctx, struct spdk_bdev *bdev) 510 { 511 struct rpc_reset_iostat_ctx *rpc_ctx = ctx; 512 struct bdev_reset_iostat_ctx *bdev_ctx; 513 int rc; 514 515 bdev_ctx = calloc(1, sizeof(struct bdev_reset_iostat_ctx)); 516 if (bdev_ctx == NULL) { 517 SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 518 return -ENOMEM; 519 } 520 521 rc = spdk_bdev_open_ext(spdk_bdev_get_name(bdev), false, dummy_bdev_event_cb, NULL, 522 &bdev_ctx->desc); 523 if (rc != 0) { 524 free(bdev_ctx); 525 SPDK_ERRLOG("Failed to open bdev\n"); 526 return rc; 527 } 528 529 rpc_ctx->bdev_count++; 530 bdev_ctx->rpc_ctx = rpc_ctx; 531 bdev_reset_device_stat(bdev, rpc_ctx->mode, bdev_reset_iostat_done, bdev_ctx); 532 533 return 0; 534 } 535 536 struct rpc_bdev_reset_iostat { 537 char *name; 538 enum bdev_reset_stat_mode mode; 539 }; 540 541 static void 542 free_rpc_bdev_reset_iostat(struct rpc_bdev_reset_iostat *r) 543 { 544 free(r->name); 545 } 546 547 static int 548 rpc_decode_reset_iostat_mode(const struct spdk_json_val *val, void *out) 549 { 550 enum bdev_reset_stat_mode *mode = out; 551 552 if (spdk_json_strequal(val, "all") == true) { 553 *mode = BDEV_RESET_STAT_ALL; 554 } else if (spdk_json_strequal(val, "maxmin") == true) { 555 *mode = BDEV_RESET_STAT_MAXMIN; 556 } else { 557 SPDK_NOTICELOG("Invalid parameter value: mode\n"); 558 return -EINVAL; 559 } 560 561 return 0; 562 } 563 564 static const struct spdk_json_object_decoder rpc_bdev_reset_iostat_decoders[] = { 565 {"name", offsetof(struct rpc_bdev_reset_iostat, name), spdk_json_decode_string, true}, 566 {"mode", offsetof(struct rpc_bdev_reset_iostat, mode), rpc_decode_reset_iostat_mode, true}, 567 }; 568 569 static void 570 rpc_bdev_reset_iostat(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 571 { 572 struct rpc_bdev_reset_iostat req = { .mode = BDEV_RESET_STAT_ALL, }; 573 struct spdk_bdev_desc *desc = NULL; 574 struct rpc_reset_iostat_ctx *rpc_ctx; 575 struct bdev_reset_iostat_ctx *bdev_ctx; 576 int rc; 577 578 if (params != NULL) { 579 if (spdk_json_decode_object(params, rpc_bdev_reset_iostat_decoders, 580 SPDK_COUNTOF(rpc_bdev_reset_iostat_decoders), 581 &req)) { 582 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 583 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 584 "spdk_json_decode_object failed"); 585 free_rpc_bdev_reset_iostat(&req); 586 return; 587 } 588 589 if (req.name) { 590 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 591 if (rc != 0) { 592 SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 593 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 594 free_rpc_bdev_reset_iostat(&req); 595 return; 596 } 597 } 598 } 599 600 601 rpc_ctx = calloc(1, sizeof(struct rpc_reset_iostat_ctx)); 602 if (rpc_ctx == NULL) { 603 SPDK_ERRLOG("Failed to allocate rpc_iostat_ctx struct\n"); 604 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 605 free_rpc_bdev_reset_iostat(&req); 606 return; 607 } 608 609 /* 610 * Increment initial bdev_count so that it will never reach 0 in the middle 611 * of iterating. 612 */ 613 rpc_ctx->bdev_count++; 614 rpc_ctx->request = request; 615 rpc_ctx->mode = req.mode; 616 617 free_rpc_bdev_reset_iostat(&req); 618 619 if (desc != NULL) { 620 bdev_ctx = calloc(1, sizeof(struct bdev_reset_iostat_ctx)); 621 if (bdev_ctx == NULL) { 622 SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 623 rpc_ctx->rc = -ENOMEM; 624 625 spdk_bdev_close(desc); 626 } else { 627 bdev_ctx->desc = desc; 628 629 rpc_ctx->bdev_count++; 630 bdev_ctx->rpc_ctx = rpc_ctx; 631 bdev_reset_device_stat(spdk_bdev_desc_get_bdev(desc), rpc_ctx->mode, 632 bdev_reset_iostat_done, bdev_ctx); 633 } 634 } else { 635 rc = spdk_for_each_bdev(rpc_ctx, bdev_reset_iostat); 636 if (rc != 0 && rpc_ctx->rc == 0) { 637 rpc_ctx->rc = rc; 638 } 639 } 640 641 rpc_reset_iostat_done(rpc_ctx); 642 } 643 SPDK_RPC_REGISTER("bdev_reset_iostat", rpc_bdev_reset_iostat, SPDK_RPC_RUNTIME) 644 645 static int 646 rpc_dump_bdev_info(void *ctx, struct spdk_bdev *bdev) 647 { 648 struct spdk_json_write_ctx *w = ctx; 649 struct spdk_bdev_alias *tmp; 650 uint64_t qos_limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES]; 651 struct spdk_memory_domain **domains; 652 int i, rc; 653 654 spdk_json_write_object_begin(w); 655 656 spdk_json_write_named_string(w, "name", spdk_bdev_get_name(bdev)); 657 658 spdk_json_write_named_array_begin(w, "aliases"); 659 660 TAILQ_FOREACH(tmp, spdk_bdev_get_aliases(bdev), tailq) { 661 spdk_json_write_string(w, tmp->alias.name); 662 } 663 664 spdk_json_write_array_end(w); 665 666 spdk_json_write_named_string(w, "product_name", spdk_bdev_get_product_name(bdev)); 667 668 spdk_json_write_named_uint32(w, "block_size", spdk_bdev_get_block_size(bdev)); 669 670 spdk_json_write_named_uint64(w, "num_blocks", spdk_bdev_get_num_blocks(bdev)); 671 672 if (!spdk_mem_all_zero(&bdev->uuid, sizeof(bdev->uuid))) { 673 char uuid_str[SPDK_UUID_STRING_LEN]; 674 675 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid); 676 spdk_json_write_named_string(w, "uuid", uuid_str); 677 } 678 679 if (spdk_bdev_get_md_size(bdev) != 0) { 680 spdk_json_write_named_uint32(w, "md_size", spdk_bdev_get_md_size(bdev)); 681 spdk_json_write_named_bool(w, "md_interleave", spdk_bdev_is_md_interleaved(bdev)); 682 spdk_json_write_named_uint32(w, "dif_type", spdk_bdev_get_dif_type(bdev)); 683 if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) { 684 spdk_json_write_named_bool(w, "dif_is_head_of_md", spdk_bdev_is_dif_head_of_md(bdev)); 685 spdk_json_write_named_object_begin(w, "enabled_dif_check_types"); 686 spdk_json_write_named_bool(w, "reftag", 687 spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG)); 688 spdk_json_write_named_bool(w, "apptag", 689 spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_APPTAG)); 690 spdk_json_write_named_bool(w, "guard", 691 spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD)); 692 spdk_json_write_object_end(w); 693 } 694 } 695 696 spdk_json_write_named_object_begin(w, "assigned_rate_limits"); 697 spdk_bdev_get_qos_rate_limits(bdev, qos_limits); 698 for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) { 699 spdk_json_write_named_uint64(w, spdk_bdev_get_qos_rpc_type(i), qos_limits[i]); 700 } 701 spdk_json_write_object_end(w); 702 703 spdk_json_write_named_bool(w, "claimed", (bdev->internal.claim_module != NULL)); 704 705 spdk_json_write_named_bool(w, "zoned", bdev->zoned); 706 if (bdev->zoned) { 707 spdk_json_write_named_uint64(w, "zone_size", bdev->zone_size); 708 spdk_json_write_named_uint64(w, "max_open_zones", bdev->max_open_zones); 709 spdk_json_write_named_uint64(w, "optimal_open_zones", bdev->optimal_open_zones); 710 } 711 712 spdk_json_write_named_object_begin(w, "supported_io_types"); 713 spdk_json_write_named_bool(w, "read", 714 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_READ)); 715 spdk_json_write_named_bool(w, "write", 716 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE)); 717 spdk_json_write_named_bool(w, "unmap", 718 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)); 719 spdk_json_write_named_bool(w, "write_zeroes", 720 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE_ZEROES)); 721 spdk_json_write_named_bool(w, "flush", 722 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_FLUSH)); 723 spdk_json_write_named_bool(w, "reset", 724 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_RESET)); 725 spdk_json_write_named_bool(w, "compare", 726 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_COMPARE)); 727 spdk_json_write_named_bool(w, "compare_and_write", 728 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_COMPARE_AND_WRITE)); 729 spdk_json_write_named_bool(w, "abort", 730 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_ABORT)); 731 spdk_json_write_named_bool(w, "nvme_admin", 732 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_ADMIN)); 733 spdk_json_write_named_bool(w, "nvme_io", 734 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_IO)); 735 spdk_json_write_object_end(w); 736 737 rc = spdk_bdev_get_memory_domains(bdev, NULL, 0); 738 if (rc > 0) { 739 domains = calloc(rc, sizeof(struct spdk_memory_domain *)); 740 if (domains) { 741 i = spdk_bdev_get_memory_domains(bdev, domains, rc); 742 if (i == rc) { 743 spdk_json_write_named_array_begin(w, "memory_domains"); 744 for (i = 0; i < rc; i++) { 745 spdk_json_write_object_begin(w); 746 spdk_json_write_named_string(w, "dma_device_id", spdk_memory_domain_get_dma_device_id(domains[i])); 747 spdk_json_write_named_int32(w, "dma_device_type", 748 spdk_memory_domain_get_dma_device_type(domains[i])); 749 spdk_json_write_object_end(w); 750 } 751 spdk_json_write_array_end(w); 752 } else { 753 SPDK_ERRLOG("Unexpected number of memory domains %d (should be %d)\n", i, rc); 754 } 755 756 free(domains); 757 } else { 758 SPDK_ERRLOG("Memory allocation failed\n"); 759 } 760 } 761 762 spdk_json_write_named_object_begin(w, "driver_specific"); 763 spdk_bdev_dump_info_json(bdev, w); 764 spdk_json_write_object_end(w); 765 766 spdk_json_write_object_end(w); 767 768 return 0; 769 } 770 771 struct rpc_bdev_get_bdevs { 772 char *name; 773 uint64_t timeout; 774 }; 775 776 struct rpc_bdev_get_bdevs_ctx { 777 struct rpc_bdev_get_bdevs rpc; 778 struct spdk_jsonrpc_request *request; 779 struct spdk_poller *poller; 780 uint64_t timeout_ticks; 781 }; 782 783 static void 784 free_rpc_bdev_get_bdevs(struct rpc_bdev_get_bdevs *r) 785 { 786 free(r->name); 787 } 788 789 static const struct spdk_json_object_decoder rpc_bdev_get_bdevs_decoders[] = { 790 {"name", offsetof(struct rpc_bdev_get_bdevs, name), spdk_json_decode_string, true}, 791 {"timeout", offsetof(struct rpc_bdev_get_bdevs, timeout), spdk_json_decode_uint64, true}, 792 }; 793 794 static int 795 get_bdevs_poller(void *_ctx) 796 { 797 struct rpc_bdev_get_bdevs_ctx *ctx = _ctx; 798 struct spdk_json_write_ctx *w; 799 struct spdk_bdev_desc *desc; 800 int rc; 801 802 rc = spdk_bdev_open_ext(ctx->rpc.name, false, dummy_bdev_event_cb, NULL, &desc); 803 if (rc != 0 && spdk_get_ticks() < ctx->timeout_ticks) { 804 return SPDK_POLLER_BUSY; 805 } 806 807 if (rc != 0) { 808 SPDK_ERRLOG("Timed out while waiting for bdev '%s' to appear\n", ctx->rpc.name); 809 spdk_jsonrpc_send_error_response(ctx->request, -ENODEV, spdk_strerror(ENODEV)); 810 } else { 811 w = spdk_jsonrpc_begin_result(ctx->request); 812 spdk_json_write_array_begin(w); 813 rpc_dump_bdev_info(w, spdk_bdev_desc_get_bdev(desc)); 814 spdk_json_write_array_end(w); 815 spdk_jsonrpc_end_result(ctx->request, w); 816 817 spdk_bdev_close(desc); 818 } 819 820 spdk_poller_unregister(&ctx->poller); 821 free_rpc_bdev_get_bdevs(&ctx->rpc); 822 free(ctx); 823 824 return SPDK_POLLER_BUSY; 825 } 826 827 static void 828 rpc_bdev_get_bdevs(struct spdk_jsonrpc_request *request, 829 const struct spdk_json_val *params) 830 { 831 struct rpc_bdev_get_bdevs req = {}; 832 struct rpc_bdev_get_bdevs_ctx *ctx; 833 struct spdk_json_write_ctx *w; 834 struct spdk_bdev_desc *desc = NULL; 835 int rc; 836 837 if (params && spdk_json_decode_object(params, rpc_bdev_get_bdevs_decoders, 838 SPDK_COUNTOF(rpc_bdev_get_bdevs_decoders), 839 &req)) { 840 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 841 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 842 "spdk_json_decode_object failed"); 843 free_rpc_bdev_get_bdevs(&req); 844 return; 845 } 846 847 if (req.name) { 848 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 849 if (rc != 0) { 850 if (req.timeout == 0) { 851 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 852 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 853 free_rpc_bdev_get_bdevs(&req); 854 return; 855 } 856 857 ctx = calloc(1, sizeof(*ctx)); 858 if (ctx == NULL) { 859 SPDK_ERRLOG("Failed to allocate bdev_get_bdevs context\n"); 860 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 861 free_rpc_bdev_get_bdevs(&req); 862 return; 863 } 864 865 ctx->poller = SPDK_POLLER_REGISTER(get_bdevs_poller, ctx, 10 * 1000); 866 if (ctx->poller == NULL) { 867 SPDK_ERRLOG("Failed to register bdev_get_bdevs poller\n"); 868 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 869 free_rpc_bdev_get_bdevs(&req); 870 free(ctx); 871 return; 872 } 873 874 memcpy(&ctx->rpc, &req, sizeof(req)); 875 ctx->timeout_ticks = spdk_get_ticks() + req.timeout * 876 spdk_get_ticks_hz() / 1000ull; 877 ctx->request = request; 878 return; 879 } 880 } 881 882 free_rpc_bdev_get_bdevs(&req); 883 w = spdk_jsonrpc_begin_result(request); 884 spdk_json_write_array_begin(w); 885 886 if (desc != NULL) { 887 rpc_dump_bdev_info(w, spdk_bdev_desc_get_bdev(desc)); 888 spdk_bdev_close(desc); 889 } else { 890 spdk_for_each_bdev(w, rpc_dump_bdev_info); 891 } 892 893 spdk_json_write_array_end(w); 894 895 spdk_jsonrpc_end_result(request, w); 896 } 897 SPDK_RPC_REGISTER("bdev_get_bdevs", rpc_bdev_get_bdevs, SPDK_RPC_RUNTIME) 898 899 struct rpc_bdev_set_qd_sampling_period { 900 char *name; 901 uint64_t period; 902 }; 903 904 static void 905 free_rpc_bdev_set_qd_sampling_period(struct rpc_bdev_set_qd_sampling_period *r) 906 { 907 free(r->name); 908 } 909 910 static const struct spdk_json_object_decoder 911 rpc_bdev_set_qd_sampling_period_decoders[] = { 912 {"name", offsetof(struct rpc_bdev_set_qd_sampling_period, name), spdk_json_decode_string}, 913 {"period", offsetof(struct rpc_bdev_set_qd_sampling_period, period), spdk_json_decode_uint64}, 914 }; 915 916 static void 917 rpc_bdev_set_qd_sampling_period(struct spdk_jsonrpc_request *request, 918 const struct spdk_json_val *params) 919 { 920 struct rpc_bdev_set_qd_sampling_period req = {0}; 921 struct spdk_bdev_desc *desc; 922 int rc; 923 924 if (spdk_json_decode_object(params, rpc_bdev_set_qd_sampling_period_decoders, 925 SPDK_COUNTOF(rpc_bdev_set_qd_sampling_period_decoders), 926 &req)) { 927 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 928 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 929 "spdk_json_decode_object failed"); 930 goto cleanup; 931 } 932 933 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 934 if (rc != 0) { 935 SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 936 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 937 goto cleanup; 938 } 939 940 spdk_bdev_set_qd_sampling_period(spdk_bdev_desc_get_bdev(desc), req.period); 941 spdk_jsonrpc_send_bool_response(request, true); 942 943 spdk_bdev_close(desc); 944 945 cleanup: 946 free_rpc_bdev_set_qd_sampling_period(&req); 947 } 948 SPDK_RPC_REGISTER("bdev_set_qd_sampling_period", 949 rpc_bdev_set_qd_sampling_period, 950 SPDK_RPC_RUNTIME) 951 952 struct rpc_bdev_set_qos_limit { 953 char *name; 954 uint64_t limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES]; 955 }; 956 957 static void 958 free_rpc_bdev_set_qos_limit(struct rpc_bdev_set_qos_limit *r) 959 { 960 free(r->name); 961 } 962 963 static const struct spdk_json_object_decoder rpc_bdev_set_qos_limit_decoders[] = { 964 {"name", offsetof(struct rpc_bdev_set_qos_limit, name), spdk_json_decode_string}, 965 { 966 "rw_ios_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 967 limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT]), 968 spdk_json_decode_uint64, true 969 }, 970 { 971 "rw_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 972 limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT]), 973 spdk_json_decode_uint64, true 974 }, 975 { 976 "r_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 977 limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT]), 978 spdk_json_decode_uint64, true 979 }, 980 { 981 "w_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 982 limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT]), 983 spdk_json_decode_uint64, true 984 }, 985 }; 986 987 static void 988 rpc_bdev_set_qos_limit_complete(void *cb_arg, int status) 989 { 990 struct spdk_jsonrpc_request *request = cb_arg; 991 992 if (status != 0) { 993 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 994 "Failed to configure rate limit: %s", 995 spdk_strerror(-status)); 996 return; 997 } 998 999 spdk_jsonrpc_send_bool_response(request, true); 1000 } 1001 1002 static void 1003 rpc_bdev_set_qos_limit(struct spdk_jsonrpc_request *request, 1004 const struct spdk_json_val *params) 1005 { 1006 struct rpc_bdev_set_qos_limit req = {NULL, {UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX}}; 1007 struct spdk_bdev_desc *desc; 1008 int i, rc; 1009 1010 if (spdk_json_decode_object(params, rpc_bdev_set_qos_limit_decoders, 1011 SPDK_COUNTOF(rpc_bdev_set_qos_limit_decoders), 1012 &req)) { 1013 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1014 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1015 "spdk_json_decode_object failed"); 1016 goto cleanup; 1017 } 1018 1019 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 1020 if (rc != 0) { 1021 SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 1022 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1023 goto cleanup; 1024 } 1025 1026 for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) { 1027 if (req.limits[i] != UINT64_MAX) { 1028 break; 1029 } 1030 } 1031 if (i == SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES) { 1032 SPDK_ERRLOG("no rate limits specified\n"); 1033 spdk_bdev_close(desc); 1034 spdk_jsonrpc_send_error_response(request, -EINVAL, "No rate limits specified"); 1035 goto cleanup; 1036 } 1037 1038 spdk_bdev_set_qos_rate_limits(spdk_bdev_desc_get_bdev(desc), req.limits, 1039 rpc_bdev_set_qos_limit_complete, request); 1040 1041 spdk_bdev_close(desc); 1042 1043 cleanup: 1044 free_rpc_bdev_set_qos_limit(&req); 1045 } 1046 1047 SPDK_RPC_REGISTER("bdev_set_qos_limit", rpc_bdev_set_qos_limit, SPDK_RPC_RUNTIME) 1048 1049 /* SPDK_RPC_ENABLE_BDEV_HISTOGRAM */ 1050 1051 struct rpc_bdev_enable_histogram_request { 1052 char *name; 1053 bool enable; 1054 }; 1055 1056 static void 1057 free_rpc_bdev_enable_histogram_request(struct rpc_bdev_enable_histogram_request *r) 1058 { 1059 free(r->name); 1060 } 1061 1062 static const struct spdk_json_object_decoder rpc_bdev_enable_histogram_request_decoders[] = { 1063 {"name", offsetof(struct rpc_bdev_enable_histogram_request, name), spdk_json_decode_string}, 1064 {"enable", offsetof(struct rpc_bdev_enable_histogram_request, enable), spdk_json_decode_bool}, 1065 }; 1066 1067 static void 1068 bdev_histogram_status_cb(void *cb_arg, int status) 1069 { 1070 struct spdk_jsonrpc_request *request = cb_arg; 1071 1072 spdk_jsonrpc_send_bool_response(request, status == 0); 1073 } 1074 1075 static void 1076 rpc_bdev_enable_histogram(struct spdk_jsonrpc_request *request, 1077 const struct spdk_json_val *params) 1078 { 1079 struct rpc_bdev_enable_histogram_request req = {NULL}; 1080 struct spdk_bdev_desc *desc; 1081 int rc; 1082 1083 if (spdk_json_decode_object(params, rpc_bdev_enable_histogram_request_decoders, 1084 SPDK_COUNTOF(rpc_bdev_enable_histogram_request_decoders), 1085 &req)) { 1086 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1087 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1088 "spdk_json_decode_object failed"); 1089 goto cleanup; 1090 } 1091 1092 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 1093 if (rc != 0) { 1094 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1095 goto cleanup; 1096 } 1097 1098 spdk_bdev_histogram_enable(spdk_bdev_desc_get_bdev(desc), bdev_histogram_status_cb, 1099 request, req.enable); 1100 1101 spdk_bdev_close(desc); 1102 1103 cleanup: 1104 free_rpc_bdev_enable_histogram_request(&req); 1105 } 1106 1107 SPDK_RPC_REGISTER("bdev_enable_histogram", rpc_bdev_enable_histogram, SPDK_RPC_RUNTIME) 1108 1109 /* SPDK_RPC_GET_BDEV_HISTOGRAM */ 1110 1111 struct rpc_bdev_get_histogram_request { 1112 char *name; 1113 }; 1114 1115 static const struct spdk_json_object_decoder rpc_bdev_get_histogram_request_decoders[] = { 1116 {"name", offsetof(struct rpc_bdev_get_histogram_request, name), spdk_json_decode_string} 1117 }; 1118 1119 static void 1120 free_rpc_bdev_get_histogram_request(struct rpc_bdev_get_histogram_request *r) 1121 { 1122 free(r->name); 1123 } 1124 1125 static void 1126 _rpc_bdev_histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram) 1127 { 1128 struct spdk_jsonrpc_request *request = cb_arg; 1129 struct spdk_json_write_ctx *w; 1130 int rc; 1131 char *encoded_histogram; 1132 size_t src_len, dst_len; 1133 1134 1135 if (status != 0) { 1136 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1137 spdk_strerror(-status)); 1138 goto invalid; 1139 } 1140 1141 src_len = SPDK_HISTOGRAM_NUM_BUCKETS(histogram) * sizeof(uint64_t); 1142 dst_len = spdk_base64_get_encoded_strlen(src_len) + 1; 1143 1144 encoded_histogram = malloc(dst_len); 1145 if (encoded_histogram == NULL) { 1146 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1147 spdk_strerror(ENOMEM)); 1148 goto invalid; 1149 } 1150 1151 rc = spdk_base64_encode(encoded_histogram, histogram->bucket, src_len); 1152 if (rc != 0) { 1153 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1154 spdk_strerror(-rc)); 1155 goto free_encoded_histogram; 1156 } 1157 1158 w = spdk_jsonrpc_begin_result(request); 1159 spdk_json_write_object_begin(w); 1160 spdk_json_write_named_string(w, "histogram", encoded_histogram); 1161 spdk_json_write_named_int64(w, "bucket_shift", histogram->bucket_shift); 1162 spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz()); 1163 spdk_json_write_object_end(w); 1164 spdk_jsonrpc_end_result(request, w); 1165 1166 free_encoded_histogram: 1167 free(encoded_histogram); 1168 invalid: 1169 spdk_histogram_data_free(histogram); 1170 } 1171 1172 static void 1173 rpc_bdev_get_histogram(struct spdk_jsonrpc_request *request, 1174 const struct spdk_json_val *params) 1175 { 1176 struct rpc_bdev_get_histogram_request req = {NULL}; 1177 struct spdk_histogram_data *histogram; 1178 struct spdk_bdev_desc *desc; 1179 int rc; 1180 1181 if (spdk_json_decode_object(params, rpc_bdev_get_histogram_request_decoders, 1182 SPDK_COUNTOF(rpc_bdev_get_histogram_request_decoders), 1183 &req)) { 1184 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1185 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1186 "spdk_json_decode_object failed"); 1187 goto cleanup; 1188 } 1189 1190 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 1191 if (rc != 0) { 1192 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1193 goto cleanup; 1194 } 1195 1196 histogram = spdk_histogram_data_alloc(); 1197 if (histogram == NULL) { 1198 spdk_bdev_close(desc); 1199 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1200 goto cleanup; 1201 } 1202 1203 spdk_bdev_histogram_get(spdk_bdev_desc_get_bdev(desc), histogram, 1204 _rpc_bdev_histogram_data_cb, request); 1205 1206 spdk_bdev_close(desc); 1207 1208 cleanup: 1209 free_rpc_bdev_get_histogram_request(&req); 1210 } 1211 1212 SPDK_RPC_REGISTER("bdev_get_histogram", rpc_bdev_get_histogram, SPDK_RPC_RUNTIME) 1213