1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2018 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/rpc.h" 7 #include "spdk/bdev.h" 8 #include "bdev_raid.h" 9 #include "spdk/util.h" 10 #include "spdk/string.h" 11 #include "spdk/log.h" 12 #include "spdk/env.h" 13 14 #define RPC_MAX_BASE_BDEVS 255 15 16 /* 17 * Input structure for bdev_raid_get_bdevs RPC 18 */ 19 struct rpc_bdev_raid_get_bdevs { 20 /* category - all or online or configuring or offline */ 21 char *category; 22 }; 23 24 /* 25 * brief: 26 * free_rpc_bdev_raid_get_bdevs function frees RPC bdev_raid_get_bdevs related parameters 27 * params: 28 * req - pointer to RPC request 29 * returns: 30 * none 31 */ 32 static void 33 free_rpc_bdev_raid_get_bdevs(struct rpc_bdev_raid_get_bdevs *req) 34 { 35 free(req->category); 36 } 37 38 /* 39 * Decoder object for RPC get_raids 40 */ 41 static const struct spdk_json_object_decoder rpc_bdev_raid_get_bdevs_decoders[] = { 42 {"category", offsetof(struct rpc_bdev_raid_get_bdevs, category), spdk_json_decode_string}, 43 }; 44 45 /* 46 * brief: 47 * rpc_bdev_raid_get_bdevs function is the RPC for rpc_bdev_raid_get_bdevs. This is used to list 48 * all the raid bdev names based on the input category requested. Category should be 49 * one of "all", "online", "configuring" or "offline". "all" means all the raids 50 * whether they are online or configuring or offline. "online" is the raid bdev which 51 * is registered with bdev layer. "configuring" is the raid bdev which does not have 52 * full configuration discovered yet. "offline" is the raid bdev which is not 53 * registered with bdev as of now and it has encountered any error or user has 54 * requested to offline the raid. 55 * params: 56 * request - pointer to json rpc request 57 * params - pointer to request parameters 58 * returns: 59 * none 60 */ 61 static void 62 rpc_bdev_raid_get_bdevs(struct spdk_jsonrpc_request *request, 63 const struct spdk_json_val *params) 64 { 65 struct rpc_bdev_raid_get_bdevs req = {}; 66 struct spdk_json_write_ctx *w; 67 struct raid_bdev *raid_bdev; 68 enum raid_bdev_state state; 69 70 if (spdk_json_decode_object(params, rpc_bdev_raid_get_bdevs_decoders, 71 SPDK_COUNTOF(rpc_bdev_raid_get_bdevs_decoders), 72 &req)) { 73 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 74 "spdk_json_decode_object failed"); 75 goto cleanup; 76 } 77 78 state = raid_bdev_str_to_state(req.category); 79 if (state == RAID_BDEV_STATE_MAX && strcmp(req.category, "all") != 0) { 80 spdk_jsonrpc_send_error_response(request, -EINVAL, spdk_strerror(EINVAL)); 81 goto cleanup; 82 } 83 84 w = spdk_jsonrpc_begin_result(request); 85 spdk_json_write_array_begin(w); 86 87 /* Get raid bdev list based on the category requested */ 88 TAILQ_FOREACH(raid_bdev, &g_raid_bdev_list, global_link) { 89 if (raid_bdev->state == state || state == RAID_BDEV_STATE_MAX) { 90 char uuid_str[SPDK_UUID_STRING_LEN]; 91 92 spdk_json_write_object_begin(w); 93 spdk_json_write_named_string(w, "name", raid_bdev->bdev.name); 94 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &raid_bdev->bdev.uuid); 95 spdk_json_write_named_string(w, "uuid", uuid_str); 96 raid_bdev_write_info_json(raid_bdev, w); 97 spdk_json_write_object_end(w); 98 } 99 } 100 spdk_json_write_array_end(w); 101 spdk_jsonrpc_end_result(request, w); 102 103 cleanup: 104 free_rpc_bdev_raid_get_bdevs(&req); 105 } 106 SPDK_RPC_REGISTER("bdev_raid_get_bdevs", rpc_bdev_raid_get_bdevs, SPDK_RPC_RUNTIME) 107 108 /* 109 * Base bdevs in RPC bdev_raid_create 110 */ 111 struct rpc_bdev_raid_create_base_bdevs { 112 /* Number of base bdevs */ 113 size_t num_base_bdevs; 114 115 /* List of base bdevs names */ 116 char *base_bdevs[RPC_MAX_BASE_BDEVS]; 117 }; 118 119 /* 120 * Input structure for RPC rpc_bdev_raid_create 121 */ 122 struct rpc_bdev_raid_create { 123 /* Raid bdev name */ 124 char *name; 125 126 /* RAID strip size in KB */ 127 uint32_t strip_size_kb; 128 129 /* RAID raid level */ 130 enum raid_level level; 131 132 /* Base bdevs information */ 133 struct rpc_bdev_raid_create_base_bdevs base_bdevs; 134 135 /* UUID for this raid bdev */ 136 struct spdk_uuid uuid; 137 138 /* If set, information about raid bdev will be stored in superblock on each base bdev */ 139 bool superblock_enabled; 140 }; 141 142 /* 143 * Decoder function for RPC bdev_raid_create to decode raid level 144 */ 145 static int 146 decode_raid_level(const struct spdk_json_val *val, void *out) 147 { 148 int ret; 149 char *str = NULL; 150 enum raid_level level; 151 152 ret = spdk_json_decode_string(val, &str); 153 if (ret == 0 && str != NULL) { 154 level = raid_bdev_str_to_level(str); 155 if (level == INVALID_RAID_LEVEL) { 156 ret = -EINVAL; 157 } else { 158 *(enum raid_level *)out = level; 159 } 160 } 161 162 free(str); 163 return ret; 164 } 165 166 /* 167 * Decoder function for RPC bdev_raid_create to decode base bdevs list 168 */ 169 static int 170 decode_base_bdevs(const struct spdk_json_val *val, void *out) 171 { 172 struct rpc_bdev_raid_create_base_bdevs *base_bdevs = out; 173 return spdk_json_decode_array(val, spdk_json_decode_string, base_bdevs->base_bdevs, 174 RPC_MAX_BASE_BDEVS, &base_bdevs->num_base_bdevs, sizeof(char *)); 175 } 176 177 /* 178 * Decoder object for RPC bdev_raid_create 179 */ 180 static const struct spdk_json_object_decoder rpc_bdev_raid_create_decoders[] = { 181 {"name", offsetof(struct rpc_bdev_raid_create, name), spdk_json_decode_string}, 182 {"strip_size_kb", offsetof(struct rpc_bdev_raid_create, strip_size_kb), spdk_json_decode_uint32, true}, 183 {"raid_level", offsetof(struct rpc_bdev_raid_create, level), decode_raid_level}, 184 {"base_bdevs", offsetof(struct rpc_bdev_raid_create, base_bdevs), decode_base_bdevs}, 185 {"uuid", offsetof(struct rpc_bdev_raid_create, uuid), spdk_json_decode_uuid, true}, 186 {"superblock", offsetof(struct rpc_bdev_raid_create, superblock_enabled), spdk_json_decode_bool, true}, 187 }; 188 189 struct rpc_bdev_raid_create_ctx { 190 struct rpc_bdev_raid_create req; 191 struct raid_bdev *raid_bdev; 192 struct spdk_jsonrpc_request *request; 193 uint8_t remaining; 194 int status; 195 }; 196 197 static void 198 free_rpc_bdev_raid_create_ctx(struct rpc_bdev_raid_create_ctx *ctx) 199 { 200 struct rpc_bdev_raid_create *req; 201 size_t i; 202 203 if (!ctx) { 204 return; 205 } 206 207 req = &ctx->req; 208 209 free(req->name); 210 for (i = 0; i < req->base_bdevs.num_base_bdevs; i++) { 211 free(req->base_bdevs.base_bdevs[i]); 212 } 213 214 free(ctx); 215 } 216 217 static void 218 rpc_bdev_raid_create_add_base_bdev_cb(void *_ctx, int status) 219 { 220 struct rpc_bdev_raid_create_ctx *ctx = _ctx; 221 222 if (status != 0) { 223 ctx->status = status; 224 } 225 226 assert(ctx->remaining != 0); 227 if (--ctx->remaining > 0) { 228 return; 229 } 230 231 if (ctx->status != 0) { 232 raid_bdev_delete(ctx->raid_bdev, NULL, NULL); 233 spdk_jsonrpc_send_error_response_fmt(ctx->request, ctx->status, 234 "Failed to create RAID bdev %s: %s", 235 ctx->req.name, 236 spdk_strerror(-ctx->status)); 237 } else { 238 spdk_jsonrpc_send_bool_response(ctx->request, true); 239 } 240 241 free_rpc_bdev_raid_create_ctx(ctx); 242 } 243 244 /* 245 * brief: 246 * rpc_bdev_raid_create function is the RPC for creating RAID bdevs. It takes 247 * input as raid bdev name, raid level, strip size in KB and list of base bdev names. 248 * params: 249 * request - pointer to json rpc request 250 * params - pointer to request parameters 251 * returns: 252 * none 253 */ 254 static void 255 rpc_bdev_raid_create(struct spdk_jsonrpc_request *request, 256 const struct spdk_json_val *params) 257 { 258 struct rpc_bdev_raid_create *req; 259 struct raid_bdev *raid_bdev; 260 int rc; 261 size_t i; 262 struct rpc_bdev_raid_create_ctx *ctx; 263 uint8_t num_base_bdevs; 264 265 ctx = calloc(1, sizeof(*ctx)); 266 if (ctx == NULL) { 267 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 268 goto cleanup; 269 } 270 req = &ctx->req; 271 272 if (spdk_json_decode_object(params, rpc_bdev_raid_create_decoders, 273 SPDK_COUNTOF(rpc_bdev_raid_create_decoders), 274 req)) { 275 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 276 "spdk_json_decode_object failed"); 277 goto cleanup; 278 } 279 num_base_bdevs = req->base_bdevs.num_base_bdevs; 280 281 for (i = 0; i < num_base_bdevs; i++) { 282 if (strlen(req->base_bdevs.base_bdevs[i]) == 0) { 283 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 284 "The base bdev name cannot be empty: %s", 285 spdk_strerror(EINVAL)); 286 goto cleanup; 287 } 288 } 289 290 rc = raid_bdev_create(req->name, req->strip_size_kb, num_base_bdevs, 291 req->level, req->superblock_enabled, &req->uuid, &raid_bdev); 292 if (rc != 0) { 293 spdk_jsonrpc_send_error_response_fmt(request, rc, 294 "Failed to create RAID bdev %s: %s", 295 req->name, spdk_strerror(-rc)); 296 goto cleanup; 297 } 298 299 ctx->raid_bdev = raid_bdev; 300 ctx->request = request; 301 ctx->remaining = num_base_bdevs; 302 303 assert(num_base_bdevs > 0); 304 305 for (i = 0; i < num_base_bdevs; i++) { 306 const char *base_bdev_name = req->base_bdevs.base_bdevs[i]; 307 308 rc = raid_bdev_add_base_bdev(raid_bdev, base_bdev_name, 309 rpc_bdev_raid_create_add_base_bdev_cb, ctx); 310 if (rc == -ENODEV) { 311 SPDK_DEBUGLOG(bdev_raid, "base bdev %s doesn't exist now\n", base_bdev_name); 312 assert(ctx->remaining > 1 || i + 1 == num_base_bdevs); 313 rpc_bdev_raid_create_add_base_bdev_cb(ctx, 0); 314 } else if (rc != 0) { 315 SPDK_DEBUGLOG(bdev_raid, "Failed to add base bdev %s to RAID bdev %s: %s", 316 base_bdev_name, req->name, spdk_strerror(-rc)); 317 ctx->remaining -= (num_base_bdevs - i - 1); 318 rpc_bdev_raid_create_add_base_bdev_cb(ctx, rc); 319 break; 320 } 321 } 322 return; 323 cleanup: 324 free_rpc_bdev_raid_create_ctx(ctx); 325 } 326 SPDK_RPC_REGISTER("bdev_raid_create", rpc_bdev_raid_create, SPDK_RPC_RUNTIME) 327 328 /* 329 * Input structure for RPC deleting a raid bdev 330 */ 331 struct rpc_bdev_raid_delete { 332 /* raid bdev name */ 333 char *name; 334 }; 335 336 /* 337 * brief: 338 * free_rpc_bdev_raid_delete function is used to free RPC bdev_raid_delete related parameters 339 * params: 340 * req - pointer to RPC request 341 * params: 342 * none 343 */ 344 static void 345 free_rpc_bdev_raid_delete(struct rpc_bdev_raid_delete *req) 346 { 347 free(req->name); 348 } 349 350 /* 351 * Decoder object for RPC raid_bdev_delete 352 */ 353 static const struct spdk_json_object_decoder rpc_bdev_raid_delete_decoders[] = { 354 {"name", offsetof(struct rpc_bdev_raid_delete, name), spdk_json_decode_string}, 355 }; 356 357 struct rpc_bdev_raid_delete_ctx { 358 struct rpc_bdev_raid_delete req; 359 struct spdk_jsonrpc_request *request; 360 }; 361 362 /* 363 * brief: 364 * params: 365 * cb_arg - pointer to the callback context. 366 * rc - return code of the deletion of the raid bdev. 367 * returns: 368 * none 369 */ 370 static void 371 bdev_raid_delete_done(void *cb_arg, int rc) 372 { 373 struct rpc_bdev_raid_delete_ctx *ctx = cb_arg; 374 struct spdk_jsonrpc_request *request = ctx->request; 375 376 if (rc != 0) { 377 SPDK_ERRLOG("Failed to delete raid bdev %s (%d): %s\n", 378 ctx->req.name, rc, spdk_strerror(-rc)); 379 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 380 spdk_strerror(-rc)); 381 goto exit; 382 } 383 384 spdk_jsonrpc_send_bool_response(request, true); 385 exit: 386 free_rpc_bdev_raid_delete(&ctx->req); 387 free(ctx); 388 } 389 390 /* 391 * brief: 392 * rpc_bdev_raid_delete function is the RPC for deleting a raid bdev. It takes raid 393 * name as input and delete that raid bdev including freeing the base bdev 394 * resources. 395 * params: 396 * request - pointer to json rpc request 397 * params - pointer to request parameters 398 * returns: 399 * none 400 */ 401 static void 402 rpc_bdev_raid_delete(struct spdk_jsonrpc_request *request, 403 const struct spdk_json_val *params) 404 { 405 struct rpc_bdev_raid_delete_ctx *ctx; 406 struct raid_bdev *raid_bdev; 407 408 ctx = calloc(1, sizeof(*ctx)); 409 if (!ctx) { 410 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 411 return; 412 } 413 414 if (spdk_json_decode_object(params, rpc_bdev_raid_delete_decoders, 415 SPDK_COUNTOF(rpc_bdev_raid_delete_decoders), 416 &ctx->req)) { 417 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 418 "spdk_json_decode_object failed"); 419 goto cleanup; 420 } 421 422 raid_bdev = raid_bdev_find_by_name(ctx->req.name); 423 if (raid_bdev == NULL) { 424 spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, 425 "raid bdev %s not found", 426 ctx->req.name); 427 goto cleanup; 428 } 429 430 ctx->request = request; 431 432 raid_bdev_delete(raid_bdev, bdev_raid_delete_done, ctx); 433 434 return; 435 436 cleanup: 437 free_rpc_bdev_raid_delete(&ctx->req); 438 free(ctx); 439 } 440 SPDK_RPC_REGISTER("bdev_raid_delete", rpc_bdev_raid_delete, SPDK_RPC_RUNTIME) 441 442 /* 443 * Base bdevs in RPC bdev_raid_add_base_bdev 444 */ 445 struct rpc_bdev_raid_add_base_bdev { 446 /* Base bdev name */ 447 char *base_bdev; 448 449 /* Raid bdev name */ 450 char *raid_bdev; 451 }; 452 453 /* 454 * brief: 455 * free_rpc_bdev_raid_add_base_bdev function is to free RPC 456 * bdev_raid_add_base_bdev related parameters. 457 * params: 458 * req - pointer to RPC request 459 * returns: 460 * none 461 */ 462 static void 463 free_rpc_bdev_raid_add_base_bdev(struct rpc_bdev_raid_add_base_bdev *req) 464 { 465 free(req->base_bdev); 466 free(req->raid_bdev); 467 } 468 469 /* 470 * Decoder object for RPC bdev_raid_add_base_bdev 471 */ 472 static const struct spdk_json_object_decoder rpc_bdev_raid_add_base_bdev_decoders[] = { 473 {"base_bdev", offsetof(struct rpc_bdev_raid_add_base_bdev, base_bdev), spdk_json_decode_string}, 474 {"raid_bdev", offsetof(struct rpc_bdev_raid_add_base_bdev, raid_bdev), spdk_json_decode_string}, 475 }; 476 477 static void 478 rpc_bdev_raid_add_base_bdev_done(void *ctx, int status) 479 { 480 struct spdk_jsonrpc_request *request = ctx; 481 482 if (status != 0) { 483 spdk_jsonrpc_send_error_response_fmt(request, status, "Failed to add base bdev to RAID bdev: %s", 484 spdk_strerror(-status)); 485 return; 486 } 487 488 spdk_jsonrpc_send_bool_response(request, true); 489 } 490 491 static void 492 rpc_bdev_raid_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 493 { 494 } 495 496 /* 497 * brief: 498 * bdev_raid_add_base_bdev function is the RPC for adding base bdev to a raid bdev. 499 * It takes base bdev and raid bdev names as input. 500 * params: 501 * request - pointer to json rpc request 502 * params - pointer to request parameters 503 * returns: 504 * none 505 */ 506 static void 507 rpc_bdev_raid_add_base_bdev(struct spdk_jsonrpc_request *request, 508 const struct spdk_json_val *params) 509 { 510 struct rpc_bdev_raid_add_base_bdev req = {}; 511 struct raid_bdev *raid_bdev; 512 int rc; 513 514 if (spdk_json_decode_object(params, rpc_bdev_raid_add_base_bdev_decoders, 515 SPDK_COUNTOF(rpc_bdev_raid_add_base_bdev_decoders), 516 &req)) { 517 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 518 "spdk_json_decode_object failed"); 519 goto cleanup; 520 } 521 522 raid_bdev = raid_bdev_find_by_name(req.raid_bdev); 523 if (raid_bdev == NULL) { 524 spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, "raid bdev %s is not found in config", 525 req.raid_bdev); 526 goto cleanup; 527 } 528 529 rc = raid_bdev_add_base_bdev(raid_bdev, req.base_bdev, rpc_bdev_raid_add_base_bdev_done, request); 530 if (rc != 0) { 531 spdk_jsonrpc_send_error_response_fmt(request, rc, 532 "Failed to add base bdev %s to RAID bdev %s: %s", 533 req.base_bdev, req.raid_bdev, 534 spdk_strerror(-rc)); 535 goto cleanup; 536 } 537 538 cleanup: 539 free_rpc_bdev_raid_add_base_bdev(&req); 540 } 541 SPDK_RPC_REGISTER("bdev_raid_add_base_bdev", rpc_bdev_raid_add_base_bdev, SPDK_RPC_RUNTIME) 542 543 /* 544 * Decoder object for RPC bdev_raid_remove_base_bdev 545 */ 546 static const struct spdk_json_object_decoder rpc_bdev_raid_remove_base_bdev_decoders[] = { 547 {"name", 0, spdk_json_decode_string}, 548 }; 549 550 static void 551 rpc_bdev_raid_remove_base_bdev_done(void *ctx, int status) 552 { 553 struct spdk_jsonrpc_request *request = ctx; 554 555 if (status != 0) { 556 spdk_jsonrpc_send_error_response_fmt(request, status, "Failed to remove base bdev from raid bdev"); 557 return; 558 } 559 560 spdk_jsonrpc_send_bool_response(request, true); 561 } 562 563 /* 564 * brief: 565 * bdev_raid_remove_base_bdev function is the RPC for removing base bdev from a raid bdev. 566 * It takes base bdev name as input. 567 * params: 568 * request - pointer to json rpc request 569 * params - pointer to request parameters 570 * returns: 571 * none 572 */ 573 static void 574 rpc_bdev_raid_remove_base_bdev(struct spdk_jsonrpc_request *request, 575 const struct spdk_json_val *params) 576 { 577 struct spdk_bdev_desc *desc; 578 char *name = NULL; 579 int rc; 580 581 if (spdk_json_decode_object(params, rpc_bdev_raid_remove_base_bdev_decoders, 582 SPDK_COUNTOF(rpc_bdev_raid_remove_base_bdev_decoders), 583 &name)) { 584 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 585 "spdk_json_decode_object failed"); 586 return; 587 } 588 589 rc = spdk_bdev_open_ext(name, false, rpc_bdev_raid_event_cb, NULL, &desc); 590 free(name); 591 if (rc != 0) { 592 goto err; 593 } 594 595 rc = raid_bdev_remove_base_bdev(spdk_bdev_desc_get_bdev(desc), rpc_bdev_raid_remove_base_bdev_done, 596 request); 597 spdk_bdev_close(desc); 598 if (rc != 0) { 599 goto err; 600 } 601 602 return; 603 err: 604 rpc_bdev_raid_remove_base_bdev_done(request, rc); 605 } 606 SPDK_RPC_REGISTER("bdev_raid_remove_base_bdev", rpc_bdev_raid_remove_base_bdev, SPDK_RPC_RUNTIME) 607 608 static const struct spdk_json_object_decoder rpc_bdev_raid_options_decoders[] = { 609 {"process_window_size_kb", offsetof(struct spdk_raid_bdev_opts, process_window_size_kb), spdk_json_decode_uint32, true}, 610 {"process_max_bandwidth_mb_sec", offsetof(struct spdk_raid_bdev_opts, process_max_bandwidth_mb_sec), spdk_json_decode_uint32, true}, 611 }; 612 613 static void 614 rpc_bdev_raid_set_options(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 615 { 616 struct spdk_raid_bdev_opts opts; 617 int rc; 618 619 raid_bdev_get_opts(&opts); 620 if (params && spdk_json_decode_object(params, rpc_bdev_raid_options_decoders, 621 SPDK_COUNTOF(rpc_bdev_raid_options_decoders), 622 &opts)) { 623 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 624 "spdk_json_decode_object failed"); 625 return; 626 } 627 628 rc = raid_bdev_set_opts(&opts); 629 if (rc) { 630 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 631 } else { 632 spdk_jsonrpc_send_bool_response(request, true); 633 } 634 635 return; 636 } 637 SPDK_RPC_REGISTER("bdev_raid_set_options", rpc_bdev_raid_set_options, 638 SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME) 639