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(bool iostat_ext) 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_alloc_io_stat(iostat_ext); 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_free_io_stat(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_dump_io_stat_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 if (bdev->fn_table->dump_device_stat_json) { 281 spdk_json_write_named_object_begin(w, "driver_specific"); 282 bdev->fn_table->dump_device_stat_json(bdev->ctxt, w); 283 spdk_json_write_object_end(w); 284 } 285 286 spdk_json_write_object_end(w); 287 288 done: 289 rpc_get_iostat_done(rpc_ctx); 290 291 spdk_bdev_close(bdev_ctx->desc); 292 bdev_iostat_ctx_free(bdev_ctx); 293 } 294 295 static int 296 bdev_get_iostat(void *ctx, struct spdk_bdev *bdev) 297 { 298 struct rpc_get_iostat_ctx *rpc_ctx = ctx; 299 struct bdev_get_iostat_ctx *bdev_ctx; 300 int rc; 301 302 bdev_ctx = bdev_iostat_ctx_alloc(true); 303 if (bdev_ctx == NULL) { 304 SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 305 return -ENOMEM; 306 } 307 308 rc = spdk_bdev_open_ext(spdk_bdev_get_name(bdev), false, dummy_bdev_event_cb, NULL, 309 &bdev_ctx->desc); 310 if (rc != 0) { 311 bdev_iostat_ctx_free(bdev_ctx); 312 SPDK_ERRLOG("Failed to open bdev\n"); 313 return rc; 314 } 315 316 rpc_ctx->bdev_count++; 317 bdev_ctx->rpc_ctx = rpc_ctx; 318 spdk_bdev_get_device_stat(bdev, bdev_ctx->stat, bdev_get_iostat_done, bdev_ctx); 319 320 return 0; 321 } 322 323 static void 324 bdev_get_per_channel_stat_done(struct spdk_bdev *bdev, void *ctx, int status) 325 { 326 struct bdev_get_iostat_ctx *bdev_ctx = ctx; 327 328 rpc_get_iostat_done(bdev_ctx->rpc_ctx); 329 330 spdk_bdev_close(bdev_ctx->desc); 331 332 bdev_iostat_ctx_free(bdev_ctx); 333 } 334 335 static void 336 bdev_get_per_channel_stat(struct spdk_bdev_channel_iter *i, struct spdk_bdev *bdev, 337 struct spdk_io_channel *ch, void *ctx) 338 { 339 struct bdev_get_iostat_ctx *bdev_ctx = ctx; 340 struct spdk_json_write_ctx *w = bdev_ctx->rpc_ctx->w; 341 342 spdk_bdev_get_io_stat(bdev, ch, bdev_ctx->stat); 343 344 spdk_json_write_object_begin(w); 345 spdk_json_write_named_uint64(w, "thread_id", spdk_thread_get_id(spdk_get_thread())); 346 bdev_dump_io_stat_json(bdev_ctx->stat, w); 347 spdk_json_write_object_end(w); 348 349 spdk_bdev_for_each_channel_continue(i, 0); 350 } 351 352 struct rpc_bdev_get_iostat { 353 char *name; 354 bool per_channel; 355 }; 356 357 static void 358 free_rpc_bdev_get_iostat(struct rpc_bdev_get_iostat *r) 359 { 360 free(r->name); 361 } 362 363 static const struct spdk_json_object_decoder rpc_bdev_get_iostat_decoders[] = { 364 {"name", offsetof(struct rpc_bdev_get_iostat, name), spdk_json_decode_string, true}, 365 {"per_channel", offsetof(struct rpc_bdev_get_iostat, per_channel), spdk_json_decode_bool, true}, 366 }; 367 368 static void 369 rpc_bdev_get_iostat(struct spdk_jsonrpc_request *request, 370 const struct spdk_json_val *params) 371 { 372 struct rpc_bdev_get_iostat req = {}; 373 struct spdk_bdev_desc *desc = NULL; 374 struct rpc_get_iostat_ctx *rpc_ctx; 375 struct bdev_get_iostat_ctx *bdev_ctx; 376 int rc; 377 378 if (params != NULL) { 379 if (spdk_json_decode_object(params, rpc_bdev_get_iostat_decoders, 380 SPDK_COUNTOF(rpc_bdev_get_iostat_decoders), 381 &req)) { 382 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 383 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 384 "spdk_json_decode_object failed"); 385 free_rpc_bdev_get_iostat(&req); 386 return; 387 } 388 389 if (req.per_channel == true && !req.name) { 390 SPDK_ERRLOG("Bdev name is required for per channel IO statistics\n"); 391 spdk_jsonrpc_send_error_response(request, -EINVAL, spdk_strerror(EINVAL)); 392 free_rpc_bdev_get_iostat(&req); 393 return; 394 } 395 396 if (req.name) { 397 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 398 if (rc != 0) { 399 SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 400 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 401 free_rpc_bdev_get_iostat(&req); 402 return; 403 } 404 } 405 } 406 407 free_rpc_bdev_get_iostat(&req); 408 409 rpc_ctx = calloc(1, sizeof(struct rpc_get_iostat_ctx)); 410 if (rpc_ctx == NULL) { 411 SPDK_ERRLOG("Failed to allocate rpc_iostat_ctx struct\n"); 412 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 413 return; 414 } 415 416 /* 417 * Increment initial bdev_count so that it will never reach 0 in the middle 418 * of iterating. 419 */ 420 rpc_ctx->bdev_count++; 421 rpc_ctx->request = request; 422 rpc_ctx->per_channel = req.per_channel; 423 424 if (desc != NULL) { 425 bdev_ctx = bdev_iostat_ctx_alloc(req.per_channel == false); 426 if (bdev_ctx == NULL) { 427 SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 428 rpc_ctx->rc = -ENOMEM; 429 430 spdk_bdev_close(desc); 431 } else { 432 bdev_ctx->desc = desc; 433 434 rpc_ctx->bdev_count++; 435 bdev_ctx->rpc_ctx = rpc_ctx; 436 if (req.per_channel == false) { 437 spdk_bdev_get_device_stat(spdk_bdev_desc_get_bdev(desc), bdev_ctx->stat, 438 bdev_get_iostat_done, bdev_ctx); 439 } else { 440 spdk_bdev_for_each_channel(spdk_bdev_desc_get_bdev(desc), 441 bdev_get_per_channel_stat, 442 bdev_ctx, 443 bdev_get_per_channel_stat_done); 444 } 445 } 446 } else { 447 rc = spdk_for_each_bdev(rpc_ctx, bdev_get_iostat); 448 if (rc != 0 && rpc_ctx->rc == 0) { 449 rpc_ctx->rc = rc; 450 } 451 } 452 453 if (rpc_ctx->rc == 0) { 454 /* We want to fail the RPC for all failures. The callback function to 455 * spdk_bdev_for_each_channel() is executed after stack unwinding if 456 * successful. Hence defer starting RPC response until it is ensured that 457 * all spdk_bdev_for_each_channel() calls will succeed or there is no bdev. 458 */ 459 rpc_get_iostat_started(rpc_ctx, desc); 460 } 461 462 rpc_get_iostat_done(rpc_ctx); 463 } 464 SPDK_RPC_REGISTER("bdev_get_iostat", rpc_bdev_get_iostat, SPDK_RPC_RUNTIME) 465 466 struct rpc_reset_iostat_ctx { 467 int bdev_count; 468 int rc; 469 struct spdk_jsonrpc_request *request; 470 struct spdk_json_write_ctx *w; 471 enum bdev_reset_stat_mode mode; 472 }; 473 474 struct bdev_reset_iostat_ctx { 475 struct rpc_reset_iostat_ctx *rpc_ctx; 476 struct spdk_bdev_desc *desc; 477 }; 478 479 static void 480 rpc_reset_iostat_done(struct rpc_reset_iostat_ctx *rpc_ctx) 481 { 482 if (--rpc_ctx->bdev_count != 0) { 483 return; 484 } 485 486 if (rpc_ctx->rc == 0) { 487 spdk_jsonrpc_send_bool_response(rpc_ctx->request, true); 488 } else { 489 spdk_jsonrpc_send_error_response(rpc_ctx->request, rpc_ctx->rc, 490 spdk_strerror(-rpc_ctx->rc)); 491 } 492 493 free(rpc_ctx); 494 } 495 496 static void 497 bdev_reset_iostat_done(struct spdk_bdev *bdev, void *cb_arg, int rc) 498 { 499 struct bdev_reset_iostat_ctx *bdev_ctx = cb_arg; 500 struct rpc_reset_iostat_ctx *rpc_ctx = bdev_ctx->rpc_ctx; 501 502 if (rc != 0 || rpc_ctx->rc != 0) { 503 if (rpc_ctx->rc == 0) { 504 rpc_ctx->rc = rc; 505 } 506 } 507 508 rpc_reset_iostat_done(rpc_ctx); 509 510 spdk_bdev_close(bdev_ctx->desc); 511 free(bdev_ctx); 512 } 513 514 static int 515 bdev_reset_iostat(void *ctx, struct spdk_bdev *bdev) 516 { 517 struct rpc_reset_iostat_ctx *rpc_ctx = ctx; 518 struct bdev_reset_iostat_ctx *bdev_ctx; 519 int rc; 520 521 bdev_ctx = calloc(1, sizeof(struct bdev_reset_iostat_ctx)); 522 if (bdev_ctx == NULL) { 523 SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 524 return -ENOMEM; 525 } 526 527 rc = spdk_bdev_open_ext(spdk_bdev_get_name(bdev), false, dummy_bdev_event_cb, NULL, 528 &bdev_ctx->desc); 529 if (rc != 0) { 530 free(bdev_ctx); 531 SPDK_ERRLOG("Failed to open bdev\n"); 532 return rc; 533 } 534 535 if (bdev->fn_table->reset_device_stat) { 536 bdev->fn_table->reset_device_stat(bdev->ctxt); 537 } 538 539 rpc_ctx->bdev_count++; 540 bdev_ctx->rpc_ctx = rpc_ctx; 541 bdev_reset_device_stat(bdev, rpc_ctx->mode, bdev_reset_iostat_done, bdev_ctx); 542 543 return 0; 544 } 545 546 struct rpc_bdev_reset_iostat { 547 char *name; 548 enum bdev_reset_stat_mode mode; 549 }; 550 551 static void 552 free_rpc_bdev_reset_iostat(struct rpc_bdev_reset_iostat *r) 553 { 554 free(r->name); 555 } 556 557 static int 558 rpc_decode_reset_iostat_mode(const struct spdk_json_val *val, void *out) 559 { 560 enum bdev_reset_stat_mode *mode = out; 561 562 if (spdk_json_strequal(val, "all") == true) { 563 *mode = BDEV_RESET_STAT_ALL; 564 } else if (spdk_json_strequal(val, "maxmin") == true) { 565 *mode = BDEV_RESET_STAT_MAXMIN; 566 } else { 567 SPDK_NOTICELOG("Invalid parameter value: mode\n"); 568 return -EINVAL; 569 } 570 571 return 0; 572 } 573 574 static const struct spdk_json_object_decoder rpc_bdev_reset_iostat_decoders[] = { 575 {"name", offsetof(struct rpc_bdev_reset_iostat, name), spdk_json_decode_string, true}, 576 {"mode", offsetof(struct rpc_bdev_reset_iostat, mode), rpc_decode_reset_iostat_mode, true}, 577 }; 578 579 static void 580 rpc_bdev_reset_iostat(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 581 { 582 struct rpc_bdev_reset_iostat req = { .mode = BDEV_RESET_STAT_ALL, }; 583 struct spdk_bdev_desc *desc = NULL; 584 struct rpc_reset_iostat_ctx *rpc_ctx; 585 struct bdev_reset_iostat_ctx *bdev_ctx; 586 int rc; 587 588 if (params != NULL) { 589 if (spdk_json_decode_object(params, rpc_bdev_reset_iostat_decoders, 590 SPDK_COUNTOF(rpc_bdev_reset_iostat_decoders), 591 &req)) { 592 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 593 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 594 "spdk_json_decode_object failed"); 595 free_rpc_bdev_reset_iostat(&req); 596 return; 597 } 598 599 if (req.name) { 600 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 601 if (rc != 0) { 602 SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 603 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 604 free_rpc_bdev_reset_iostat(&req); 605 return; 606 } 607 } 608 } 609 610 611 rpc_ctx = calloc(1, sizeof(struct rpc_reset_iostat_ctx)); 612 if (rpc_ctx == NULL) { 613 SPDK_ERRLOG("Failed to allocate rpc_iostat_ctx struct\n"); 614 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 615 free_rpc_bdev_reset_iostat(&req); 616 return; 617 } 618 619 /* 620 * Increment initial bdev_count so that it will never reach 0 in the middle 621 * of iterating. 622 */ 623 rpc_ctx->bdev_count++; 624 rpc_ctx->request = request; 625 rpc_ctx->mode = req.mode; 626 627 free_rpc_bdev_reset_iostat(&req); 628 629 if (desc != NULL) { 630 bdev_ctx = calloc(1, sizeof(struct bdev_reset_iostat_ctx)); 631 if (bdev_ctx == NULL) { 632 SPDK_ERRLOG("Failed to allocate bdev_iostat_ctx struct\n"); 633 rpc_ctx->rc = -ENOMEM; 634 635 spdk_bdev_close(desc); 636 } else { 637 bdev_ctx->desc = desc; 638 639 rpc_ctx->bdev_count++; 640 bdev_ctx->rpc_ctx = rpc_ctx; 641 bdev_reset_device_stat(spdk_bdev_desc_get_bdev(desc), rpc_ctx->mode, 642 bdev_reset_iostat_done, bdev_ctx); 643 } 644 } else { 645 rc = spdk_for_each_bdev(rpc_ctx, bdev_reset_iostat); 646 if (rc != 0 && rpc_ctx->rc == 0) { 647 rpc_ctx->rc = rc; 648 } 649 } 650 651 rpc_reset_iostat_done(rpc_ctx); 652 } 653 SPDK_RPC_REGISTER("bdev_reset_iostat", rpc_bdev_reset_iostat, SPDK_RPC_RUNTIME) 654 655 static int 656 rpc_dump_bdev_info(void *ctx, struct spdk_bdev *bdev) 657 { 658 struct spdk_json_write_ctx *w = ctx; 659 struct spdk_bdev_alias *tmp; 660 uint64_t qos_limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES]; 661 struct spdk_memory_domain **domains; 662 int i, rc; 663 664 spdk_json_write_object_begin(w); 665 666 spdk_json_write_named_string(w, "name", spdk_bdev_get_name(bdev)); 667 668 spdk_json_write_named_array_begin(w, "aliases"); 669 670 TAILQ_FOREACH(tmp, spdk_bdev_get_aliases(bdev), tailq) { 671 spdk_json_write_string(w, tmp->alias.name); 672 } 673 674 spdk_json_write_array_end(w); 675 676 spdk_json_write_named_string(w, "product_name", spdk_bdev_get_product_name(bdev)); 677 678 spdk_json_write_named_uint32(w, "block_size", spdk_bdev_get_block_size(bdev)); 679 680 spdk_json_write_named_uint64(w, "num_blocks", spdk_bdev_get_num_blocks(bdev)); 681 682 if (!spdk_mem_all_zero(&bdev->uuid, sizeof(bdev->uuid))) { 683 char uuid_str[SPDK_UUID_STRING_LEN]; 684 685 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid); 686 spdk_json_write_named_string(w, "uuid", uuid_str); 687 } 688 689 if (spdk_bdev_get_md_size(bdev) != 0) { 690 spdk_json_write_named_uint32(w, "md_size", spdk_bdev_get_md_size(bdev)); 691 spdk_json_write_named_bool(w, "md_interleave", spdk_bdev_is_md_interleaved(bdev)); 692 spdk_json_write_named_uint32(w, "dif_type", spdk_bdev_get_dif_type(bdev)); 693 if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) { 694 spdk_json_write_named_bool(w, "dif_is_head_of_md", spdk_bdev_is_dif_head_of_md(bdev)); 695 spdk_json_write_named_object_begin(w, "enabled_dif_check_types"); 696 spdk_json_write_named_bool(w, "reftag", 697 spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG)); 698 spdk_json_write_named_bool(w, "apptag", 699 spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_APPTAG)); 700 spdk_json_write_named_bool(w, "guard", 701 spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD)); 702 spdk_json_write_object_end(w); 703 } 704 } 705 706 spdk_json_write_named_object_begin(w, "assigned_rate_limits"); 707 spdk_bdev_get_qos_rate_limits(bdev, qos_limits); 708 for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) { 709 spdk_json_write_named_uint64(w, spdk_bdev_get_qos_rpc_type(i), qos_limits[i]); 710 } 711 spdk_json_write_object_end(w); 712 713 spdk_json_write_named_bool(w, "claimed", (bdev->internal.claim_module != NULL)); 714 715 spdk_json_write_named_bool(w, "zoned", bdev->zoned); 716 if (bdev->zoned) { 717 spdk_json_write_named_uint64(w, "zone_size", bdev->zone_size); 718 spdk_json_write_named_uint64(w, "max_open_zones", bdev->max_open_zones); 719 spdk_json_write_named_uint64(w, "optimal_open_zones", bdev->optimal_open_zones); 720 } 721 722 spdk_json_write_named_object_begin(w, "supported_io_types"); 723 spdk_json_write_named_bool(w, "read", 724 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_READ)); 725 spdk_json_write_named_bool(w, "write", 726 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE)); 727 spdk_json_write_named_bool(w, "unmap", 728 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)); 729 spdk_json_write_named_bool(w, "write_zeroes", 730 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE_ZEROES)); 731 spdk_json_write_named_bool(w, "flush", 732 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_FLUSH)); 733 spdk_json_write_named_bool(w, "reset", 734 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_RESET)); 735 spdk_json_write_named_bool(w, "compare", 736 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_COMPARE)); 737 spdk_json_write_named_bool(w, "compare_and_write", 738 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_COMPARE_AND_WRITE)); 739 spdk_json_write_named_bool(w, "abort", 740 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_ABORT)); 741 spdk_json_write_named_bool(w, "nvme_admin", 742 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_ADMIN)); 743 spdk_json_write_named_bool(w, "nvme_io", 744 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_IO)); 745 spdk_json_write_object_end(w); 746 747 rc = spdk_bdev_get_memory_domains(bdev, NULL, 0); 748 if (rc > 0) { 749 domains = calloc(rc, sizeof(struct spdk_memory_domain *)); 750 if (domains) { 751 i = spdk_bdev_get_memory_domains(bdev, domains, rc); 752 if (i == rc) { 753 spdk_json_write_named_array_begin(w, "memory_domains"); 754 for (i = 0; i < rc; i++) { 755 spdk_json_write_object_begin(w); 756 spdk_json_write_named_string(w, "dma_device_id", spdk_memory_domain_get_dma_device_id(domains[i])); 757 spdk_json_write_named_int32(w, "dma_device_type", 758 spdk_memory_domain_get_dma_device_type(domains[i])); 759 spdk_json_write_object_end(w); 760 } 761 spdk_json_write_array_end(w); 762 } else { 763 SPDK_ERRLOG("Unexpected number of memory domains %d (should be %d)\n", i, rc); 764 } 765 766 free(domains); 767 } else { 768 SPDK_ERRLOG("Memory allocation failed\n"); 769 } 770 } 771 772 spdk_json_write_named_object_begin(w, "driver_specific"); 773 spdk_bdev_dump_info_json(bdev, w); 774 spdk_json_write_object_end(w); 775 776 spdk_json_write_object_end(w); 777 778 return 0; 779 } 780 781 struct rpc_bdev_get_bdevs { 782 char *name; 783 uint64_t timeout; 784 }; 785 786 struct rpc_bdev_get_bdevs_ctx { 787 struct rpc_bdev_get_bdevs rpc; 788 struct spdk_jsonrpc_request *request; 789 struct spdk_poller *poller; 790 uint64_t timeout_ticks; 791 }; 792 793 static void 794 free_rpc_bdev_get_bdevs(struct rpc_bdev_get_bdevs *r) 795 { 796 free(r->name); 797 } 798 799 static const struct spdk_json_object_decoder rpc_bdev_get_bdevs_decoders[] = { 800 {"name", offsetof(struct rpc_bdev_get_bdevs, name), spdk_json_decode_string, true}, 801 {"timeout", offsetof(struct rpc_bdev_get_bdevs, timeout), spdk_json_decode_uint64, true}, 802 }; 803 804 static int 805 get_bdevs_poller(void *_ctx) 806 { 807 struct rpc_bdev_get_bdevs_ctx *ctx = _ctx; 808 struct spdk_json_write_ctx *w; 809 struct spdk_bdev_desc *desc; 810 int rc; 811 812 rc = spdk_bdev_open_ext(ctx->rpc.name, false, dummy_bdev_event_cb, NULL, &desc); 813 if (rc != 0 && spdk_get_ticks() < ctx->timeout_ticks) { 814 return SPDK_POLLER_BUSY; 815 } 816 817 if (rc != 0) { 818 SPDK_ERRLOG("Timed out while waiting for bdev '%s' to appear\n", ctx->rpc.name); 819 spdk_jsonrpc_send_error_response(ctx->request, -ENODEV, spdk_strerror(ENODEV)); 820 } else { 821 w = spdk_jsonrpc_begin_result(ctx->request); 822 spdk_json_write_array_begin(w); 823 rpc_dump_bdev_info(w, spdk_bdev_desc_get_bdev(desc)); 824 spdk_json_write_array_end(w); 825 spdk_jsonrpc_end_result(ctx->request, w); 826 827 spdk_bdev_close(desc); 828 } 829 830 spdk_poller_unregister(&ctx->poller); 831 free_rpc_bdev_get_bdevs(&ctx->rpc); 832 free(ctx); 833 834 return SPDK_POLLER_BUSY; 835 } 836 837 static void 838 rpc_bdev_get_bdevs(struct spdk_jsonrpc_request *request, 839 const struct spdk_json_val *params) 840 { 841 struct rpc_bdev_get_bdevs req = {}; 842 struct rpc_bdev_get_bdevs_ctx *ctx; 843 struct spdk_json_write_ctx *w; 844 struct spdk_bdev_desc *desc = NULL; 845 int rc; 846 847 if (params && spdk_json_decode_object(params, rpc_bdev_get_bdevs_decoders, 848 SPDK_COUNTOF(rpc_bdev_get_bdevs_decoders), 849 &req)) { 850 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 851 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 852 "spdk_json_decode_object failed"); 853 free_rpc_bdev_get_bdevs(&req); 854 return; 855 } 856 857 if (req.name) { 858 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 859 if (rc != 0) { 860 if (req.timeout == 0) { 861 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 862 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 863 free_rpc_bdev_get_bdevs(&req); 864 return; 865 } 866 867 ctx = calloc(1, sizeof(*ctx)); 868 if (ctx == NULL) { 869 SPDK_ERRLOG("Failed to allocate bdev_get_bdevs context\n"); 870 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 871 free_rpc_bdev_get_bdevs(&req); 872 return; 873 } 874 875 ctx->poller = SPDK_POLLER_REGISTER(get_bdevs_poller, ctx, 10 * 1000); 876 if (ctx->poller == NULL) { 877 SPDK_ERRLOG("Failed to register bdev_get_bdevs poller\n"); 878 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 879 free_rpc_bdev_get_bdevs(&req); 880 free(ctx); 881 return; 882 } 883 884 memcpy(&ctx->rpc, &req, sizeof(req)); 885 ctx->timeout_ticks = spdk_get_ticks() + req.timeout * 886 spdk_get_ticks_hz() / 1000ull; 887 ctx->request = request; 888 return; 889 } 890 } 891 892 free_rpc_bdev_get_bdevs(&req); 893 w = spdk_jsonrpc_begin_result(request); 894 spdk_json_write_array_begin(w); 895 896 if (desc != NULL) { 897 rpc_dump_bdev_info(w, spdk_bdev_desc_get_bdev(desc)); 898 spdk_bdev_close(desc); 899 } else { 900 spdk_for_each_bdev(w, rpc_dump_bdev_info); 901 } 902 903 spdk_json_write_array_end(w); 904 905 spdk_jsonrpc_end_result(request, w); 906 } 907 SPDK_RPC_REGISTER("bdev_get_bdevs", rpc_bdev_get_bdevs, SPDK_RPC_RUNTIME) 908 909 struct rpc_bdev_set_qd_sampling_period { 910 char *name; 911 uint64_t period; 912 }; 913 914 static void 915 free_rpc_bdev_set_qd_sampling_period(struct rpc_bdev_set_qd_sampling_period *r) 916 { 917 free(r->name); 918 } 919 920 static const struct spdk_json_object_decoder 921 rpc_bdev_set_qd_sampling_period_decoders[] = { 922 {"name", offsetof(struct rpc_bdev_set_qd_sampling_period, name), spdk_json_decode_string}, 923 {"period", offsetof(struct rpc_bdev_set_qd_sampling_period, period), spdk_json_decode_uint64}, 924 }; 925 926 static void 927 rpc_bdev_set_qd_sampling_period(struct spdk_jsonrpc_request *request, 928 const struct spdk_json_val *params) 929 { 930 struct rpc_bdev_set_qd_sampling_period req = {0}; 931 struct spdk_bdev_desc *desc; 932 int rc; 933 934 if (spdk_json_decode_object(params, rpc_bdev_set_qd_sampling_period_decoders, 935 SPDK_COUNTOF(rpc_bdev_set_qd_sampling_period_decoders), 936 &req)) { 937 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 938 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 939 "spdk_json_decode_object failed"); 940 goto cleanup; 941 } 942 943 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 944 if (rc != 0) { 945 SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 946 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 947 goto cleanup; 948 } 949 950 spdk_bdev_set_qd_sampling_period(spdk_bdev_desc_get_bdev(desc), req.period); 951 spdk_jsonrpc_send_bool_response(request, true); 952 953 spdk_bdev_close(desc); 954 955 cleanup: 956 free_rpc_bdev_set_qd_sampling_period(&req); 957 } 958 SPDK_RPC_REGISTER("bdev_set_qd_sampling_period", 959 rpc_bdev_set_qd_sampling_period, 960 SPDK_RPC_RUNTIME) 961 962 struct rpc_bdev_set_qos_limit { 963 char *name; 964 uint64_t limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES]; 965 }; 966 967 static void 968 free_rpc_bdev_set_qos_limit(struct rpc_bdev_set_qos_limit *r) 969 { 970 free(r->name); 971 } 972 973 static const struct spdk_json_object_decoder rpc_bdev_set_qos_limit_decoders[] = { 974 {"name", offsetof(struct rpc_bdev_set_qos_limit, name), spdk_json_decode_string}, 975 { 976 "rw_ios_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 977 limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT]), 978 spdk_json_decode_uint64, true 979 }, 980 { 981 "rw_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 982 limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT]), 983 spdk_json_decode_uint64, true 984 }, 985 { 986 "r_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 987 limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT]), 988 spdk_json_decode_uint64, true 989 }, 990 { 991 "w_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 992 limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT]), 993 spdk_json_decode_uint64, true 994 }, 995 }; 996 997 static void 998 rpc_bdev_set_qos_limit_complete(void *cb_arg, int status) 999 { 1000 struct spdk_jsonrpc_request *request = cb_arg; 1001 1002 if (status != 0) { 1003 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1004 "Failed to configure rate limit: %s", 1005 spdk_strerror(-status)); 1006 return; 1007 } 1008 1009 spdk_jsonrpc_send_bool_response(request, true); 1010 } 1011 1012 static void 1013 rpc_bdev_set_qos_limit(struct spdk_jsonrpc_request *request, 1014 const struct spdk_json_val *params) 1015 { 1016 struct rpc_bdev_set_qos_limit req = {NULL, {UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX}}; 1017 struct spdk_bdev_desc *desc; 1018 int i, rc; 1019 1020 if (spdk_json_decode_object(params, rpc_bdev_set_qos_limit_decoders, 1021 SPDK_COUNTOF(rpc_bdev_set_qos_limit_decoders), 1022 &req)) { 1023 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1024 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1025 "spdk_json_decode_object failed"); 1026 goto cleanup; 1027 } 1028 1029 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 1030 if (rc != 0) { 1031 SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc); 1032 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1033 goto cleanup; 1034 } 1035 1036 for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) { 1037 if (req.limits[i] != UINT64_MAX) { 1038 break; 1039 } 1040 } 1041 if (i == SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES) { 1042 SPDK_ERRLOG("no rate limits specified\n"); 1043 spdk_bdev_close(desc); 1044 spdk_jsonrpc_send_error_response(request, -EINVAL, "No rate limits specified"); 1045 goto cleanup; 1046 } 1047 1048 spdk_bdev_set_qos_rate_limits(spdk_bdev_desc_get_bdev(desc), req.limits, 1049 rpc_bdev_set_qos_limit_complete, request); 1050 1051 spdk_bdev_close(desc); 1052 1053 cleanup: 1054 free_rpc_bdev_set_qos_limit(&req); 1055 } 1056 1057 SPDK_RPC_REGISTER("bdev_set_qos_limit", rpc_bdev_set_qos_limit, SPDK_RPC_RUNTIME) 1058 1059 /* SPDK_RPC_ENABLE_BDEV_HISTOGRAM */ 1060 1061 struct rpc_bdev_enable_histogram_request { 1062 char *name; 1063 bool enable; 1064 }; 1065 1066 static void 1067 free_rpc_bdev_enable_histogram_request(struct rpc_bdev_enable_histogram_request *r) 1068 { 1069 free(r->name); 1070 } 1071 1072 static const struct spdk_json_object_decoder rpc_bdev_enable_histogram_request_decoders[] = { 1073 {"name", offsetof(struct rpc_bdev_enable_histogram_request, name), spdk_json_decode_string}, 1074 {"enable", offsetof(struct rpc_bdev_enable_histogram_request, enable), spdk_json_decode_bool}, 1075 }; 1076 1077 static void 1078 bdev_histogram_status_cb(void *cb_arg, int status) 1079 { 1080 struct spdk_jsonrpc_request *request = cb_arg; 1081 1082 spdk_jsonrpc_send_bool_response(request, status == 0); 1083 } 1084 1085 static void 1086 rpc_bdev_enable_histogram(struct spdk_jsonrpc_request *request, 1087 const struct spdk_json_val *params) 1088 { 1089 struct rpc_bdev_enable_histogram_request req = {NULL}; 1090 struct spdk_bdev_desc *desc; 1091 int rc; 1092 1093 if (spdk_json_decode_object(params, rpc_bdev_enable_histogram_request_decoders, 1094 SPDK_COUNTOF(rpc_bdev_enable_histogram_request_decoders), 1095 &req)) { 1096 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1097 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1098 "spdk_json_decode_object failed"); 1099 goto cleanup; 1100 } 1101 1102 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 1103 if (rc != 0) { 1104 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1105 goto cleanup; 1106 } 1107 1108 spdk_bdev_histogram_enable(spdk_bdev_desc_get_bdev(desc), bdev_histogram_status_cb, 1109 request, req.enable); 1110 1111 spdk_bdev_close(desc); 1112 1113 cleanup: 1114 free_rpc_bdev_enable_histogram_request(&req); 1115 } 1116 1117 SPDK_RPC_REGISTER("bdev_enable_histogram", rpc_bdev_enable_histogram, SPDK_RPC_RUNTIME) 1118 1119 /* SPDK_RPC_GET_BDEV_HISTOGRAM */ 1120 1121 struct rpc_bdev_get_histogram_request { 1122 char *name; 1123 }; 1124 1125 static const struct spdk_json_object_decoder rpc_bdev_get_histogram_request_decoders[] = { 1126 {"name", offsetof(struct rpc_bdev_get_histogram_request, name), spdk_json_decode_string} 1127 }; 1128 1129 static void 1130 free_rpc_bdev_get_histogram_request(struct rpc_bdev_get_histogram_request *r) 1131 { 1132 free(r->name); 1133 } 1134 1135 static void 1136 _rpc_bdev_histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram) 1137 { 1138 struct spdk_jsonrpc_request *request = cb_arg; 1139 struct spdk_json_write_ctx *w; 1140 int rc; 1141 char *encoded_histogram; 1142 size_t src_len, dst_len; 1143 1144 1145 if (status != 0) { 1146 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1147 spdk_strerror(-status)); 1148 goto invalid; 1149 } 1150 1151 src_len = SPDK_HISTOGRAM_NUM_BUCKETS(histogram) * sizeof(uint64_t); 1152 dst_len = spdk_base64_get_encoded_strlen(src_len) + 1; 1153 1154 encoded_histogram = malloc(dst_len); 1155 if (encoded_histogram == NULL) { 1156 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1157 spdk_strerror(ENOMEM)); 1158 goto invalid; 1159 } 1160 1161 rc = spdk_base64_encode(encoded_histogram, histogram->bucket, src_len); 1162 if (rc != 0) { 1163 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1164 spdk_strerror(-rc)); 1165 goto free_encoded_histogram; 1166 } 1167 1168 w = spdk_jsonrpc_begin_result(request); 1169 spdk_json_write_object_begin(w); 1170 spdk_json_write_named_string(w, "histogram", encoded_histogram); 1171 spdk_json_write_named_int64(w, "bucket_shift", histogram->bucket_shift); 1172 spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz()); 1173 spdk_json_write_object_end(w); 1174 spdk_jsonrpc_end_result(request, w); 1175 1176 free_encoded_histogram: 1177 free(encoded_histogram); 1178 invalid: 1179 spdk_histogram_data_free(histogram); 1180 } 1181 1182 static void 1183 rpc_bdev_get_histogram(struct spdk_jsonrpc_request *request, 1184 const struct spdk_json_val *params) 1185 { 1186 struct rpc_bdev_get_histogram_request req = {NULL}; 1187 struct spdk_histogram_data *histogram; 1188 struct spdk_bdev_desc *desc; 1189 int rc; 1190 1191 if (spdk_json_decode_object(params, rpc_bdev_get_histogram_request_decoders, 1192 SPDK_COUNTOF(rpc_bdev_get_histogram_request_decoders), 1193 &req)) { 1194 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1195 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1196 "spdk_json_decode_object failed"); 1197 goto cleanup; 1198 } 1199 1200 rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc); 1201 if (rc != 0) { 1202 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 1203 goto cleanup; 1204 } 1205 1206 histogram = spdk_histogram_data_alloc(); 1207 if (histogram == NULL) { 1208 spdk_bdev_close(desc); 1209 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1210 goto cleanup; 1211 } 1212 1213 spdk_bdev_histogram_get(spdk_bdev_desc_get_bdev(desc), histogram, 1214 _rpc_bdev_histogram_data_cb, request); 1215 1216 spdk_bdev_close(desc); 1217 1218 cleanup: 1219 free_rpc_bdev_get_histogram_request(&req); 1220 } 1221 1222 SPDK_RPC_REGISTER("bdev_get_histogram", rpc_bdev_get_histogram, SPDK_RPC_RUNTIME) 1223