1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2018 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "vbdev_ocf.h" 7 #include "stats.h" 8 #include "utils.h" 9 #include "spdk/log.h" 10 #include "spdk/rpc.h" 11 #include "spdk/string.h" 12 13 /* Common structure to hold the name parameter for RPC methods using bdev name only. */ 14 struct rpc_bdev_ocf_name { 15 char *name; /* main vbdev name */ 16 }; 17 18 /* Common free function for RPC methods using bdev name only. */ 19 static void 20 free_rpc_bdev_ocf_name(struct rpc_bdev_ocf_name *r) 21 { 22 free(r->name); 23 } 24 25 /* Common function to decode the name input parameter for RPC methods using bdev name only. */ 26 static const struct spdk_json_object_decoder rpc_bdev_ocf_name_decoders[] = { 27 {"name", offsetof(struct rpc_bdev_ocf_name, name), spdk_json_decode_string}, 28 }; 29 30 31 /* Structure to hold the parameters for this RPC method. */ 32 struct rpc_bdev_ocf_create { 33 char *name; /* main vbdev */ 34 char *mode; /* OCF mode (choose one) */ 35 uint64_t cache_line_size; /* OCF cache line size */ 36 char *cache_bdev_name; /* sub bdev */ 37 char *core_bdev_name; /* sub bdev */ 38 }; 39 40 static void 41 free_rpc_bdev_ocf_create(struct rpc_bdev_ocf_create *r) 42 { 43 free(r->name); 44 free(r->core_bdev_name); 45 free(r->cache_bdev_name); 46 free(r->mode); 47 } 48 49 /* Structure to decode the input parameters for this RPC method. */ 50 static const struct spdk_json_object_decoder rpc_bdev_ocf_create_decoders[] = { 51 {"name", offsetof(struct rpc_bdev_ocf_create, name), spdk_json_decode_string}, 52 {"mode", offsetof(struct rpc_bdev_ocf_create, mode), spdk_json_decode_string}, 53 {"cache_line_size", offsetof(struct rpc_bdev_ocf_create, cache_line_size), spdk_json_decode_uint64, true}, 54 {"cache_bdev_name", offsetof(struct rpc_bdev_ocf_create, cache_bdev_name), spdk_json_decode_string}, 55 {"core_bdev_name", offsetof(struct rpc_bdev_ocf_create, core_bdev_name), spdk_json_decode_string}, 56 }; 57 58 static void 59 construct_cb(int status, struct vbdev_ocf *vbdev, void *cb_arg) 60 { 61 struct spdk_jsonrpc_request *request = cb_arg; 62 struct spdk_json_write_ctx *w; 63 64 if (status) { 65 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 66 "Could not create OCF vbdev: %d", 67 status); 68 } else { 69 w = spdk_jsonrpc_begin_result(request); 70 spdk_json_write_string(w, vbdev->name); 71 spdk_jsonrpc_end_result(request, w); 72 } 73 } 74 75 static void 76 rpc_bdev_ocf_create(struct spdk_jsonrpc_request *request, 77 const struct spdk_json_val *params) 78 { 79 struct rpc_bdev_ocf_create req = {NULL}; 80 int ret; 81 82 ret = spdk_json_decode_object(params, rpc_bdev_ocf_create_decoders, 83 SPDK_COUNTOF(rpc_bdev_ocf_create_decoders), 84 &req); 85 if (ret) { 86 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 87 "Invalid parameters"); 88 free_rpc_bdev_ocf_create(&req); 89 return; 90 } 91 92 vbdev_ocf_construct(req.name, req.mode, req.cache_line_size, req.cache_bdev_name, 93 req.core_bdev_name, false, construct_cb, request); 94 free_rpc_bdev_ocf_create(&req); 95 } 96 SPDK_RPC_REGISTER("bdev_ocf_create", rpc_bdev_ocf_create, SPDK_RPC_RUNTIME) 97 98 static void 99 delete_cb(void *cb_arg, int status) 100 { 101 struct spdk_jsonrpc_request *request = cb_arg; 102 103 if (status) { 104 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 105 "Could not delete OCF vbdev: %d", 106 status); 107 } else { 108 spdk_jsonrpc_send_bool_response(request, true); 109 } 110 } 111 112 static void 113 rpc_bdev_ocf_delete(struct spdk_jsonrpc_request *request, 114 const struct spdk_json_val *params) 115 { 116 struct rpc_bdev_ocf_name req = {NULL}; 117 struct vbdev_ocf *vbdev; 118 int status; 119 120 status = spdk_json_decode_object(params, rpc_bdev_ocf_name_decoders, 121 SPDK_COUNTOF(rpc_bdev_ocf_name_decoders), 122 &req); 123 if (status) { 124 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 125 "Invalid parameters"); 126 goto end; 127 } 128 129 vbdev = vbdev_ocf_get_by_name(req.name); 130 if (vbdev == NULL) { 131 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 132 spdk_strerror(ENODEV)); 133 goto end; 134 } 135 136 status = vbdev_ocf_delete_clean(vbdev, delete_cb, request); 137 if (status) { 138 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 139 "Could not delete OCF vbdev: %s", 140 spdk_strerror(-status)); 141 goto end; 142 } 143 144 end: 145 free_rpc_bdev_ocf_name(&req); 146 } 147 SPDK_RPC_REGISTER("bdev_ocf_delete", rpc_bdev_ocf_delete, SPDK_RPC_RUNTIME) 148 149 struct get_ocf_stats_ctx { 150 struct spdk_jsonrpc_request *request; 151 char *core_name; 152 }; 153 154 static void 155 rpc_bdev_ocf_get_stats_cmpl(ocf_cache_t cache, void *priv, int error) 156 { 157 struct get_ocf_stats_ctx *ctx = (struct get_ocf_stats_ctx *) priv; 158 struct spdk_json_write_ctx *w; 159 struct vbdev_ocf_stats stats; 160 161 if (error) { 162 goto end; 163 } 164 165 error = vbdev_ocf_stats_get(cache, ctx->core_name, &stats); 166 167 ocf_mngt_cache_read_unlock(cache); 168 169 if (error) { 170 goto end; 171 } 172 173 w = spdk_jsonrpc_begin_result(ctx->request); 174 vbdev_ocf_stats_write_json(w, &stats); 175 spdk_jsonrpc_end_result(ctx->request, w); 176 177 end: 178 if (error) { 179 spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 180 "Could not get stats: %s", 181 spdk_strerror(-error)); 182 } 183 free(ctx); 184 } 185 186 static void 187 rpc_bdev_ocf_get_stats(struct spdk_jsonrpc_request *request, 188 const struct spdk_json_val *params) 189 { 190 struct rpc_bdev_ocf_name req = {NULL}; 191 struct vbdev_ocf *vbdev; 192 struct get_ocf_stats_ctx *ctx; 193 194 ctx = calloc(1, sizeof(*ctx)); 195 if (!ctx) { 196 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 197 "Not enough memory to process request"); 198 goto end; 199 } 200 201 if (spdk_json_decode_object(params, rpc_bdev_ocf_name_decoders, 202 SPDK_COUNTOF(rpc_bdev_ocf_name_decoders), 203 &req)) { 204 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 205 "Invalid parameters"); 206 free(ctx); 207 goto end; 208 } 209 210 vbdev = vbdev_ocf_get_by_name(req.name); 211 if (vbdev == NULL) { 212 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 213 spdk_strerror(ENODEV)); 214 free(ctx); 215 goto end; 216 } 217 218 ctx->core_name = vbdev->core.name; 219 ctx->request = request; 220 ocf_mngt_cache_read_lock(vbdev->ocf_cache, rpc_bdev_ocf_get_stats_cmpl, ctx); 221 222 end: 223 free_rpc_bdev_ocf_name(&req); 224 } 225 SPDK_RPC_REGISTER("bdev_ocf_get_stats", rpc_bdev_ocf_get_stats, SPDK_RPC_RUNTIME) 226 227 static void 228 rpc_bdev_ocf_reset_stats_cmpl(ocf_cache_t cache, void *priv, int error) 229 { 230 struct get_ocf_stats_ctx *ctx = (struct get_ocf_stats_ctx *) priv; 231 232 if (error) { 233 goto end; 234 } 235 236 error = vbdev_ocf_stats_reset(cache, ctx->core_name); 237 238 ocf_mngt_cache_read_unlock(cache); 239 240 end: 241 if (error) { 242 spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 243 "Could not reset stats: %s", 244 spdk_strerror(-error)); 245 } else { 246 spdk_jsonrpc_send_bool_response(ctx->request, true); 247 } 248 free(ctx); 249 } 250 251 static void 252 rpc_bdev_ocf_reset_stats(struct spdk_jsonrpc_request *request, 253 const struct spdk_json_val *params) 254 { 255 struct rpc_bdev_ocf_name req = {NULL}; 256 struct vbdev_ocf *vbdev; 257 struct get_ocf_stats_ctx *ctx; 258 259 ctx = calloc(1, sizeof(*ctx)); 260 if (!ctx) { 261 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 262 "Not enough memory to process request"); 263 goto end; 264 } 265 266 if (spdk_json_decode_object(params, rpc_bdev_ocf_name_decoders, 267 SPDK_COUNTOF(rpc_bdev_ocf_name_decoders), 268 &req)) { 269 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 270 "Invalid parameters"); 271 free(ctx); 272 goto end; 273 } 274 275 vbdev = vbdev_ocf_get_by_name(req.name); 276 if (vbdev == NULL) { 277 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 278 spdk_strerror(ENODEV)); 279 free(ctx); 280 goto end; 281 } 282 283 ctx->core_name = vbdev->core.name; 284 ctx->request = request; 285 ocf_mngt_cache_read_lock(vbdev->ocf_cache, rpc_bdev_ocf_reset_stats_cmpl, ctx); 286 287 end: 288 free_rpc_bdev_ocf_name(&req); 289 } 290 SPDK_RPC_REGISTER("bdev_ocf_reset_stats", rpc_bdev_ocf_reset_stats, SPDK_RPC_RUNTIME) 291 292 /* Structure to decode the input parameters for this RPC method. */ 293 static const struct spdk_json_object_decoder rpc_bdev_ocf_get_bdevs_decoders[] = { 294 {"name", offsetof(struct rpc_bdev_ocf_name, name), spdk_json_decode_string, true}, 295 }; 296 297 struct bdev_get_bdevs_ctx { 298 char *name; 299 struct spdk_json_write_ctx *w; 300 }; 301 302 static void 303 bdev_get_bdevs_fn(struct vbdev_ocf *vbdev, void *ctx) 304 { 305 struct bdev_get_bdevs_ctx *cctx = ctx; 306 struct spdk_json_write_ctx *w = cctx->w; 307 308 if (cctx->name != NULL && 309 strcmp(vbdev->name, cctx->name) && 310 strcmp(vbdev->cache.name, cctx->name) && 311 strcmp(vbdev->core.name, cctx->name)) { 312 return; 313 } 314 315 spdk_json_write_object_begin(w); 316 spdk_json_write_named_string(w, "name", vbdev->name); 317 spdk_json_write_named_bool(w, "started", vbdev->state.started); 318 319 spdk_json_write_named_object_begin(w, "cache"); 320 spdk_json_write_named_string(w, "name", vbdev->cache.name); 321 spdk_json_write_named_bool(w, "attached", vbdev->cache.attached); 322 spdk_json_write_object_end(w); 323 324 spdk_json_write_named_object_begin(w, "core"); 325 spdk_json_write_named_string(w, "name", vbdev->core.name); 326 spdk_json_write_named_bool(w, "attached", vbdev->core.attached); 327 spdk_json_write_object_end(w); 328 329 spdk_json_write_object_end(w); 330 } 331 332 static void 333 rpc_bdev_ocf_get_bdevs(struct spdk_jsonrpc_request *request, 334 const struct spdk_json_val *params) 335 { 336 struct spdk_json_write_ctx *w; 337 struct rpc_bdev_ocf_name req = {NULL}; 338 struct bdev_get_bdevs_ctx cctx; 339 340 if (params && spdk_json_decode_object(params, rpc_bdev_ocf_get_bdevs_decoders, 341 SPDK_COUNTOF(rpc_bdev_ocf_get_bdevs_decoders), 342 &req)) { 343 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 344 "Invalid parameters"); 345 goto end; 346 } 347 348 if (req.name) { 349 if (!(vbdev_ocf_get_by_name(req.name) || vbdev_ocf_get_base_by_name(req.name))) { 350 spdk_jsonrpc_send_error_response(request, 351 SPDK_JSONRPC_ERROR_INVALID_PARAMS, 352 spdk_strerror(ENODEV)); 353 goto end; 354 } 355 } 356 357 w = spdk_jsonrpc_begin_result(request); 358 359 cctx.name = req.name; 360 cctx.w = w; 361 362 spdk_json_write_array_begin(w); 363 vbdev_ocf_foreach(bdev_get_bdevs_fn, &cctx); 364 spdk_json_write_array_end(w); 365 spdk_jsonrpc_end_result(request, w); 366 367 end: 368 free_rpc_bdev_ocf_name(&req); 369 } 370 SPDK_RPC_REGISTER("bdev_ocf_get_bdevs", rpc_bdev_ocf_get_bdevs, SPDK_RPC_RUNTIME) 371 372 /* Structure to hold the parameters for this RPC method. */ 373 struct rpc_bdev_ocf_set_cache_mode { 374 char *name; /* main vbdev name */ 375 char *mode; /* OCF cache mode to switch to */ 376 }; 377 378 static void 379 free_rpc_bdev_ocf_set_cache_mode(struct rpc_bdev_ocf_set_cache_mode *r) 380 { 381 free(r->name); 382 free(r->mode); 383 } 384 385 /* Structure to decode the input parameters for this RPC method. */ 386 static const struct spdk_json_object_decoder rpc_bdev_ocf_set_cache_mode_decoders[] = { 387 {"name", offsetof(struct rpc_bdev_ocf_set_cache_mode, name), spdk_json_decode_string}, 388 {"mode", offsetof(struct rpc_bdev_ocf_set_cache_mode, mode), spdk_json_decode_string}, 389 }; 390 391 static void 392 cache_mode_cb(int status, struct vbdev_ocf *vbdev, void *cb_arg) 393 { 394 struct spdk_jsonrpc_request *request = cb_arg; 395 struct spdk_json_write_ctx *w; 396 397 if (status) { 398 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 399 "Could not change OCF vbdev cache mode: %d", 400 status); 401 } else { 402 w = spdk_jsonrpc_begin_result(request); 403 spdk_json_write_string(w, ocf_get_cache_modename( 404 ocf_cache_get_mode(vbdev->ocf_cache))); 405 spdk_jsonrpc_end_result(request, w); 406 } 407 } 408 409 static void 410 rpc_bdev_ocf_set_cache_mode(struct spdk_jsonrpc_request *request, 411 const struct spdk_json_val *params) 412 { 413 struct rpc_bdev_ocf_set_cache_mode req = {NULL}; 414 struct vbdev_ocf *vbdev; 415 int status; 416 417 status = spdk_json_decode_object(params, rpc_bdev_ocf_set_cache_mode_decoders, 418 SPDK_COUNTOF(rpc_bdev_ocf_set_cache_mode_decoders), 419 &req); 420 if (status) { 421 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 422 "Invalid parameters"); 423 goto end; 424 } 425 426 vbdev = vbdev_ocf_get_by_name(req.name); 427 if (vbdev == NULL) { 428 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 429 spdk_strerror(ENODEV)); 430 goto end; 431 } 432 433 vbdev_ocf_set_cache_mode(vbdev, req.mode, cache_mode_cb, request); 434 435 end: 436 free_rpc_bdev_ocf_set_cache_mode(&req); 437 } 438 SPDK_RPC_REGISTER("bdev_ocf_set_cache_mode", rpc_bdev_ocf_set_cache_mode, SPDK_RPC_RUNTIME) 439 440 static void 441 seqcutoff_cb(int status, void *cb_arg) 442 { 443 struct spdk_jsonrpc_request *request = cb_arg; 444 445 if (status) { 446 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 447 "OCF could not set sequential cutoff parameters: %d", status); 448 } else { 449 spdk_jsonrpc_send_bool_response(request, true); 450 } 451 } 452 453 /* Structure to hold the parameters for this RPC method. */ 454 struct rpc_bdev_ocf_set_seqcutoff { 455 char *name; /* main vbdev name */ 456 char *policy; 457 uint32_t threshold; 458 uint32_t promotion_count; 459 }; 460 461 static void 462 free_rpc_bdev_ocf_set_seqcutoff(struct rpc_bdev_ocf_set_seqcutoff *r) 463 { 464 free(r->name); 465 free(r->policy); 466 } 467 468 /* Structure to decode the input parameters for this RPC method. */ 469 static const struct spdk_json_object_decoder rpc_bdev_ocf_set_seqcutoff_decoders[] = { 470 {"name", offsetof(struct rpc_bdev_ocf_set_seqcutoff, name), spdk_json_decode_string}, 471 {"policy", offsetof(struct rpc_bdev_ocf_set_seqcutoff, policy), spdk_json_decode_string}, 472 {"threshold", offsetof(struct rpc_bdev_ocf_set_seqcutoff, threshold), spdk_json_decode_uint32, true}, 473 {"promotion_count", offsetof(struct rpc_bdev_ocf_set_seqcutoff, promotion_count), spdk_json_decode_uint32, true}, 474 }; 475 476 static void 477 rpc_bdev_ocf_set_seqcutoff(struct spdk_jsonrpc_request *request, 478 const struct spdk_json_val *params) 479 { 480 struct rpc_bdev_ocf_set_seqcutoff req = {NULL}; 481 struct vbdev_ocf *vbdev; 482 int ret; 483 484 ret = spdk_json_decode_object(params, rpc_bdev_ocf_set_seqcutoff_decoders, 485 SPDK_COUNTOF(rpc_bdev_ocf_set_seqcutoff_decoders), &req); 486 if (ret) { 487 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 488 "Invalid parameters"); 489 goto end; 490 } 491 492 vbdev = vbdev_ocf_get_by_name(req.name); 493 if (vbdev == NULL) { 494 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 495 spdk_strerror(ENODEV)); 496 goto end; 497 } 498 499 vbdev_ocf_set_seqcutoff(vbdev, req.policy, req.threshold, req.promotion_count, seqcutoff_cb, 500 request); 501 502 end: 503 free_rpc_bdev_ocf_set_seqcutoff(&req); 504 } 505 SPDK_RPC_REGISTER("bdev_ocf_set_seqcutoff", rpc_bdev_ocf_set_seqcutoff, SPDK_RPC_RUNTIME) 506 507 struct get_ocf_flush_start_ctx { 508 struct spdk_jsonrpc_request *request; 509 struct vbdev_ocf *vbdev; 510 }; 511 512 static void 513 rpc_bdev_ocf_flush_start_cmpl(ocf_cache_t cache, void *priv, int error) 514 { 515 struct get_ocf_flush_start_ctx *ctx = priv; 516 517 ctx->vbdev->flush.in_progress = false; 518 ctx->vbdev->flush.status = error; 519 520 ocf_mngt_cache_read_unlock(cache); 521 522 free(ctx); 523 } 524 525 static void 526 rpc_bdev_ocf_flush_start_lock_cmpl(ocf_cache_t cache, void *priv, int error) 527 { 528 struct get_ocf_flush_start_ctx *ctx = priv; 529 530 if (error) { 531 spdk_jsonrpc_send_error_response_fmt(ctx->request, 532 SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 533 "Could not lock cache: %d", error); 534 free(ctx); 535 return; 536 } 537 538 ctx->vbdev->flush.in_progress = true; 539 ocf_mngt_cache_flush(cache, rpc_bdev_ocf_flush_start_cmpl, ctx); 540 541 spdk_jsonrpc_send_bool_response(ctx->request, true); 542 } 543 544 static void 545 rpc_bdev_ocf_flush_start(struct spdk_jsonrpc_request *request, 546 const struct spdk_json_val *params) 547 { 548 struct rpc_bdev_ocf_name req = {NULL}; 549 struct get_ocf_flush_start_ctx *ctx; 550 int status; 551 552 ctx = calloc(1, sizeof(*ctx)); 553 if (!ctx) { 554 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 555 "Not enough memory to process request"); 556 goto end; 557 } 558 559 status = spdk_json_decode_object(params, rpc_bdev_ocf_name_decoders, 560 SPDK_COUNTOF(rpc_bdev_ocf_name_decoders), 561 &req); 562 if (status) { 563 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 564 "Invalid parameters"); 565 free(ctx); 566 goto end; 567 } 568 569 ctx->vbdev = vbdev_ocf_get_by_name(req.name); 570 if (ctx->vbdev == NULL) { 571 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 572 spdk_strerror(ENODEV)); 573 free(ctx); 574 goto end; 575 } 576 577 if (!ctx->vbdev->ocf_cache) { 578 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 579 "Couldn't flush cache: device not attached"); 580 free(ctx); 581 goto end; 582 } 583 584 ctx->request = request; 585 ocf_mngt_cache_read_lock(ctx->vbdev->ocf_cache, rpc_bdev_ocf_flush_start_lock_cmpl, ctx); 586 587 end: 588 free_rpc_bdev_ocf_name(&req); 589 } 590 SPDK_RPC_REGISTER("bdev_ocf_flush_start", rpc_bdev_ocf_flush_start, SPDK_RPC_RUNTIME) 591 592 static void 593 rpc_bdev_ocf_flush_status(struct spdk_jsonrpc_request *request, 594 const struct spdk_json_val *params) 595 { 596 struct rpc_bdev_ocf_name req = {NULL}; 597 struct spdk_json_write_ctx *w; 598 struct vbdev_ocf *vbdev; 599 int status; 600 601 status = spdk_json_decode_object(params, rpc_bdev_ocf_name_decoders, 602 SPDK_COUNTOF(rpc_bdev_ocf_name_decoders), 603 &req); 604 if (status) { 605 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 606 "Invalid parameters"); 607 goto end; 608 } 609 610 vbdev = vbdev_ocf_get_by_name(req.name); 611 if (vbdev == NULL) { 612 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 613 spdk_strerror(ENODEV)); 614 goto end; 615 } 616 617 w = spdk_jsonrpc_begin_result(request); 618 619 spdk_json_write_object_begin(w); 620 spdk_json_write_named_bool(w, "in_progress", vbdev->flush.in_progress); 621 if (!vbdev->flush.in_progress) { 622 spdk_json_write_named_int32(w, "status", vbdev->flush.status); 623 } 624 spdk_json_write_object_end(w); 625 626 spdk_jsonrpc_end_result(request, w); 627 628 end: 629 free_rpc_bdev_ocf_name(&req); 630 } 631 SPDK_RPC_REGISTER("bdev_ocf_flush_status", rpc_bdev_ocf_flush_status, SPDK_RPC_RUNTIME) 632