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 rc = raid_bdev_create(req->name, req->strip_size_kb, num_base_bdevs, 282 req->level, req->superblock_enabled, &req->uuid, &raid_bdev); 283 if (rc != 0) { 284 spdk_jsonrpc_send_error_response_fmt(request, rc, 285 "Failed to create RAID bdev %s: %s", 286 req->name, spdk_strerror(-rc)); 287 goto cleanup; 288 } 289 290 ctx->raid_bdev = raid_bdev; 291 ctx->request = request; 292 ctx->remaining = num_base_bdevs; 293 294 assert(num_base_bdevs > 0); 295 296 for (i = 0; i < num_base_bdevs; i++) { 297 const char *base_bdev_name = req->base_bdevs.base_bdevs[i]; 298 299 rc = raid_bdev_add_base_device(raid_bdev, base_bdev_name, i, 300 rpc_bdev_raid_create_add_base_bdev_cb, ctx); 301 if (rc == -ENODEV) { 302 SPDK_DEBUGLOG(bdev_raid, "base bdev %s doesn't exist now\n", base_bdev_name); 303 assert(ctx->remaining > 1 || i + 1 == num_base_bdevs); 304 rpc_bdev_raid_create_add_base_bdev_cb(ctx, 0); 305 } else if (rc != 0) { 306 SPDK_DEBUGLOG(bdev_raid, "Failed to add base bdev %s to RAID bdev %s: %s", 307 base_bdev_name, req->name, spdk_strerror(-rc)); 308 ctx->remaining -= (num_base_bdevs - i - 1); 309 rpc_bdev_raid_create_add_base_bdev_cb(ctx, rc); 310 break; 311 } 312 } 313 return; 314 cleanup: 315 free_rpc_bdev_raid_create_ctx(ctx); 316 } 317 SPDK_RPC_REGISTER("bdev_raid_create", rpc_bdev_raid_create, SPDK_RPC_RUNTIME) 318 319 /* 320 * Input structure for RPC deleting a raid bdev 321 */ 322 struct rpc_bdev_raid_delete { 323 /* raid bdev name */ 324 char *name; 325 }; 326 327 /* 328 * brief: 329 * free_rpc_bdev_raid_delete function is used to free RPC bdev_raid_delete related parameters 330 * params: 331 * req - pointer to RPC request 332 * params: 333 * none 334 */ 335 static void 336 free_rpc_bdev_raid_delete(struct rpc_bdev_raid_delete *req) 337 { 338 free(req->name); 339 } 340 341 /* 342 * Decoder object for RPC raid_bdev_delete 343 */ 344 static const struct spdk_json_object_decoder rpc_bdev_raid_delete_decoders[] = { 345 {"name", offsetof(struct rpc_bdev_raid_delete, name), spdk_json_decode_string}, 346 }; 347 348 struct rpc_bdev_raid_delete_ctx { 349 struct rpc_bdev_raid_delete req; 350 struct spdk_jsonrpc_request *request; 351 }; 352 353 /* 354 * brief: 355 * params: 356 * cb_arg - pointer to the callback context. 357 * rc - return code of the deletion of the raid bdev. 358 * returns: 359 * none 360 */ 361 static void 362 bdev_raid_delete_done(void *cb_arg, int rc) 363 { 364 struct rpc_bdev_raid_delete_ctx *ctx = cb_arg; 365 struct spdk_jsonrpc_request *request = ctx->request; 366 367 if (rc != 0) { 368 SPDK_ERRLOG("Failed to delete raid bdev %s (%d): %s\n", 369 ctx->req.name, rc, spdk_strerror(-rc)); 370 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 371 spdk_strerror(-rc)); 372 goto exit; 373 } 374 375 spdk_jsonrpc_send_bool_response(request, true); 376 exit: 377 free_rpc_bdev_raid_delete(&ctx->req); 378 free(ctx); 379 } 380 381 /* 382 * brief: 383 * rpc_bdev_raid_delete function is the RPC for deleting a raid bdev. It takes raid 384 * name as input and delete that raid bdev including freeing the base bdev 385 * resources. 386 * params: 387 * request - pointer to json rpc request 388 * params - pointer to request parameters 389 * returns: 390 * none 391 */ 392 static void 393 rpc_bdev_raid_delete(struct spdk_jsonrpc_request *request, 394 const struct spdk_json_val *params) 395 { 396 struct rpc_bdev_raid_delete_ctx *ctx; 397 struct raid_bdev *raid_bdev; 398 399 ctx = calloc(1, sizeof(*ctx)); 400 if (!ctx) { 401 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 402 return; 403 } 404 405 if (spdk_json_decode_object(params, rpc_bdev_raid_delete_decoders, 406 SPDK_COUNTOF(rpc_bdev_raid_delete_decoders), 407 &ctx->req)) { 408 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 409 "spdk_json_decode_object failed"); 410 goto cleanup; 411 } 412 413 raid_bdev = raid_bdev_find_by_name(ctx->req.name); 414 if (raid_bdev == NULL) { 415 spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, 416 "raid bdev %s not found", 417 ctx->req.name); 418 goto cleanup; 419 } 420 421 ctx->request = request; 422 423 raid_bdev_delete(raid_bdev, bdev_raid_delete_done, ctx); 424 425 return; 426 427 cleanup: 428 free_rpc_bdev_raid_delete(&ctx->req); 429 free(ctx); 430 } 431 SPDK_RPC_REGISTER("bdev_raid_delete", rpc_bdev_raid_delete, SPDK_RPC_RUNTIME) 432 433 /* 434 * Base bdevs in RPC bdev_raid_add_base_bdev 435 */ 436 struct rpc_bdev_raid_add_base_bdev { 437 /* Base bdev name */ 438 char *base_bdev; 439 440 /* Raid bdev name */ 441 char *raid_bdev; 442 }; 443 444 /* 445 * brief: 446 * free_rpc_bdev_raid_add_base_bdev function is to free RPC 447 * bdev_raid_add_base_bdev related parameters. 448 * params: 449 * req - pointer to RPC request 450 * returns: 451 * none 452 */ 453 static void 454 free_rpc_bdev_raid_add_base_bdev(struct rpc_bdev_raid_add_base_bdev *req) 455 { 456 free(req->base_bdev); 457 free(req->raid_bdev); 458 } 459 460 /* 461 * Decoder object for RPC bdev_raid_add_base_bdev 462 */ 463 static const struct spdk_json_object_decoder rpc_bdev_raid_add_base_bdev_decoders[] = { 464 {"base_bdev", offsetof(struct rpc_bdev_raid_add_base_bdev, base_bdev), spdk_json_decode_string}, 465 {"raid_bdev", offsetof(struct rpc_bdev_raid_add_base_bdev, raid_bdev), spdk_json_decode_string}, 466 }; 467 468 static void 469 rpc_bdev_raid_add_base_bdev_done(void *ctx, int status) 470 { 471 struct spdk_jsonrpc_request *request = ctx; 472 473 if (status != 0) { 474 spdk_jsonrpc_send_error_response_fmt(request, status, "Failed to add base bdev to RAID bdev: %s", 475 spdk_strerror(-status)); 476 return; 477 } 478 479 spdk_jsonrpc_send_bool_response(request, true); 480 } 481 482 static void 483 rpc_bdev_raid_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) 484 { 485 } 486 487 /* 488 * brief: 489 * bdev_raid_add_base_bdev function is the RPC for adding base bdev to a raid bdev. 490 * It takes base bdev and raid bdev names as input. 491 * params: 492 * request - pointer to json rpc request 493 * params - pointer to request parameters 494 * returns: 495 * none 496 */ 497 static void 498 rpc_bdev_raid_add_base_bdev(struct spdk_jsonrpc_request *request, 499 const struct spdk_json_val *params) 500 { 501 struct rpc_bdev_raid_add_base_bdev req = {}; 502 struct raid_bdev *raid_bdev; 503 struct spdk_bdev_desc *desc; 504 int rc; 505 506 if (spdk_json_decode_object(params, rpc_bdev_raid_add_base_bdev_decoders, 507 SPDK_COUNTOF(rpc_bdev_raid_add_base_bdev_decoders), 508 &req)) { 509 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 510 "spdk_json_decode_object failed"); 511 goto cleanup; 512 } 513 514 raid_bdev = raid_bdev_find_by_name(req.raid_bdev); 515 if (raid_bdev == NULL) { 516 spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, "raid bdev %s is not found in config", 517 req.raid_bdev); 518 goto cleanup; 519 } 520 521 rc = spdk_bdev_open_ext(req.base_bdev, false, rpc_bdev_raid_event_cb, NULL, &desc); 522 if (rc != 0) { 523 spdk_jsonrpc_send_error_response_fmt(request, rc, "Failed to open bdev %s: %s", 524 req.base_bdev, spdk_strerror(-rc)); 525 goto cleanup; 526 } 527 528 rc = raid_bdev_attach_base_bdev(raid_bdev, spdk_bdev_desc_get_bdev(desc), 529 rpc_bdev_raid_add_base_bdev_done, request); 530 spdk_bdev_close(desc); 531 if (rc != 0) { 532 spdk_jsonrpc_send_error_response_fmt(request, rc, 533 "Failed to attach base bdev %s to RAID bdev %s: %s", 534 req.base_bdev, req.raid_bdev, 535 spdk_strerror(-rc)); 536 goto cleanup; 537 } 538 539 cleanup: 540 free_rpc_bdev_raid_add_base_bdev(&req); 541 } 542 SPDK_RPC_REGISTER("bdev_raid_add_base_bdev", rpc_bdev_raid_add_base_bdev, SPDK_RPC_RUNTIME) 543 544 /* 545 * Decoder object for RPC bdev_raid_remove_base_bdev 546 */ 547 static const struct spdk_json_object_decoder rpc_bdev_raid_remove_base_bdev_decoders[] = { 548 {"name", 0, spdk_json_decode_string}, 549 }; 550 551 static void 552 rpc_bdev_raid_remove_base_bdev_done(void *ctx, int status) 553 { 554 struct spdk_jsonrpc_request *request = ctx; 555 556 if (status != 0) { 557 spdk_jsonrpc_send_error_response_fmt(request, status, "Failed to remove base bdev from raid bdev"); 558 return; 559 } 560 561 spdk_jsonrpc_send_bool_response(request, true); 562 } 563 564 /* 565 * brief: 566 * bdev_raid_remove_base_bdev function is the RPC for removing base bdev from a raid bdev. 567 * It takes base bdev name as input. 568 * params: 569 * request - pointer to json rpc request 570 * params - pointer to request parameters 571 * returns: 572 * none 573 */ 574 static void 575 rpc_bdev_raid_remove_base_bdev(struct spdk_jsonrpc_request *request, 576 const struct spdk_json_val *params) 577 { 578 struct spdk_bdev_desc *desc; 579 char *name = NULL; 580 int rc; 581 582 if (spdk_json_decode_object(params, rpc_bdev_raid_remove_base_bdev_decoders, 583 SPDK_COUNTOF(rpc_bdev_raid_remove_base_bdev_decoders), 584 &name)) { 585 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 586 "spdk_json_decode_object failed"); 587 return; 588 } 589 590 rc = spdk_bdev_open_ext(name, false, rpc_bdev_raid_event_cb, NULL, &desc); 591 free(name); 592 if (rc != 0) { 593 goto err; 594 } 595 596 rc = raid_bdev_remove_base_bdev(spdk_bdev_desc_get_bdev(desc), rpc_bdev_raid_remove_base_bdev_done, 597 request); 598 spdk_bdev_close(desc); 599 if (rc != 0) { 600 goto err; 601 } 602 603 return; 604 err: 605 rpc_bdev_raid_remove_base_bdev_done(request, rc); 606 } 607 SPDK_RPC_REGISTER("bdev_raid_remove_base_bdev", rpc_bdev_raid_remove_base_bdev, SPDK_RPC_RUNTIME) 608 609 static const struct spdk_json_object_decoder rpc_bdev_raid_options_decoders[] = { 610 {"process_window_size_kb", offsetof(struct spdk_raid_bdev_opts, process_window_size_kb), 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