1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/bdev.h" 35 36 #include "spdk/env.h" 37 #include "spdk/rpc.h" 38 #include "spdk/util.h" 39 #include "spdk/string.h" 40 #include "spdk/base64.h" 41 #include "spdk/bdev_module.h" 42 43 #include "spdk/log.h" 44 45 struct spdk_rpc_set_bdev_opts { 46 uint32_t bdev_io_pool_size; 47 uint32_t bdev_io_cache_size; 48 bool bdev_auto_examine; 49 }; 50 51 static const struct spdk_json_object_decoder rpc_set_bdev_opts_decoders[] = { 52 {"bdev_io_pool_size", offsetof(struct spdk_rpc_set_bdev_opts, bdev_io_pool_size), spdk_json_decode_uint32, true}, 53 {"bdev_io_cache_size", offsetof(struct spdk_rpc_set_bdev_opts, bdev_io_cache_size), spdk_json_decode_uint32, true}, 54 {"bdev_auto_examine", offsetof(struct spdk_rpc_set_bdev_opts, bdev_auto_examine), spdk_json_decode_bool, true}, 55 }; 56 57 static void 58 rpc_bdev_set_options(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 59 { 60 struct spdk_rpc_set_bdev_opts rpc_opts; 61 struct spdk_bdev_opts bdev_opts; 62 struct spdk_json_write_ctx *w; 63 int rc; 64 65 rpc_opts.bdev_io_pool_size = UINT32_MAX; 66 rpc_opts.bdev_io_cache_size = UINT32_MAX; 67 rpc_opts.bdev_auto_examine = true; 68 69 if (params != NULL) { 70 if (spdk_json_decode_object(params, rpc_set_bdev_opts_decoders, 71 SPDK_COUNTOF(rpc_set_bdev_opts_decoders), &rpc_opts)) { 72 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 73 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 74 "Invalid parameters"); 75 return; 76 } 77 } 78 79 spdk_bdev_get_opts(&bdev_opts); 80 if (rpc_opts.bdev_io_pool_size != UINT32_MAX) { 81 bdev_opts.bdev_io_pool_size = rpc_opts.bdev_io_pool_size; 82 } 83 if (rpc_opts.bdev_io_cache_size != UINT32_MAX) { 84 bdev_opts.bdev_io_cache_size = rpc_opts.bdev_io_cache_size; 85 } 86 bdev_opts.bdev_auto_examine = rpc_opts.bdev_auto_examine; 87 rc = spdk_bdev_set_opts(&bdev_opts); 88 89 if (rc != 0) { 90 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 91 "Pool size %" PRIu32 " too small for cache size %" PRIu32, 92 bdev_opts.bdev_io_pool_size, bdev_opts.bdev_io_cache_size); 93 return; 94 } 95 96 w = spdk_jsonrpc_begin_result(request); 97 spdk_json_write_bool(w, true); 98 spdk_jsonrpc_end_result(request, w); 99 } 100 SPDK_RPC_REGISTER("bdev_set_options", rpc_bdev_set_options, SPDK_RPC_STARTUP) 101 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_options, set_bdev_options) 102 103 struct rpc_bdev_examine { 104 char *name; 105 }; 106 107 static void 108 free_rpc_bdev_examine(struct rpc_bdev_examine *r) 109 { 110 free(r->name); 111 } 112 113 static const struct spdk_json_object_decoder rpc_examine_bdev_decoders[] = { 114 {"name", offsetof(struct rpc_bdev_examine, name), spdk_json_decode_string}, 115 }; 116 117 static void 118 rpc_bdev_examine_bdev(struct spdk_jsonrpc_request *request, 119 const struct spdk_json_val *params) 120 { 121 struct rpc_bdev_examine req = {NULL}; 122 struct spdk_json_write_ctx *w; 123 int rc; 124 125 if (spdk_json_decode_object(params, rpc_examine_bdev_decoders, 126 SPDK_COUNTOF(rpc_examine_bdev_decoders), 127 &req)) { 128 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 129 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 130 "spdk_json_decode_object failed"); 131 goto cleanup; 132 } 133 134 rc = spdk_bdev_examine(req.name); 135 if (rc != 0) { 136 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 137 goto cleanup; 138 } 139 w = spdk_jsonrpc_begin_result(request); 140 spdk_json_write_bool(w, true); 141 spdk_jsonrpc_end_result(request, w); 142 143 cleanup: 144 free_rpc_bdev_examine(&req); 145 } 146 SPDK_RPC_REGISTER("bdev_examine", rpc_bdev_examine_bdev, SPDK_RPC_RUNTIME) 147 148 struct rpc_bdev_get_iostat_ctx { 149 int bdev_count; 150 struct spdk_jsonrpc_request *request; 151 struct spdk_json_write_ctx *w; 152 }; 153 154 static void 155 rpc_bdev_get_iostat_cb(struct spdk_bdev *bdev, 156 struct spdk_bdev_io_stat *stat, void *cb_arg, int rc) 157 { 158 struct rpc_bdev_get_iostat_ctx *ctx = cb_arg; 159 struct spdk_json_write_ctx *w = ctx->w; 160 const char *bdev_name; 161 162 if (rc != 0) { 163 goto done; 164 } 165 166 bdev_name = spdk_bdev_get_name(bdev); 167 if (bdev_name != NULL) { 168 spdk_json_write_object_begin(w); 169 170 spdk_json_write_named_string(w, "name", bdev_name); 171 172 spdk_json_write_named_uint64(w, "bytes_read", stat->bytes_read); 173 174 spdk_json_write_named_uint64(w, "num_read_ops", stat->num_read_ops); 175 176 spdk_json_write_named_uint64(w, "bytes_written", stat->bytes_written); 177 178 spdk_json_write_named_uint64(w, "num_write_ops", stat->num_write_ops); 179 180 spdk_json_write_named_uint64(w, "bytes_unmapped", stat->bytes_unmapped); 181 182 spdk_json_write_named_uint64(w, "num_unmap_ops", stat->num_unmap_ops); 183 184 spdk_json_write_named_uint64(w, "read_latency_ticks", stat->read_latency_ticks); 185 186 spdk_json_write_named_uint64(w, "write_latency_ticks", stat->write_latency_ticks); 187 188 spdk_json_write_named_uint64(w, "unmap_latency_ticks", stat->unmap_latency_ticks); 189 190 if (spdk_bdev_get_qd_sampling_period(bdev)) { 191 spdk_json_write_named_uint64(w, "queue_depth_polling_period", 192 spdk_bdev_get_qd_sampling_period(bdev)); 193 194 spdk_json_write_named_uint64(w, "queue_depth", spdk_bdev_get_qd(bdev)); 195 196 spdk_json_write_named_uint64(w, "io_time", spdk_bdev_get_io_time(bdev)); 197 198 spdk_json_write_named_uint64(w, "weighted_io_time", 199 spdk_bdev_get_weighted_io_time(bdev)); 200 } 201 202 spdk_json_write_object_end(w); 203 } 204 205 done: 206 free(stat); 207 if (--ctx->bdev_count == 0) { 208 spdk_json_write_array_end(ctx->w); 209 spdk_json_write_object_end(w); 210 spdk_jsonrpc_end_result(ctx->request, ctx->w); 211 free(ctx); 212 } 213 } 214 215 struct rpc_bdev_get_iostat { 216 char *name; 217 }; 218 219 static void 220 free_rpc_bdev_get_iostat(struct rpc_bdev_get_iostat *r) 221 { 222 free(r->name); 223 } 224 225 static const struct spdk_json_object_decoder rpc_bdev_get_iostat_decoders[] = { 226 {"name", offsetof(struct rpc_bdev_get_iostat, name), spdk_json_decode_string, true}, 227 }; 228 229 static void 230 rpc_bdev_get_iostat(struct spdk_jsonrpc_request *request, 231 const struct spdk_json_val *params) 232 { 233 struct rpc_bdev_get_iostat req = {}; 234 struct spdk_bdev *bdev = NULL; 235 struct spdk_json_write_ctx *w; 236 struct spdk_bdev_io_stat *stat; 237 struct rpc_bdev_get_iostat_ctx *ctx; 238 239 if (params != NULL) { 240 if (spdk_json_decode_object(params, rpc_bdev_get_iostat_decoders, 241 SPDK_COUNTOF(rpc_bdev_get_iostat_decoders), 242 &req)) { 243 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 244 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 245 "spdk_json_decode_object failed"); 246 free_rpc_bdev_get_iostat(&req); 247 return; 248 } 249 250 if (req.name) { 251 bdev = spdk_bdev_get_by_name(req.name); 252 if (bdev == NULL) { 253 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 254 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 255 free_rpc_bdev_get_iostat(&req); 256 return; 257 } 258 } 259 } 260 261 free_rpc_bdev_get_iostat(&req); 262 263 ctx = calloc(1, sizeof(struct rpc_bdev_get_iostat_ctx)); 264 if (ctx == NULL) { 265 SPDK_ERRLOG("Failed to allocate rpc_bdev_get_iostat_ctx struct\n"); 266 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 267 return; 268 } 269 270 w = spdk_jsonrpc_begin_result(request); 271 /* 272 * Increment initial bdev_count so that it will never reach 0 in the middle 273 * of iterating. 274 */ 275 ctx->bdev_count++; 276 ctx->request = request; 277 ctx->w = w; 278 279 280 spdk_json_write_object_begin(w); 281 spdk_json_write_named_uint64(w, "tick_rate", spdk_get_ticks_hz()); 282 spdk_json_write_named_uint64(w, "ticks", spdk_get_ticks()); 283 284 spdk_json_write_named_array_begin(w, "bdevs"); 285 286 if (bdev != NULL) { 287 stat = calloc(1, sizeof(struct spdk_bdev_io_stat)); 288 if (stat == NULL) { 289 SPDK_ERRLOG("Failed to allocate rpc_bdev_get_iostat_ctx struct\n"); 290 } else { 291 ctx->bdev_count++; 292 spdk_bdev_get_device_stat(bdev, stat, rpc_bdev_get_iostat_cb, ctx); 293 } 294 } else { 295 for (bdev = spdk_bdev_first(); bdev != NULL; bdev = spdk_bdev_next(bdev)) { 296 stat = calloc(1, sizeof(struct spdk_bdev_io_stat)); 297 if (stat == NULL) { 298 SPDK_ERRLOG("Failed to allocate spdk_bdev_io_stat struct\n"); 299 break; 300 } 301 ctx->bdev_count++; 302 spdk_bdev_get_device_stat(bdev, stat, rpc_bdev_get_iostat_cb, ctx); 303 } 304 } 305 306 if (--ctx->bdev_count == 0) { 307 spdk_json_write_array_end(w); 308 spdk_json_write_object_end(w); 309 spdk_jsonrpc_end_result(request, w); 310 free(ctx); 311 } 312 } 313 SPDK_RPC_REGISTER("bdev_get_iostat", rpc_bdev_get_iostat, SPDK_RPC_RUNTIME) 314 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_iostat, get_bdevs_iostat) 315 316 static void 317 rpc_dump_bdev_info(struct spdk_json_write_ctx *w, 318 struct spdk_bdev *bdev) 319 { 320 struct spdk_bdev_alias *tmp; 321 uint64_t qos_limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES]; 322 int i; 323 324 spdk_json_write_object_begin(w); 325 326 spdk_json_write_named_string(w, "name", spdk_bdev_get_name(bdev)); 327 328 spdk_json_write_named_array_begin(w, "aliases"); 329 330 TAILQ_FOREACH(tmp, spdk_bdev_get_aliases(bdev), tailq) { 331 spdk_json_write_string(w, tmp->alias); 332 } 333 334 spdk_json_write_array_end(w); 335 336 spdk_json_write_named_string(w, "product_name", spdk_bdev_get_product_name(bdev)); 337 338 spdk_json_write_named_uint32(w, "block_size", spdk_bdev_get_block_size(bdev)); 339 340 spdk_json_write_named_uint64(w, "num_blocks", spdk_bdev_get_num_blocks(bdev)); 341 342 if (!spdk_mem_all_zero(&bdev->uuid, sizeof(bdev->uuid))) { 343 char uuid_str[SPDK_UUID_STRING_LEN]; 344 345 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid); 346 spdk_json_write_named_string(w, "uuid", uuid_str); 347 } 348 349 if (spdk_bdev_get_md_size(bdev) != 0) { 350 spdk_json_write_named_uint32(w, "md_size", spdk_bdev_get_md_size(bdev)); 351 spdk_json_write_named_bool(w, "md_interleave", spdk_bdev_is_md_interleaved(bdev)); 352 spdk_json_write_named_uint32(w, "dif_type", spdk_bdev_get_dif_type(bdev)); 353 if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) { 354 spdk_json_write_named_bool(w, "dif_is_head_of_md", spdk_bdev_is_dif_head_of_md(bdev)); 355 spdk_json_write_named_object_begin(w, "enabled_dif_check_types"); 356 spdk_json_write_named_bool(w, "reftag", 357 spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG)); 358 spdk_json_write_named_bool(w, "apptag", 359 spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_APPTAG)); 360 spdk_json_write_named_bool(w, "guard", 361 spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD)); 362 spdk_json_write_object_end(w); 363 } 364 } 365 366 spdk_json_write_named_object_begin(w, "assigned_rate_limits"); 367 spdk_bdev_get_qos_rate_limits(bdev, qos_limits); 368 for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) { 369 spdk_json_write_named_uint64(w, spdk_bdev_get_qos_rpc_type(i), qos_limits[i]); 370 } 371 spdk_json_write_object_end(w); 372 373 spdk_json_write_named_bool(w, "claimed", (bdev->internal.claim_module != NULL)); 374 375 spdk_json_write_named_bool(w, "zoned", bdev->zoned); 376 if (bdev->zoned) { 377 spdk_json_write_named_uint64(w, "zone_size", bdev->zone_size); 378 spdk_json_write_named_uint64(w, "max_open_zones", bdev->max_open_zones); 379 spdk_json_write_named_uint64(w, "optimal_open_zones", bdev->optimal_open_zones); 380 } 381 382 spdk_json_write_named_object_begin(w, "supported_io_types"); 383 spdk_json_write_named_bool(w, "read", 384 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_READ)); 385 spdk_json_write_named_bool(w, "write", 386 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE)); 387 spdk_json_write_named_bool(w, "unmap", 388 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)); 389 spdk_json_write_named_bool(w, "write_zeroes", 390 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE_ZEROES)); 391 spdk_json_write_named_bool(w, "flush", 392 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_FLUSH)); 393 spdk_json_write_named_bool(w, "reset", 394 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_RESET)); 395 spdk_json_write_named_bool(w, "nvme_admin", 396 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_ADMIN)); 397 spdk_json_write_named_bool(w, "nvme_io", 398 spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_NVME_IO)); 399 spdk_json_write_object_end(w); 400 401 spdk_json_write_named_object_begin(w, "driver_specific"); 402 spdk_bdev_dump_info_json(bdev, w); 403 spdk_json_write_object_end(w); 404 405 spdk_json_write_object_end(w); 406 } 407 408 struct rpc_bdev_get_bdevs { 409 char *name; 410 }; 411 412 static void 413 free_rpc_bdev_get_bdevs(struct rpc_bdev_get_bdevs *r) 414 { 415 free(r->name); 416 } 417 418 static const struct spdk_json_object_decoder rpc_bdev_get_bdevs_decoders[] = { 419 {"name", offsetof(struct rpc_bdev_get_bdevs, name), spdk_json_decode_string, true}, 420 }; 421 422 static void 423 rpc_bdev_get_bdevs(struct spdk_jsonrpc_request *request, 424 const struct spdk_json_val *params) 425 { 426 struct rpc_bdev_get_bdevs req = {}; 427 struct spdk_json_write_ctx *w; 428 struct spdk_bdev *bdev = NULL; 429 430 if (params && spdk_json_decode_object(params, rpc_bdev_get_bdevs_decoders, 431 SPDK_COUNTOF(rpc_bdev_get_bdevs_decoders), 432 &req)) { 433 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 434 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 435 "spdk_json_decode_object failed"); 436 free_rpc_bdev_get_bdevs(&req); 437 return; 438 } 439 440 if (req.name) { 441 bdev = spdk_bdev_get_by_name(req.name); 442 if (bdev == NULL) { 443 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 444 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 445 free_rpc_bdev_get_bdevs(&req); 446 return; 447 } 448 } 449 450 free_rpc_bdev_get_bdevs(&req); 451 w = spdk_jsonrpc_begin_result(request); 452 spdk_json_write_array_begin(w); 453 454 if (bdev != NULL) { 455 rpc_dump_bdev_info(w, bdev); 456 } else { 457 for (bdev = spdk_bdev_first(); bdev != NULL; bdev = spdk_bdev_next(bdev)) { 458 rpc_dump_bdev_info(w, bdev); 459 } 460 } 461 462 spdk_json_write_array_end(w); 463 464 spdk_jsonrpc_end_result(request, w); 465 } 466 SPDK_RPC_REGISTER("bdev_get_bdevs", rpc_bdev_get_bdevs, SPDK_RPC_RUNTIME) 467 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_bdevs, get_bdevs) 468 469 struct rpc_bdev_set_qd_sampling_period { 470 char *name; 471 uint64_t period; 472 }; 473 474 static void 475 free_rpc_bdev_set_qd_sampling_period(struct rpc_bdev_set_qd_sampling_period *r) 476 { 477 free(r->name); 478 } 479 480 static const struct spdk_json_object_decoder 481 rpc_bdev_set_qd_sampling_period_decoders[] = { 482 {"name", offsetof(struct rpc_bdev_set_qd_sampling_period, name), spdk_json_decode_string}, 483 {"period", offsetof(struct rpc_bdev_set_qd_sampling_period, period), spdk_json_decode_uint64}, 484 }; 485 486 static void 487 rpc_bdev_set_qd_sampling_period(struct spdk_jsonrpc_request *request, 488 const struct spdk_json_val *params) 489 { 490 struct rpc_bdev_set_qd_sampling_period req = {0}; 491 struct spdk_bdev *bdev; 492 struct spdk_json_write_ctx *w; 493 494 if (spdk_json_decode_object(params, rpc_bdev_set_qd_sampling_period_decoders, 495 SPDK_COUNTOF(rpc_bdev_set_qd_sampling_period_decoders), 496 &req)) { 497 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 498 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 499 "spdk_json_decode_object failed"); 500 goto cleanup; 501 } 502 503 bdev = spdk_bdev_get_by_name(req.name); 504 if (bdev == NULL) { 505 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 506 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 507 goto cleanup; 508 } 509 510 w = spdk_jsonrpc_begin_result(request); 511 spdk_bdev_set_qd_sampling_period(bdev, req.period); 512 513 spdk_json_write_bool(w, true); 514 spdk_jsonrpc_end_result(request, w); 515 516 cleanup: 517 free_rpc_bdev_set_qd_sampling_period(&req); 518 } 519 SPDK_RPC_REGISTER("bdev_set_qd_sampling_period", 520 rpc_bdev_set_qd_sampling_period, 521 SPDK_RPC_RUNTIME) 522 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_qd_sampling_period, 523 set_bdev_qd_sampling_period) 524 525 struct rpc_bdev_set_qos_limit { 526 char *name; 527 uint64_t limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES]; 528 }; 529 530 static void 531 free_rpc_bdev_set_qos_limit(struct rpc_bdev_set_qos_limit *r) 532 { 533 free(r->name); 534 } 535 536 static const struct spdk_json_object_decoder rpc_bdev_set_qos_limit_decoders[] = { 537 {"name", offsetof(struct rpc_bdev_set_qos_limit, name), spdk_json_decode_string}, 538 { 539 "rw_ios_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 540 limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT]), 541 spdk_json_decode_uint64, true 542 }, 543 { 544 "rw_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 545 limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT]), 546 spdk_json_decode_uint64, true 547 }, 548 { 549 "r_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 550 limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT]), 551 spdk_json_decode_uint64, true 552 }, 553 { 554 "w_mbytes_per_sec", offsetof(struct rpc_bdev_set_qos_limit, 555 limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT]), 556 spdk_json_decode_uint64, true 557 }, 558 }; 559 560 static void 561 rpc_bdev_set_qos_limit_complete(void *cb_arg, int status) 562 { 563 struct spdk_jsonrpc_request *request = cb_arg; 564 struct spdk_json_write_ctx *w; 565 566 if (status != 0) { 567 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 568 "Failed to configure rate limit: %s", 569 spdk_strerror(-status)); 570 return; 571 } 572 573 w = spdk_jsonrpc_begin_result(request); 574 spdk_json_write_bool(w, true); 575 spdk_jsonrpc_end_result(request, w); 576 } 577 578 static void 579 rpc_bdev_set_qos_limit(struct spdk_jsonrpc_request *request, 580 const struct spdk_json_val *params) 581 { 582 struct rpc_bdev_set_qos_limit req = {NULL, {UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX}}; 583 struct spdk_bdev *bdev; 584 int i; 585 586 if (spdk_json_decode_object(params, rpc_bdev_set_qos_limit_decoders, 587 SPDK_COUNTOF(rpc_bdev_set_qos_limit_decoders), 588 &req)) { 589 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 590 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 591 "spdk_json_decode_object failed"); 592 goto cleanup; 593 } 594 595 bdev = spdk_bdev_get_by_name(req.name); 596 if (bdev == NULL) { 597 SPDK_ERRLOG("bdev '%s' does not exist\n", req.name); 598 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 599 goto cleanup; 600 } 601 602 for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) { 603 if (req.limits[i] != UINT64_MAX) { 604 break; 605 } 606 } 607 if (i == SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES) { 608 SPDK_ERRLOG("no rate limits specified\n"); 609 spdk_jsonrpc_send_error_response(request, -EINVAL, "No rate limits specified"); 610 goto cleanup; 611 } 612 613 spdk_bdev_set_qos_rate_limits(bdev, req.limits, rpc_bdev_set_qos_limit_complete, request); 614 615 cleanup: 616 free_rpc_bdev_set_qos_limit(&req); 617 } 618 619 SPDK_RPC_REGISTER("bdev_set_qos_limit", rpc_bdev_set_qos_limit, SPDK_RPC_RUNTIME) 620 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_set_qos_limit, set_bdev_qos_limit) 621 622 /* SPDK_RPC_ENABLE_BDEV_HISTOGRAM */ 623 624 struct rpc_bdev_enable_histogram_request { 625 char *name; 626 bool enable; 627 }; 628 629 static void 630 free_rpc_bdev_enable_histogram_request(struct rpc_bdev_enable_histogram_request *r) 631 { 632 free(r->name); 633 } 634 635 static const struct spdk_json_object_decoder rpc_bdev_enable_histogram_request_decoders[] = { 636 {"name", offsetof(struct rpc_bdev_enable_histogram_request, name), spdk_json_decode_string}, 637 {"enable", offsetof(struct rpc_bdev_enable_histogram_request, enable), spdk_json_decode_bool}, 638 }; 639 640 static void 641 bdev_histogram_status_cb(void *cb_arg, int status) 642 { 643 struct spdk_jsonrpc_request *request = cb_arg; 644 struct spdk_json_write_ctx *w = spdk_jsonrpc_begin_result(request); 645 646 spdk_json_write_bool(w, status == 0); 647 spdk_jsonrpc_end_result(request, w); 648 } 649 650 static void 651 rpc_bdev_enable_histogram(struct spdk_jsonrpc_request *request, 652 const struct spdk_json_val *params) 653 { 654 struct rpc_bdev_enable_histogram_request req = {NULL}; 655 struct spdk_bdev *bdev; 656 657 if (spdk_json_decode_object(params, rpc_bdev_enable_histogram_request_decoders, 658 SPDK_COUNTOF(rpc_bdev_enable_histogram_request_decoders), 659 &req)) { 660 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 661 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 662 "spdk_json_decode_object failed"); 663 goto cleanup; 664 } 665 666 bdev = spdk_bdev_get_by_name(req.name); 667 if (bdev == NULL) { 668 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 669 goto cleanup; 670 } 671 672 spdk_bdev_histogram_enable(bdev, bdev_histogram_status_cb, request, req.enable); 673 674 cleanup: 675 free_rpc_bdev_enable_histogram_request(&req); 676 } 677 678 SPDK_RPC_REGISTER("bdev_enable_histogram", rpc_bdev_enable_histogram, SPDK_RPC_RUNTIME) 679 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_enable_histogram, enable_bdev_histogram) 680 681 /* SPDK_RPC_GET_BDEV_HISTOGRAM */ 682 683 struct rpc_bdev_get_histogram_request { 684 char *name; 685 }; 686 687 static const struct spdk_json_object_decoder rpc_bdev_get_histogram_request_decoders[] = { 688 {"name", offsetof(struct rpc_bdev_get_histogram_request, name), spdk_json_decode_string} 689 }; 690 691 static void 692 free_rpc_bdev_get_histogram_request(struct rpc_bdev_get_histogram_request *r) 693 { 694 free(r->name); 695 } 696 697 static void 698 _rpc_bdev_histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram) 699 { 700 struct spdk_jsonrpc_request *request = cb_arg; 701 struct spdk_json_write_ctx *w; 702 int rc; 703 char *encoded_histogram; 704 size_t src_len, dst_len; 705 706 707 if (status != 0) { 708 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 709 spdk_strerror(-status)); 710 goto invalid; 711 } 712 713 src_len = SPDK_HISTOGRAM_NUM_BUCKETS(histogram) * sizeof(uint64_t); 714 dst_len = spdk_base64_get_encoded_strlen(src_len) + 1; 715 716 encoded_histogram = malloc(dst_len); 717 if (encoded_histogram == NULL) { 718 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 719 spdk_strerror(ENOMEM)); 720 goto invalid; 721 } 722 723 rc = spdk_base64_encode(encoded_histogram, histogram->bucket, src_len); 724 if (rc != 0) { 725 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 726 spdk_strerror(-rc)); 727 goto free_encoded_histogram; 728 } 729 730 w = spdk_jsonrpc_begin_result(request); 731 spdk_json_write_object_begin(w); 732 spdk_json_write_named_string(w, "histogram", encoded_histogram); 733 spdk_json_write_named_int64(w, "bucket_shift", histogram->bucket_shift); 734 spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz()); 735 spdk_json_write_object_end(w); 736 spdk_jsonrpc_end_result(request, w); 737 738 free_encoded_histogram: 739 free(encoded_histogram); 740 invalid: 741 spdk_histogram_data_free(histogram); 742 } 743 744 static void 745 rpc_bdev_get_histogram(struct spdk_jsonrpc_request *request, 746 const struct spdk_json_val *params) 747 { 748 struct rpc_bdev_get_histogram_request req = {NULL}; 749 struct spdk_histogram_data *histogram; 750 struct spdk_bdev *bdev; 751 752 if (spdk_json_decode_object(params, rpc_bdev_get_histogram_request_decoders, 753 SPDK_COUNTOF(rpc_bdev_get_histogram_request_decoders), 754 &req)) { 755 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 756 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 757 "spdk_json_decode_object failed"); 758 goto cleanup; 759 } 760 761 bdev = spdk_bdev_get_by_name(req.name); 762 if (bdev == NULL) { 763 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 764 goto cleanup; 765 } 766 767 histogram = spdk_histogram_data_alloc(); 768 if (histogram == NULL) { 769 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 770 goto cleanup; 771 } 772 773 spdk_bdev_histogram_get(bdev, histogram, _rpc_bdev_histogram_data_cb, request); 774 775 cleanup: 776 free_rpc_bdev_get_histogram_request(&req); 777 } 778 779 SPDK_RPC_REGISTER("bdev_get_histogram", rpc_bdev_get_histogram, SPDK_RPC_RUNTIME) 780 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_get_histogram, get_bdev_histogram) 781