1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 3 * Copyright (C) 2016 Intel Corporation. 4 * All rights reserved. 5 */ 6 7 #include "iscsi/iscsi.h" 8 #include "iscsi/conn.h" 9 #include "iscsi/tgt_node.h" 10 #include "iscsi/portal_grp.h" 11 #include "iscsi/init_grp.h" 12 13 #include "spdk/rpc.h" 14 #include "spdk/util.h" 15 #include "spdk/string.h" 16 #include "spdk/log.h" 17 #include "spdk/base64.h" 18 #include "spdk/histogram_data.h" 19 20 static void 21 rpc_iscsi_get_initiator_groups(struct spdk_jsonrpc_request *request, 22 const struct spdk_json_val *params) 23 { 24 struct spdk_json_write_ctx *w; 25 26 if (params != NULL) { 27 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 28 "iscsi_get_initiator_groups requires no parameters"); 29 return; 30 } 31 32 w = spdk_jsonrpc_begin_result(request); 33 spdk_json_write_array_begin(w); 34 iscsi_init_grps_info_json(w); 35 spdk_json_write_array_end(w); 36 37 spdk_jsonrpc_end_result(request, w); 38 } 39 SPDK_RPC_REGISTER("iscsi_get_initiator_groups", rpc_iscsi_get_initiator_groups, 40 SPDK_RPC_RUNTIME) 41 42 struct rpc_initiator_list { 43 size_t num_initiators; 44 char *initiators[MAX_INITIATOR]; 45 }; 46 47 static int 48 decode_rpc_initiator_list(const struct spdk_json_val *val, void *out) 49 { 50 struct rpc_initiator_list *list = out; 51 52 return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR, 53 &list->num_initiators, sizeof(char *)); 54 } 55 56 static void 57 free_rpc_initiator_list(struct rpc_initiator_list *list) 58 { 59 size_t i; 60 61 for (i = 0; i < list->num_initiators; i++) { 62 free(list->initiators[i]); 63 } 64 } 65 66 struct rpc_netmask_list { 67 size_t num_netmasks; 68 char *netmasks[MAX_NETMASK]; 69 }; 70 71 static int 72 decode_rpc_netmask_list(const struct spdk_json_val *val, void *out) 73 { 74 struct rpc_netmask_list *list = out; 75 76 return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK, 77 &list->num_netmasks, sizeof(char *)); 78 } 79 80 static void 81 free_rpc_netmask_list(struct rpc_netmask_list *list) 82 { 83 size_t i; 84 85 for (i = 0; i < list->num_netmasks; i++) { 86 free(list->netmasks[i]); 87 } 88 } 89 90 struct rpc_initiator_group { 91 int32_t tag; 92 struct rpc_initiator_list initiator_list; 93 struct rpc_netmask_list netmask_list; 94 }; 95 96 static void 97 free_rpc_initiator_group(struct rpc_initiator_group *ig) 98 { 99 free_rpc_initiator_list(&ig->initiator_list); 100 free_rpc_netmask_list(&ig->netmask_list); 101 } 102 103 static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = { 104 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 105 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list}, 106 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list}, 107 }; 108 109 static void 110 rpc_iscsi_create_initiator_group(struct spdk_jsonrpc_request *request, 111 const struct spdk_json_val *params) 112 { 113 struct rpc_initiator_group req = {}; 114 115 if (spdk_json_decode_object(params, rpc_initiator_group_decoders, 116 SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) { 117 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 118 goto invalid; 119 } 120 121 if (req.initiator_list.num_initiators == 0 || 122 req.netmask_list.num_netmasks == 0) { 123 goto invalid; 124 } 125 126 if (iscsi_init_grp_create_from_initiator_list(req.tag, 127 req.initiator_list.num_initiators, 128 req.initiator_list.initiators, 129 req.netmask_list.num_netmasks, 130 req.netmask_list.netmasks)) { 131 SPDK_ERRLOG("create_from_initiator_list failed\n"); 132 goto invalid; 133 } 134 135 free_rpc_initiator_group(&req); 136 137 spdk_jsonrpc_send_bool_response(request, true); 138 return; 139 140 invalid: 141 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 142 free_rpc_initiator_group(&req); 143 } 144 SPDK_RPC_REGISTER("iscsi_create_initiator_group", rpc_iscsi_create_initiator_group, 145 SPDK_RPC_RUNTIME) 146 147 static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = { 148 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 149 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true}, 150 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true}, 151 }; 152 153 static void 154 rpc_iscsi_initiator_group_add_initiators(struct spdk_jsonrpc_request *request, 155 const struct spdk_json_val *params) 156 { 157 struct rpc_initiator_group req = {}; 158 159 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 160 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 161 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 162 goto invalid; 163 } 164 165 if (iscsi_init_grp_add_initiators_from_initiator_list(req.tag, 166 req.initiator_list.num_initiators, 167 req.initiator_list.initiators, 168 req.netmask_list.num_netmasks, 169 req.netmask_list.netmasks)) { 170 SPDK_ERRLOG("add_initiators_from_initiator_list failed\n"); 171 goto invalid; 172 } 173 174 free_rpc_initiator_group(&req); 175 176 spdk_jsonrpc_send_bool_response(request, true); 177 return; 178 179 invalid: 180 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 181 free_rpc_initiator_group(&req); 182 } 183 SPDK_RPC_REGISTER("iscsi_initiator_group_add_initiators", 184 rpc_iscsi_initiator_group_add_initiators, SPDK_RPC_RUNTIME) 185 186 static void 187 rpc_iscsi_initiator_group_remove_initiators(struct spdk_jsonrpc_request *request, 188 const struct spdk_json_val *params) 189 { 190 struct rpc_initiator_group req = {}; 191 192 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 193 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 194 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 195 goto invalid; 196 } 197 198 if (iscsi_init_grp_delete_initiators_from_initiator_list(req.tag, 199 req.initiator_list.num_initiators, 200 req.initiator_list.initiators, 201 req.netmask_list.num_netmasks, 202 req.netmask_list.netmasks)) { 203 SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n"); 204 goto invalid; 205 } 206 207 free_rpc_initiator_group(&req); 208 209 spdk_jsonrpc_send_bool_response(request, true); 210 return; 211 212 invalid: 213 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 214 free_rpc_initiator_group(&req); 215 } 216 SPDK_RPC_REGISTER("iscsi_initiator_group_remove_initiators", 217 rpc_iscsi_initiator_group_remove_initiators, SPDK_RPC_RUNTIME) 218 219 struct rpc_iscsi_delete_initiator_group { 220 int32_t tag; 221 }; 222 223 static const struct spdk_json_object_decoder rpc_iscsi_delete_initiator_group_decoders[] = { 224 {"tag", offsetof(struct rpc_iscsi_delete_initiator_group, tag), spdk_json_decode_int32}, 225 }; 226 227 static void 228 rpc_iscsi_delete_initiator_group(struct spdk_jsonrpc_request *request, 229 const struct spdk_json_val *params) 230 { 231 struct rpc_iscsi_delete_initiator_group req = {}; 232 struct spdk_iscsi_init_grp *ig; 233 234 if (spdk_json_decode_object(params, rpc_iscsi_delete_initiator_group_decoders, 235 SPDK_COUNTOF(rpc_iscsi_delete_initiator_group_decoders), 236 &req)) { 237 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 238 goto invalid; 239 } 240 241 ig = iscsi_init_grp_unregister(req.tag); 242 if (!ig) { 243 goto invalid; 244 } 245 iscsi_tgt_node_delete_map(NULL, ig); 246 iscsi_init_grp_destroy(ig); 247 248 spdk_jsonrpc_send_bool_response(request, true); 249 return; 250 251 invalid: 252 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 253 } 254 SPDK_RPC_REGISTER("iscsi_delete_initiator_group", rpc_iscsi_delete_initiator_group, 255 SPDK_RPC_RUNTIME) 256 257 static void 258 rpc_iscsi_get_target_nodes(struct spdk_jsonrpc_request *request, 259 const struct spdk_json_val *params) 260 { 261 struct spdk_json_write_ctx *w; 262 263 if (params != NULL) { 264 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 265 "iscsi_get_target_nodes requires no parameters"); 266 return; 267 } 268 269 w = spdk_jsonrpc_begin_result(request); 270 spdk_json_write_array_begin(w); 271 iscsi_tgt_nodes_info_json(w); 272 spdk_json_write_array_end(w); 273 274 spdk_jsonrpc_end_result(request, w); 275 } 276 SPDK_RPC_REGISTER("iscsi_get_target_nodes", rpc_iscsi_get_target_nodes, SPDK_RPC_RUNTIME) 277 278 struct rpc_pg_ig_map { 279 int32_t pg_tag; 280 int32_t ig_tag; 281 }; 282 283 static const struct spdk_json_object_decoder rpc_pg_ig_map_decoders[] = { 284 {"pg_tag", offsetof(struct rpc_pg_ig_map, pg_tag), spdk_json_decode_int32}, 285 {"ig_tag", offsetof(struct rpc_pg_ig_map, ig_tag), spdk_json_decode_int32}, 286 }; 287 288 static int 289 decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out) 290 { 291 struct rpc_pg_ig_map *pg_ig_map = out; 292 293 return spdk_json_decode_object(val, rpc_pg_ig_map_decoders, 294 SPDK_COUNTOF(rpc_pg_ig_map_decoders), 295 pg_ig_map); 296 } 297 298 struct rpc_pg_ig_maps { 299 size_t num_maps; 300 struct rpc_pg_ig_map maps[MAX_TARGET_MAP]; 301 }; 302 303 static int 304 decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out) 305 { 306 struct rpc_pg_ig_maps *pg_ig_maps = out; 307 308 return spdk_json_decode_array(val, decode_rpc_pg_ig_map, pg_ig_maps->maps, 309 MAX_TARGET_MAP, &pg_ig_maps->num_maps, 310 sizeof(struct rpc_pg_ig_map)); 311 } 312 313 #define RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN 64 314 315 struct rpc_lun { 316 char *bdev_name; 317 int32_t lun_id; 318 }; 319 320 static const struct spdk_json_object_decoder rpc_lun_decoders[] = { 321 {"bdev_name", offsetof(struct rpc_lun, bdev_name), spdk_json_decode_string}, 322 {"lun_id", offsetof(struct rpc_lun, lun_id), spdk_json_decode_int32}, 323 }; 324 325 static int 326 decode_rpc_lun(const struct spdk_json_val *val, void *out) 327 { 328 struct rpc_lun *lun = out; 329 330 return spdk_json_decode_object(val, rpc_lun_decoders, 331 SPDK_COUNTOF(rpc_lun_decoders), lun); 332 } 333 334 struct rpc_luns { 335 size_t num_luns; 336 struct rpc_lun luns[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN]; 337 }; 338 339 static int 340 decode_rpc_luns(const struct spdk_json_val *val, void *out) 341 { 342 struct rpc_luns *luns = out; 343 344 return spdk_json_decode_array(val, decode_rpc_lun, luns->luns, 345 RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN, 346 &luns->num_luns, sizeof(struct rpc_lun)); 347 } 348 349 static void 350 free_rpc_luns(struct rpc_luns *p) 351 { 352 size_t i; 353 354 for (i = 0; i < p->num_luns; i++) { 355 free(p->luns[i].bdev_name); 356 } 357 } 358 359 struct rpc_target_node { 360 char *name; 361 char *alias_name; 362 363 struct rpc_pg_ig_maps pg_ig_maps; 364 struct rpc_luns luns; 365 366 int32_t queue_depth; 367 bool disable_chap; 368 bool require_chap; 369 bool mutual_chap; 370 int32_t chap_group; 371 372 bool header_digest; 373 bool data_digest; 374 }; 375 376 static void 377 free_rpc_target_node(struct rpc_target_node *req) 378 { 379 free(req->name); 380 free(req->alias_name); 381 free_rpc_luns(&req->luns); 382 } 383 384 static const struct spdk_json_object_decoder rpc_target_node_decoders[] = { 385 {"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string}, 386 {"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string}, 387 {"pg_ig_maps", offsetof(struct rpc_target_node, pg_ig_maps), decode_rpc_pg_ig_maps}, 388 {"luns", offsetof(struct rpc_target_node, luns), decode_rpc_luns}, 389 {"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32}, 390 {"disable_chap", offsetof(struct rpc_target_node, disable_chap), spdk_json_decode_bool, true}, 391 {"require_chap", offsetof(struct rpc_target_node, require_chap), spdk_json_decode_bool, true}, 392 {"mutual_chap", offsetof(struct rpc_target_node, mutual_chap), spdk_json_decode_bool, true}, 393 {"chap_group", offsetof(struct rpc_target_node, chap_group), spdk_json_decode_int32, true}, 394 {"header_digest", offsetof(struct rpc_target_node, header_digest), spdk_json_decode_bool, true}, 395 {"data_digest", offsetof(struct rpc_target_node, data_digest), spdk_json_decode_bool, true}, 396 }; 397 398 static void 399 rpc_iscsi_create_target_node(struct spdk_jsonrpc_request *request, 400 const struct spdk_json_val *params) 401 { 402 struct rpc_target_node req = {}; 403 struct spdk_iscsi_tgt_node *target; 404 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 405 char *bdev_names[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0}; 406 int32_t lun_ids[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0}; 407 size_t i; 408 409 if (spdk_json_decode_object(params, rpc_target_node_decoders, 410 SPDK_COUNTOF(rpc_target_node_decoders), 411 &req)) { 412 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 413 goto invalid; 414 } 415 416 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 417 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 418 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 419 } 420 421 for (i = 0; i < req.luns.num_luns; i++) { 422 bdev_names[i] = req.luns.luns[i].bdev_name; 423 lun_ids[i] = req.luns.luns[i].lun_id; 424 } 425 426 /* 427 * Use default parameters in a few places: 428 * index = -1 : automatically pick an index for the new target node 429 * alias = NULL 430 */ 431 target = iscsi_tgt_node_construct(-1, req.name, req.alias_name, 432 pg_tags, 433 ig_tags, 434 req.pg_ig_maps.num_maps, 435 (const char **)bdev_names, 436 lun_ids, 437 req.luns.num_luns, 438 req.queue_depth, 439 req.disable_chap, 440 req.require_chap, 441 req.mutual_chap, 442 req.chap_group, 443 req.header_digest, 444 req.data_digest); 445 446 if (target == NULL) { 447 goto invalid; 448 } 449 450 free_rpc_target_node(&req); 451 452 spdk_jsonrpc_send_bool_response(request, true); 453 return; 454 455 invalid: 456 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 457 free_rpc_target_node(&req); 458 } 459 SPDK_RPC_REGISTER("iscsi_create_target_node", rpc_iscsi_create_target_node, SPDK_RPC_RUNTIME) 460 461 struct rpc_tgt_node_pg_ig_maps { 462 char *name; 463 struct rpc_pg_ig_maps pg_ig_maps; 464 }; 465 466 static const struct spdk_json_object_decoder rpc_tgt_node_pg_ig_maps_decoders[] = { 467 {"name", offsetof(struct rpc_tgt_node_pg_ig_maps, name), spdk_json_decode_string}, 468 {"pg_ig_maps", offsetof(struct rpc_tgt_node_pg_ig_maps, pg_ig_maps), decode_rpc_pg_ig_maps}, 469 }; 470 471 static void 472 rpc_iscsi_target_node_add_pg_ig_maps(struct spdk_jsonrpc_request *request, 473 const struct spdk_json_val *params) 474 { 475 struct rpc_tgt_node_pg_ig_maps req = {}; 476 struct spdk_iscsi_tgt_node *target; 477 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 478 size_t i; 479 int rc; 480 481 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 482 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 483 &req)) { 484 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 485 goto invalid; 486 } 487 488 target = iscsi_find_tgt_node(req.name); 489 if (target == NULL) { 490 SPDK_ERRLOG("target is not found\n"); 491 goto invalid; 492 } 493 494 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 495 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 496 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 497 } 498 499 rc = iscsi_target_node_add_pg_ig_maps(target, pg_tags, ig_tags, 500 req.pg_ig_maps.num_maps); 501 if (rc < 0) { 502 SPDK_ERRLOG("add pg-ig maps failed\n"); 503 goto invalid; 504 } 505 506 free(req.name); 507 508 spdk_jsonrpc_send_bool_response(request, true); 509 return; 510 511 invalid: 512 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 513 "Invalid parameters"); 514 free(req.name); 515 } 516 SPDK_RPC_REGISTER("iscsi_target_node_add_pg_ig_maps", 517 rpc_iscsi_target_node_add_pg_ig_maps, SPDK_RPC_RUNTIME) 518 519 static void 520 rpc_iscsi_target_node_remove_pg_ig_maps(struct spdk_jsonrpc_request *request, 521 const struct spdk_json_val *params) 522 { 523 struct rpc_tgt_node_pg_ig_maps req = {}; 524 struct spdk_iscsi_tgt_node *target; 525 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 526 size_t i; 527 int rc; 528 529 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 530 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 531 &req)) { 532 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 533 goto invalid; 534 } 535 536 target = iscsi_find_tgt_node(req.name); 537 if (target == NULL) { 538 SPDK_ERRLOG("target is not found\n"); 539 goto invalid; 540 } 541 542 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 543 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 544 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 545 } 546 547 rc = iscsi_target_node_remove_pg_ig_maps(target, pg_tags, ig_tags, 548 req.pg_ig_maps.num_maps); 549 if (rc < 0) { 550 SPDK_ERRLOG("remove pg-ig maps failed\n"); 551 goto invalid; 552 } 553 554 free(req.name); 555 556 spdk_jsonrpc_send_bool_response(request, true); 557 return; 558 559 invalid: 560 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 561 "Invalid parameters"); 562 free(req.name); 563 } 564 SPDK_RPC_REGISTER("iscsi_target_node_remove_pg_ig_maps", 565 rpc_iscsi_target_node_remove_pg_ig_maps, SPDK_RPC_RUNTIME) 566 567 struct rpc_iscsi_delete_target_node { 568 char *name; 569 }; 570 571 static void 572 free_rpc_iscsi_delete_target_node(struct rpc_iscsi_delete_target_node *r) 573 { 574 free(r->name); 575 } 576 577 static const struct spdk_json_object_decoder rpc_iscsi_delete_target_node_decoders[] = { 578 {"name", offsetof(struct rpc_iscsi_delete_target_node, name), spdk_json_decode_string}, 579 }; 580 581 struct rpc_iscsi_delete_target_node_ctx { 582 struct rpc_iscsi_delete_target_node req; 583 struct spdk_jsonrpc_request *request; 584 }; 585 586 static void 587 rpc_iscsi_delete_target_node_done(void *cb_arg, int rc) 588 { 589 struct rpc_iscsi_delete_target_node_ctx *ctx = cb_arg; 590 591 free_rpc_iscsi_delete_target_node(&ctx->req); 592 if (rc == 0) { 593 spdk_jsonrpc_send_bool_response(ctx->request, true); 594 } else { 595 spdk_jsonrpc_send_error_response(ctx->request, rc, spdk_strerror(-rc)); 596 } 597 free(ctx); 598 } 599 600 static void 601 rpc_iscsi_delete_target_node(struct spdk_jsonrpc_request *request, 602 const struct spdk_json_val *params) 603 { 604 struct rpc_iscsi_delete_target_node_ctx *ctx; 605 606 ctx = calloc(1, sizeof(*ctx)); 607 if (!ctx) { 608 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 609 spdk_strerror(ENOMEM)); 610 return; 611 } 612 613 if (spdk_json_decode_object(params, rpc_iscsi_delete_target_node_decoders, 614 SPDK_COUNTOF(rpc_iscsi_delete_target_node_decoders), 615 &ctx->req)) { 616 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 617 goto invalid; 618 } 619 620 if (ctx->req.name == NULL) { 621 SPDK_ERRLOG("missing name param\n"); 622 goto invalid; 623 } 624 625 ctx->request = request; 626 627 iscsi_shutdown_tgt_node_by_name(ctx->req.name, 628 rpc_iscsi_delete_target_node_done, ctx); 629 return; 630 631 invalid: 632 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 633 free_rpc_iscsi_delete_target_node(&ctx->req); 634 free(ctx); 635 } 636 SPDK_RPC_REGISTER("iscsi_delete_target_node", rpc_iscsi_delete_target_node, SPDK_RPC_RUNTIME) 637 638 static void 639 rpc_iscsi_get_portal_groups(struct spdk_jsonrpc_request *request, 640 const struct spdk_json_val *params) 641 { 642 struct spdk_json_write_ctx *w; 643 644 if (params != NULL) { 645 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 646 "iscsi_get_portal_groups requires no parameters"); 647 return; 648 } 649 650 w = spdk_jsonrpc_begin_result(request); 651 spdk_json_write_array_begin(w); 652 iscsi_portal_grps_info_json(w); 653 spdk_json_write_array_end(w); 654 655 spdk_jsonrpc_end_result(request, w); 656 } 657 SPDK_RPC_REGISTER("iscsi_get_portal_groups", rpc_iscsi_get_portal_groups, SPDK_RPC_RUNTIME) 658 659 struct rpc_portal { 660 char *host; 661 char *port; 662 }; 663 664 struct rpc_portal_list { 665 size_t num_portals; 666 struct rpc_portal portals[MAX_PORTAL]; 667 }; 668 669 struct rpc_portal_group { 670 int32_t tag; 671 struct rpc_portal_list portal_list; 672 bool is_private; 673 bool wait; 674 }; 675 676 static void 677 free_rpc_portal(struct rpc_portal *portal) 678 { 679 free(portal->host); 680 free(portal->port); 681 } 682 683 static void 684 free_rpc_portal_list(struct rpc_portal_list *pl) 685 { 686 size_t i; 687 688 for (i = 0; i < pl->num_portals; i++) { 689 free_rpc_portal(&pl->portals[i]); 690 } 691 pl->num_portals = 0; 692 } 693 694 static void 695 free_rpc_portal_group(struct rpc_portal_group *pg) 696 { 697 free_rpc_portal_list(&pg->portal_list); 698 } 699 700 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 701 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 702 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 703 }; 704 705 static int 706 decode_rpc_portal(const struct spdk_json_val *val, void *out) 707 { 708 struct rpc_portal *portal = out; 709 710 return spdk_json_decode_object(val, rpc_portal_decoders, 711 SPDK_COUNTOF(rpc_portal_decoders), 712 portal); 713 } 714 715 static int 716 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 717 { 718 struct rpc_portal_list *list = out; 719 720 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 721 sizeof(struct rpc_portal)); 722 } 723 724 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 725 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 726 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 727 {"private", offsetof(struct rpc_portal_group, is_private), spdk_json_decode_bool, true}, 728 {"wait", offsetof(struct rpc_portal_group, wait), spdk_json_decode_bool, true}, 729 }; 730 731 static void 732 rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request, 733 const struct spdk_json_val *params) 734 { 735 struct rpc_portal_group req = {}; 736 struct spdk_iscsi_portal_grp *pg = NULL; 737 struct spdk_iscsi_portal *portal; 738 size_t i = 0; 739 int rc = -1; 740 741 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 742 SPDK_COUNTOF(rpc_portal_group_decoders), 743 &req)) { 744 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 745 goto out; 746 } 747 748 pg = iscsi_portal_grp_create(req.tag, req.is_private); 749 if (pg == NULL) { 750 SPDK_ERRLOG("portal_grp_create failed\n"); 751 goto out; 752 } 753 for (i = 0; i < req.portal_list.num_portals; i++) { 754 portal = iscsi_portal_create(req.portal_list.portals[i].host, 755 req.portal_list.portals[i].port); 756 if (portal == NULL) { 757 SPDK_ERRLOG("portal_create failed\n"); 758 goto out; 759 } 760 iscsi_portal_grp_add_portal(pg, portal); 761 } 762 763 rc = iscsi_portal_grp_open(pg, req.wait); 764 if (rc != 0) { 765 SPDK_ERRLOG("portal_grp_open failed\n"); 766 goto out; 767 } 768 769 rc = iscsi_portal_grp_register(pg); 770 if (rc != 0) { 771 SPDK_ERRLOG("portal_grp_register failed\n"); 772 } 773 774 out: 775 if (rc == 0) { 776 spdk_jsonrpc_send_bool_response(request, true); 777 } else { 778 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 779 780 if (pg != NULL) { 781 iscsi_portal_grp_release(pg); 782 } 783 } 784 free_rpc_portal_group(&req); 785 } 786 SPDK_RPC_REGISTER("iscsi_create_portal_group", rpc_iscsi_create_portal_group, SPDK_RPC_RUNTIME) 787 788 struct rpc_iscsi_change_portal_group { 789 int32_t tag; 790 }; 791 792 static const struct spdk_json_object_decoder rpc_iscsi_change_portal_group_decoders[] = { 793 {"tag", offsetof(struct rpc_iscsi_change_portal_group, tag), spdk_json_decode_int32}, 794 }; 795 796 typedef int (*iscsi_change_portal_grp_fn)(int pg_tag); 797 798 static void 799 _rpc_iscsi_change_portal_group(struct spdk_jsonrpc_request *request, 800 const struct spdk_json_val *params, 801 iscsi_change_portal_grp_fn fn) 802 { 803 struct rpc_iscsi_change_portal_group req = {}; 804 int rc; 805 806 if (spdk_json_decode_object(params, rpc_iscsi_change_portal_group_decoders, 807 SPDK_COUNTOF(rpc_iscsi_change_portal_group_decoders), 808 &req)) { 809 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 810 goto invalid; 811 } 812 813 rc = fn(req.tag); 814 if (rc != 0) { 815 goto invalid; 816 } 817 818 spdk_jsonrpc_send_bool_response(request, true); 819 return; 820 821 invalid: 822 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 823 } 824 825 static int 826 _rpc_iscsi_delete_portal_group(int pg_tag) 827 { 828 struct spdk_iscsi_portal_grp *pg; 829 830 pg = iscsi_portal_grp_unregister(pg_tag); 831 if (!pg) { 832 return -ENODEV; 833 } 834 835 iscsi_tgt_node_delete_map(pg, NULL); 836 iscsi_portal_grp_release(pg); 837 return 0; 838 } 839 840 static void 841 rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request *request, 842 const struct spdk_json_val *params) 843 { 844 _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_delete_portal_group); 845 } 846 SPDK_RPC_REGISTER("iscsi_delete_portal_group", rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME) 847 848 static int 849 _rpc_iscsi_start_portal_group(int pg_tag) 850 { 851 struct spdk_iscsi_portal_grp *pg; 852 853 pg = iscsi_portal_grp_find_by_tag(pg_tag); 854 if (!pg) { 855 return -ENODEV; 856 } 857 858 iscsi_portal_grp_resume(pg); 859 return 0; 860 } 861 862 static void 863 rpc_iscsi_start_portal_group(struct spdk_jsonrpc_request *request, 864 const struct spdk_json_val *params) 865 { 866 _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_start_portal_group); 867 } 868 SPDK_RPC_REGISTER("iscsi_start_portal_group", rpc_iscsi_start_portal_group, SPDK_RPC_RUNTIME) 869 870 struct rpc_portal_group_auth { 871 int32_t tag; 872 bool disable_chap; 873 bool require_chap; 874 bool mutual_chap; 875 int32_t chap_group; 876 }; 877 878 static const struct spdk_json_object_decoder rpc_portal_group_auth_decoders[] = { 879 {"tag", offsetof(struct rpc_portal_group_auth, tag), spdk_json_decode_int32}, 880 {"disable_chap", offsetof(struct rpc_portal_group_auth, disable_chap), spdk_json_decode_bool, true}, 881 {"require_chap", offsetof(struct rpc_portal_group_auth, require_chap), spdk_json_decode_bool, true}, 882 {"mutual_chap", offsetof(struct rpc_portal_group_auth, mutual_chap), spdk_json_decode_bool, true}, 883 {"chap_group", offsetof(struct rpc_portal_group_auth, chap_group), spdk_json_decode_int32, true}, 884 }; 885 886 static void 887 rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request, 888 const struct spdk_json_val *params) 889 { 890 struct rpc_portal_group_auth req = {}; 891 struct spdk_iscsi_portal_grp *pg; 892 int rc; 893 894 if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders, 895 SPDK_COUNTOF(rpc_portal_group_auth_decoders), &req)) { 896 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 897 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 898 "Invalid parameters"); 899 return; 900 } 901 902 pthread_mutex_lock(&g_iscsi.mutex); 903 904 pg = iscsi_portal_grp_find_by_tag(req.tag); 905 if (pg == NULL) { 906 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 907 "Could not find portal group %d", req.tag); 908 goto exit; 909 } 910 911 rc = iscsi_portal_grp_set_chap_params(pg, req.disable_chap, req.require_chap, 912 req.mutual_chap, req.chap_group); 913 if (rc < 0) { 914 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 915 "Invalid combination of auth params"); 916 goto exit; 917 } 918 919 pthread_mutex_unlock(&g_iscsi.mutex); 920 921 spdk_jsonrpc_send_bool_response(request, true); 922 return; 923 924 exit: 925 pthread_mutex_unlock(&g_iscsi.mutex); 926 } 927 SPDK_RPC_REGISTER("iscsi_portal_group_set_auth", rpc_iscsi_portal_group_set_auth, 928 SPDK_RPC_RUNTIME) 929 930 struct rpc_iscsi_get_connections_ctx { 931 struct spdk_jsonrpc_request *request; 932 struct spdk_json_write_ctx *w; 933 }; 934 935 static void 936 _rpc_iscsi_get_connections_done(struct spdk_io_channel_iter *i, int status) 937 { 938 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 939 940 spdk_json_write_array_end(ctx->w); 941 spdk_jsonrpc_end_result(ctx->request, ctx->w); 942 943 free(ctx); 944 } 945 946 static void 947 _rpc_iscsi_get_connections(struct spdk_io_channel_iter *i) 948 { 949 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 950 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 951 struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch); 952 struct spdk_iscsi_conn *conn; 953 954 STAILQ_FOREACH(conn, &pg->connections, pg_link) { 955 iscsi_conn_info_json(ctx->w, conn); 956 } 957 958 spdk_for_each_channel_continue(i, 0); 959 } 960 961 static void 962 rpc_iscsi_get_connections(struct spdk_jsonrpc_request *request, 963 const struct spdk_json_val *params) 964 { 965 struct rpc_iscsi_get_connections_ctx *ctx; 966 967 if (params != NULL) { 968 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 969 "iscsi_get_connections requires no parameters"); 970 return; 971 } 972 973 ctx = calloc(1, sizeof(struct rpc_iscsi_get_connections_ctx)); 974 if (ctx == NULL) { 975 SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n"); 976 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 977 return; 978 } 979 980 ctx->request = request; 981 ctx->w = spdk_jsonrpc_begin_result(request); 982 983 spdk_json_write_array_begin(ctx->w); 984 985 spdk_for_each_channel(&g_iscsi, 986 _rpc_iscsi_get_connections, 987 ctx, 988 _rpc_iscsi_get_connections_done); 989 } 990 SPDK_RPC_REGISTER("iscsi_get_connections", rpc_iscsi_get_connections, SPDK_RPC_RUNTIME) 991 992 struct rpc_target_lun { 993 char *name; 994 char *bdev_name; 995 int32_t lun_id; 996 }; 997 998 struct rpc_iscsi_get_stats_ctx { 999 struct spdk_jsonrpc_request *request; 1000 uint32_t invalid; 1001 uint32_t running; 1002 uint32_t exiting; 1003 uint32_t exited; 1004 }; 1005 1006 static void 1007 _rpc_iscsi_get_stats_done(struct spdk_io_channel_iter *i, int status) 1008 { 1009 struct spdk_json_write_ctx *w; 1010 struct rpc_iscsi_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1011 1012 w = spdk_jsonrpc_begin_result(ctx->request); 1013 spdk_json_write_object_begin(w); 1014 1015 spdk_json_write_named_uint32(w, "invalid", ctx->invalid); 1016 spdk_json_write_named_uint32(w, "running", ctx->running); 1017 spdk_json_write_named_uint32(w, "exiting", ctx->exiting); 1018 spdk_json_write_named_uint32(w, "exited", ctx->exited); 1019 1020 spdk_json_write_object_end(w); 1021 spdk_jsonrpc_end_result(ctx->request, w); 1022 1023 free(ctx); 1024 } 1025 1026 static void 1027 _iscsi_get_stats(struct rpc_iscsi_get_stats_ctx *ctx, 1028 struct spdk_iscsi_conn *conn) 1029 { 1030 switch (conn->state) { 1031 case ISCSI_CONN_STATE_INVALID: 1032 ctx->invalid += 1; 1033 break; 1034 case ISCSI_CONN_STATE_RUNNING: 1035 ctx->running += 1; 1036 break; 1037 case ISCSI_CONN_STATE_EXITING: 1038 ctx->exiting += 1; 1039 break; 1040 case ISCSI_CONN_STATE_EXITED: 1041 ctx->exited += 1; 1042 break; 1043 } 1044 } 1045 1046 static void 1047 _rpc_iscsi_get_stats(struct spdk_io_channel_iter *i) 1048 { 1049 struct rpc_iscsi_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 1050 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 1051 struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch); 1052 struct spdk_iscsi_conn *conn; 1053 1054 STAILQ_FOREACH(conn, &pg->connections, pg_link) { 1055 _iscsi_get_stats(ctx, conn); 1056 } 1057 1058 spdk_for_each_channel_continue(i, 0); 1059 } 1060 1061 1062 1063 static void 1064 rpc_iscsi_get_stats(struct spdk_jsonrpc_request *request, 1065 const struct spdk_json_val *params) 1066 { 1067 struct rpc_iscsi_get_stats_ctx *ctx; 1068 1069 if (params != NULL) { 1070 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1071 "iscsi_get_stats requires no parameters"); 1072 return; 1073 } 1074 1075 ctx = calloc(1, sizeof(struct rpc_iscsi_get_stats_ctx)); 1076 if (ctx == NULL) { 1077 SPDK_ERRLOG("Failed to allocate rpc_iscsi_get_stats_ctx struct\n"); 1078 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1079 return; 1080 } 1081 1082 ctx->request = request; 1083 1084 spdk_for_each_channel(&g_iscsi, 1085 _rpc_iscsi_get_stats, 1086 ctx, 1087 _rpc_iscsi_get_stats_done); 1088 1089 } 1090 SPDK_RPC_REGISTER("iscsi_get_stats", rpc_iscsi_get_stats, SPDK_RPC_RUNTIME) 1091 1092 static void 1093 free_rpc_target_lun(struct rpc_target_lun *req) 1094 { 1095 free(req->name); 1096 free(req->bdev_name); 1097 } 1098 1099 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 1100 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 1101 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 1102 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 1103 }; 1104 1105 static void 1106 rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request *request, 1107 const struct spdk_json_val *params) 1108 { 1109 struct rpc_target_lun req = {}; 1110 struct spdk_iscsi_tgt_node *target; 1111 int rc; 1112 1113 req.lun_id = -1; 1114 1115 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 1116 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 1117 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1118 goto invalid; 1119 } 1120 1121 target = iscsi_find_tgt_node(req.name); 1122 if (target == NULL) { 1123 SPDK_ERRLOG("target is not found\n"); 1124 goto invalid; 1125 } 1126 1127 rc = iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 1128 if (rc < 0) { 1129 SPDK_ERRLOG("add lun failed\n"); 1130 goto invalid; 1131 } 1132 1133 free_rpc_target_lun(&req); 1134 1135 spdk_jsonrpc_send_bool_response(request, true); 1136 return; 1137 1138 invalid: 1139 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1140 "Invalid parameters"); 1141 free_rpc_target_lun(&req); 1142 } 1143 SPDK_RPC_REGISTER("iscsi_target_node_add_lun", rpc_iscsi_target_node_add_lun, SPDK_RPC_RUNTIME) 1144 1145 struct rpc_target_auth { 1146 char *name; 1147 bool disable_chap; 1148 bool require_chap; 1149 bool mutual_chap; 1150 int32_t chap_group; 1151 }; 1152 1153 static void 1154 free_rpc_target_auth(struct rpc_target_auth *req) 1155 { 1156 free(req->name); 1157 } 1158 1159 static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = { 1160 {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string}, 1161 {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true}, 1162 {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true}, 1163 {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true}, 1164 {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true}, 1165 }; 1166 1167 static void 1168 rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request *request, 1169 const struct spdk_json_val *params) 1170 { 1171 struct rpc_target_auth req = {}; 1172 struct spdk_iscsi_tgt_node *target; 1173 int rc; 1174 1175 if (spdk_json_decode_object(params, rpc_target_auth_decoders, 1176 SPDK_COUNTOF(rpc_target_auth_decoders), &req)) { 1177 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1178 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1179 "Invalid parameters"); 1180 goto exit; 1181 } 1182 1183 target = iscsi_find_tgt_node(req.name); 1184 if (target == NULL) { 1185 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1186 "Could not find target %s", req.name); 1187 goto exit; 1188 } 1189 1190 rc = iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap, 1191 req.mutual_chap, req.chap_group); 1192 if (rc < 0) { 1193 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1194 "Invalid combination of auth params"); 1195 goto exit; 1196 } 1197 1198 free_rpc_target_auth(&req); 1199 1200 spdk_jsonrpc_send_bool_response(request, true); 1201 return; 1202 1203 exit: 1204 free_rpc_target_auth(&req); 1205 } 1206 SPDK_RPC_REGISTER("iscsi_target_node_set_auth", rpc_iscsi_target_node_set_auth, 1207 SPDK_RPC_RUNTIME) 1208 1209 struct rpc_target_redirect { 1210 char *name; 1211 int32_t pg_tag; 1212 char *redirect_host; 1213 char *redirect_port; 1214 }; 1215 1216 static void 1217 free_rpc_target_redirect(struct rpc_target_redirect *req) 1218 { 1219 free(req->name); 1220 free(req->redirect_host); 1221 free(req->redirect_port); 1222 } 1223 1224 static const struct spdk_json_object_decoder rpc_target_redirect_decoders[] = { 1225 {"name", offsetof(struct rpc_target_redirect, name), spdk_json_decode_string}, 1226 {"pg_tag", offsetof(struct rpc_target_redirect, pg_tag), spdk_json_decode_int32}, 1227 {"redirect_host", offsetof(struct rpc_target_redirect, redirect_host), spdk_json_decode_string, true}, 1228 {"redirect_port", offsetof(struct rpc_target_redirect, redirect_port), spdk_json_decode_string, true}, 1229 }; 1230 1231 static void 1232 rpc_iscsi_target_node_set_redirect(struct spdk_jsonrpc_request *request, 1233 const struct spdk_json_val *params) 1234 { 1235 struct rpc_target_redirect req = {}; 1236 struct spdk_iscsi_tgt_node *target; 1237 int rc; 1238 1239 if (spdk_json_decode_object(params, rpc_target_redirect_decoders, 1240 SPDK_COUNTOF(rpc_target_redirect_decoders), 1241 &req)) { 1242 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1243 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1244 "Invalid parameters"); 1245 free_rpc_target_redirect(&req); 1246 return; 1247 } 1248 1249 target = iscsi_find_tgt_node(req.name); 1250 if (target == NULL) { 1251 SPDK_ERRLOG("target %s is not found\n", req.name); 1252 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1253 "Target %s is not found", req.name); 1254 free_rpc_target_redirect(&req); 1255 return; 1256 } 1257 1258 rc = iscsi_tgt_node_redirect(target, req.pg_tag, req.redirect_host, req.redirect_port); 1259 if (rc != 0) { 1260 SPDK_ERRLOG("failed to redirect target %s\n", req.name); 1261 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1262 "Failed to redirect target %s, (%d): %s", 1263 req.name, rc, spdk_strerror(-rc)); 1264 free_rpc_target_redirect(&req); 1265 return; 1266 } 1267 1268 free_rpc_target_redirect(&req); 1269 1270 spdk_jsonrpc_send_bool_response(request, true); 1271 } 1272 SPDK_RPC_REGISTER("iscsi_target_node_set_redirect", rpc_iscsi_target_node_set_redirect, 1273 SPDK_RPC_RUNTIME) 1274 1275 struct rpc_target_logout { 1276 char *name; 1277 int32_t pg_tag; 1278 }; 1279 1280 static void 1281 free_rpc_target_logout(struct rpc_target_logout *req) 1282 { 1283 free(req->name); 1284 } 1285 1286 static const struct spdk_json_object_decoder rpc_target_logout_decoders[] = { 1287 {"name", offsetof(struct rpc_target_logout, name), spdk_json_decode_string}, 1288 {"pg_tag", offsetof(struct rpc_target_logout, pg_tag), spdk_json_decode_int32, true}, 1289 }; 1290 1291 static void 1292 rpc_iscsi_target_node_request_logout(struct spdk_jsonrpc_request *request, 1293 const struct spdk_json_val *params) 1294 { 1295 struct rpc_target_logout req = {}; 1296 struct spdk_iscsi_tgt_node *target; 1297 1298 /* If pg_tag is omitted, request all connections to the specified target 1299 * to logout. 1300 */ 1301 req.pg_tag = -1; 1302 1303 if (spdk_json_decode_object(params, rpc_target_logout_decoders, 1304 SPDK_COUNTOF(rpc_target_logout_decoders), 1305 &req)) { 1306 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1307 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1308 "Invalid parameters"); 1309 free_rpc_target_logout(&req); 1310 return; 1311 } 1312 1313 target = iscsi_find_tgt_node(req.name); 1314 if (target == NULL) { 1315 SPDK_ERRLOG("target %s is not found\n", req.name); 1316 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1317 "Target %s is not found", req.name); 1318 free_rpc_target_logout(&req); 1319 return; 1320 } 1321 1322 iscsi_conns_request_logout(target, req.pg_tag); 1323 1324 free_rpc_target_logout(&req); 1325 1326 spdk_jsonrpc_send_bool_response(request, true); 1327 } 1328 SPDK_RPC_REGISTER("iscsi_target_node_request_logout", rpc_iscsi_target_node_request_logout, 1329 SPDK_RPC_RUNTIME) 1330 1331 static void 1332 rpc_iscsi_get_options(struct spdk_jsonrpc_request *request, 1333 const struct spdk_json_val *params) 1334 { 1335 struct spdk_json_write_ctx *w; 1336 1337 if (params != NULL) { 1338 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1339 "iscsi_get_options requires no parameters"); 1340 return; 1341 } 1342 1343 w = spdk_jsonrpc_begin_result(request); 1344 iscsi_opts_info_json(w); 1345 1346 spdk_jsonrpc_end_result(request, w); 1347 } 1348 SPDK_RPC_REGISTER("iscsi_get_options", rpc_iscsi_get_options, SPDK_RPC_RUNTIME) 1349 1350 struct rpc_discovery_auth { 1351 bool disable_chap; 1352 bool require_chap; 1353 bool mutual_chap; 1354 int32_t chap_group; 1355 }; 1356 1357 static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = { 1358 {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true}, 1359 {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true}, 1360 {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true}, 1361 {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true}, 1362 }; 1363 1364 static void 1365 rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request *request, 1366 const struct spdk_json_val *params) 1367 { 1368 struct rpc_discovery_auth req = {}; 1369 int rc; 1370 1371 if (spdk_json_decode_object(params, rpc_discovery_auth_decoders, 1372 SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) { 1373 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1374 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1375 "Invalid parameters"); 1376 return; 1377 } 1378 1379 rc = iscsi_set_discovery_auth(req.disable_chap, req.require_chap, 1380 req.mutual_chap, req.chap_group); 1381 if (rc < 0) { 1382 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1383 "Invalid combination of CHAP params"); 1384 return; 1385 } 1386 1387 spdk_jsonrpc_send_bool_response(request, true); 1388 } 1389 SPDK_RPC_REGISTER("iscsi_set_discovery_auth", rpc_iscsi_set_discovery_auth, SPDK_RPC_RUNTIME) 1390 1391 #define MAX_AUTH_SECRETS 64 1392 1393 struct rpc_auth_secret { 1394 char *user; 1395 char *secret; 1396 char *muser; 1397 char *msecret; 1398 }; 1399 1400 static void 1401 free_rpc_auth_secret(struct rpc_auth_secret *_secret) 1402 { 1403 free(_secret->user); 1404 free(_secret->secret); 1405 free(_secret->muser); 1406 free(_secret->msecret); 1407 } 1408 1409 static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = { 1410 {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string}, 1411 {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string}, 1412 {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true}, 1413 {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true}, 1414 }; 1415 1416 static int 1417 decode_rpc_auth_secret(const struct spdk_json_val *val, void *out) 1418 { 1419 struct rpc_auth_secret *_secret = out; 1420 1421 return spdk_json_decode_object(val, rpc_auth_secret_decoders, 1422 SPDK_COUNTOF(rpc_auth_secret_decoders), _secret); 1423 } 1424 1425 struct rpc_auth_secrets { 1426 size_t num_secret; 1427 struct rpc_auth_secret secrets[MAX_AUTH_SECRETS]; 1428 }; 1429 1430 static void 1431 free_rpc_auth_secrets(struct rpc_auth_secrets *secrets) 1432 { 1433 size_t i; 1434 1435 for (i = 0; i < secrets->num_secret; i++) { 1436 free_rpc_auth_secret(&secrets->secrets[i]); 1437 } 1438 } 1439 1440 static int 1441 decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out) 1442 { 1443 struct rpc_auth_secrets *secrets = out; 1444 1445 return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets, 1446 MAX_AUTH_SECRETS, &secrets->num_secret, 1447 sizeof(struct rpc_auth_secret)); 1448 } 1449 1450 struct rpc_auth_group { 1451 int32_t tag; 1452 struct rpc_auth_secrets secrets; 1453 }; 1454 1455 static void 1456 free_rpc_auth_group(struct rpc_auth_group *group) 1457 { 1458 free_rpc_auth_secrets(&group->secrets); 1459 } 1460 1461 static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = { 1462 {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32}, 1463 {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true}, 1464 }; 1465 1466 static void 1467 rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request *request, 1468 const struct spdk_json_val *params) 1469 { 1470 struct rpc_auth_group req = {}; 1471 struct rpc_auth_secret *_secret; 1472 struct spdk_iscsi_auth_group *group = NULL; 1473 int rc; 1474 size_t i; 1475 1476 if (spdk_json_decode_object(params, rpc_auth_group_decoders, 1477 SPDK_COUNTOF(rpc_auth_group_decoders), &req)) { 1478 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1479 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1480 "Invalid parameters"); 1481 free_rpc_auth_group(&req); 1482 return; 1483 } 1484 1485 pthread_mutex_lock(&g_iscsi.mutex); 1486 1487 rc = iscsi_add_auth_group(req.tag, &group); 1488 if (rc != 0) { 1489 pthread_mutex_unlock(&g_iscsi.mutex); 1490 1491 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1492 "Could not add auth group (%d), %s", 1493 req.tag, spdk_strerror(-rc)); 1494 free_rpc_auth_group(&req); 1495 return; 1496 } 1497 1498 for (i = 0; i < req.secrets.num_secret; i++) { 1499 _secret = &req.secrets.secrets[i]; 1500 rc = iscsi_auth_group_add_secret(group, _secret->user, _secret->secret, 1501 _secret->muser, _secret->msecret); 1502 if (rc != 0) { 1503 iscsi_delete_auth_group(group); 1504 pthread_mutex_unlock(&g_iscsi.mutex); 1505 1506 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1507 "Could not add secret to auth group (%d), %s", 1508 req.tag, spdk_strerror(-rc)); 1509 free_rpc_auth_group(&req); 1510 return; 1511 } 1512 } 1513 1514 pthread_mutex_unlock(&g_iscsi.mutex); 1515 1516 free_rpc_auth_group(&req); 1517 1518 spdk_jsonrpc_send_bool_response(request, true); 1519 } 1520 SPDK_RPC_REGISTER("iscsi_create_auth_group", rpc_iscsi_create_auth_group, SPDK_RPC_RUNTIME) 1521 1522 struct rpc_delete_auth_group { 1523 int32_t tag; 1524 }; 1525 1526 static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = { 1527 {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32}, 1528 }; 1529 1530 static void 1531 rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request *request, 1532 const struct spdk_json_val *params) 1533 { 1534 struct rpc_delete_auth_group req = {}; 1535 struct spdk_iscsi_auth_group *group; 1536 1537 if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders, 1538 SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) { 1539 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1540 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1541 "Invalid parameters"); 1542 return; 1543 } 1544 1545 pthread_mutex_lock(&g_iscsi.mutex); 1546 1547 group = iscsi_find_auth_group_by_tag(req.tag); 1548 if (group == NULL) { 1549 pthread_mutex_unlock(&g_iscsi.mutex); 1550 1551 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1552 "Could not find auth group (%d)", req.tag); 1553 return; 1554 } 1555 1556 iscsi_delete_auth_group(group); 1557 1558 pthread_mutex_unlock(&g_iscsi.mutex); 1559 1560 spdk_jsonrpc_send_bool_response(request, true); 1561 } 1562 SPDK_RPC_REGISTER("iscsi_delete_auth_group", rpc_iscsi_delete_auth_group, SPDK_RPC_RUNTIME) 1563 1564 struct rpc_add_auth_secret { 1565 int32_t tag; 1566 char *user; 1567 char *secret; 1568 char *muser; 1569 char *msecret; 1570 }; 1571 1572 static void 1573 free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret) 1574 { 1575 free(_secret->user); 1576 free(_secret->secret); 1577 free(_secret->muser); 1578 free(_secret->msecret); 1579 } 1580 1581 static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = { 1582 {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32}, 1583 {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string}, 1584 {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string}, 1585 {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true}, 1586 {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true}, 1587 }; 1588 1589 static void 1590 rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request *request, 1591 const struct spdk_json_val *params) 1592 { 1593 struct rpc_add_auth_secret req = {}; 1594 struct spdk_iscsi_auth_group *group; 1595 int rc; 1596 1597 if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders, 1598 SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) { 1599 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1600 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1601 "Invalid parameters"); 1602 free_rpc_add_auth_secret(&req); 1603 return; 1604 } 1605 1606 pthread_mutex_lock(&g_iscsi.mutex); 1607 1608 group = iscsi_find_auth_group_by_tag(req.tag); 1609 if (group == NULL) { 1610 pthread_mutex_unlock(&g_iscsi.mutex); 1611 1612 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1613 "Could not find auth group (%d)", req.tag); 1614 free_rpc_add_auth_secret(&req); 1615 return; 1616 } 1617 1618 rc = iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret); 1619 if (rc != 0) { 1620 pthread_mutex_unlock(&g_iscsi.mutex); 1621 1622 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1623 "Could not add secret to auth group (%d), %s", 1624 req.tag, spdk_strerror(-rc)); 1625 free_rpc_add_auth_secret(&req); 1626 return; 1627 } 1628 1629 pthread_mutex_unlock(&g_iscsi.mutex); 1630 1631 free_rpc_add_auth_secret(&req); 1632 1633 spdk_jsonrpc_send_bool_response(request, true); 1634 } 1635 SPDK_RPC_REGISTER("iscsi_auth_group_add_secret", rpc_iscsi_auth_group_add_secret, 1636 SPDK_RPC_RUNTIME) 1637 1638 1639 struct rpc_remove_auth_secret { 1640 int32_t tag; 1641 char *user; 1642 }; 1643 1644 static void 1645 free_rpc_remove_auth_secret(struct rpc_remove_auth_secret *_secret) 1646 { 1647 free(_secret->user); 1648 } 1649 1650 static const struct spdk_json_object_decoder rpc_remove_auth_secret_decoders[] = { 1651 {"tag", offsetof(struct rpc_remove_auth_secret, tag), spdk_json_decode_int32}, 1652 {"user", offsetof(struct rpc_remove_auth_secret, user), spdk_json_decode_string}, 1653 }; 1654 1655 static void 1656 rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request *request, 1657 const struct spdk_json_val *params) 1658 { 1659 struct rpc_remove_auth_secret req = {}; 1660 struct spdk_iscsi_auth_group *group; 1661 int rc; 1662 1663 if (spdk_json_decode_object(params, rpc_remove_auth_secret_decoders, 1664 SPDK_COUNTOF(rpc_remove_auth_secret_decoders), &req)) { 1665 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1666 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1667 "Invalid parameters"); 1668 free_rpc_remove_auth_secret(&req); 1669 return; 1670 } 1671 1672 pthread_mutex_lock(&g_iscsi.mutex); 1673 1674 group = iscsi_find_auth_group_by_tag(req.tag); 1675 if (group == NULL) { 1676 pthread_mutex_unlock(&g_iscsi.mutex); 1677 1678 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1679 "Could not find auth group (%d)", req.tag); 1680 free_rpc_remove_auth_secret(&req); 1681 return; 1682 } 1683 1684 rc = iscsi_auth_group_delete_secret(group, req.user); 1685 if (rc != 0) { 1686 pthread_mutex_unlock(&g_iscsi.mutex); 1687 1688 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1689 "Could not delete secret from CHAP group (%d), %s", 1690 req.tag, spdk_strerror(-rc)); 1691 free_rpc_remove_auth_secret(&req); 1692 return; 1693 } 1694 1695 pthread_mutex_unlock(&g_iscsi.mutex); 1696 1697 free_rpc_remove_auth_secret(&req); 1698 1699 spdk_jsonrpc_send_bool_response(request, true); 1700 } 1701 SPDK_RPC_REGISTER("iscsi_auth_group_remove_secret", 1702 rpc_iscsi_auth_group_remove_secret, SPDK_RPC_RUNTIME) 1703 1704 static void 1705 rpc_iscsi_get_auth_groups(struct spdk_jsonrpc_request *request, 1706 const struct spdk_json_val *params) 1707 { 1708 struct spdk_json_write_ctx *w; 1709 1710 if (params != NULL) { 1711 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1712 "iscsi_get_auth_groups requires no parameters"); 1713 return; 1714 } 1715 1716 w = spdk_jsonrpc_begin_result(request); 1717 spdk_json_write_array_begin(w); 1718 iscsi_auth_groups_info_json(w); 1719 spdk_json_write_array_end(w); 1720 1721 spdk_jsonrpc_end_result(request, w); 1722 } 1723 SPDK_RPC_REGISTER("iscsi_get_auth_groups", rpc_iscsi_get_auth_groups, SPDK_RPC_RUNTIME) 1724 1725 static const struct spdk_json_object_decoder rpc_set_iscsi_opts_decoders[] = { 1726 {"auth_file", offsetof(struct spdk_iscsi_opts, authfile), spdk_json_decode_string, true}, 1727 {"node_base", offsetof(struct spdk_iscsi_opts, nodebase), spdk_json_decode_string, true}, 1728 {"nop_timeout", offsetof(struct spdk_iscsi_opts, timeout), spdk_json_decode_int32, true}, 1729 {"nop_in_interval", offsetof(struct spdk_iscsi_opts, nopininterval), spdk_json_decode_int32, true}, 1730 {"no_discovery_auth", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1731 {"req_discovery_auth", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1732 {"req_discovery_auth_mutual", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1733 {"discovery_auth_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1734 {"disable_chap", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1735 {"require_chap", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1736 {"mutual_chap", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1737 {"chap_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1738 {"max_sessions", offsetof(struct spdk_iscsi_opts, MaxSessions), spdk_json_decode_uint32, true}, 1739 {"max_queue_depth", offsetof(struct spdk_iscsi_opts, MaxQueueDepth), spdk_json_decode_uint32, true}, 1740 {"max_connections_per_session", offsetof(struct spdk_iscsi_opts, MaxConnectionsPerSession), spdk_json_decode_uint32, true}, 1741 {"default_time2wait", offsetof(struct spdk_iscsi_opts, DefaultTime2Wait), spdk_json_decode_uint32, true}, 1742 {"default_time2retain", offsetof(struct spdk_iscsi_opts, DefaultTime2Retain), spdk_json_decode_uint32, true}, 1743 {"first_burst_length", offsetof(struct spdk_iscsi_opts, FirstBurstLength), spdk_json_decode_uint32, true}, 1744 {"immediate_data", offsetof(struct spdk_iscsi_opts, ImmediateData), spdk_json_decode_bool, true}, 1745 {"error_recovery_level", offsetof(struct spdk_iscsi_opts, ErrorRecoveryLevel), spdk_json_decode_uint32, true}, 1746 {"allow_duplicated_isid", offsetof(struct spdk_iscsi_opts, AllowDuplicateIsid), spdk_json_decode_bool, true}, 1747 {"max_large_datain_per_connection", offsetof(struct spdk_iscsi_opts, MaxLargeDataInPerConnection), spdk_json_decode_uint32, true}, 1748 {"max_r2t_per_connection", offsetof(struct spdk_iscsi_opts, MaxR2TPerConnection), spdk_json_decode_uint32, true}, 1749 {"pdu_pool_size", offsetof(struct spdk_iscsi_opts, pdu_pool_size), spdk_json_decode_uint32, true}, 1750 {"immediate_data_pool_size", offsetof(struct spdk_iscsi_opts, immediate_data_pool_size), spdk_json_decode_uint32, true}, 1751 {"data_out_pool_size", offsetof(struct spdk_iscsi_opts, data_out_pool_size), spdk_json_decode_uint32, true}, 1752 }; 1753 1754 static void 1755 rpc_iscsi_set_options(struct spdk_jsonrpc_request *request, 1756 const struct spdk_json_val *params) 1757 { 1758 struct spdk_iscsi_opts *opts; 1759 1760 if (g_spdk_iscsi_opts != NULL) { 1761 SPDK_ERRLOG("this RPC must not be called more than once.\n"); 1762 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1763 "Must not call more than once"); 1764 return; 1765 } 1766 1767 opts = iscsi_opts_alloc(); 1768 if (opts == NULL) { 1769 SPDK_ERRLOG("iscsi_opts_alloc() failed.\n"); 1770 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1771 "Out of memory"); 1772 return; 1773 } 1774 1775 if (params != NULL) { 1776 if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders, 1777 SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) { 1778 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 1779 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1780 "Invalid parameters"); 1781 iscsi_opts_free(opts); 1782 return; 1783 } 1784 } 1785 1786 g_spdk_iscsi_opts = iscsi_opts_copy(opts); 1787 iscsi_opts_free(opts); 1788 1789 if (g_spdk_iscsi_opts == NULL) { 1790 SPDK_ERRLOG("iscsi_opts_copy() failed\n"); 1791 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1792 "Out of memory"); 1793 return; 1794 } 1795 1796 spdk_jsonrpc_send_bool_response(request, true); 1797 } 1798 SPDK_RPC_REGISTER("iscsi_set_options", rpc_iscsi_set_options, SPDK_RPC_STARTUP) 1799 1800 struct rpc_iscsi_enable_histogram_request { 1801 char *name; 1802 bool enable; 1803 }; 1804 1805 static const struct spdk_json_object_decoder rpc_iscsi_enable_histogram_request_decoders[] = { 1806 {"name", offsetof(struct rpc_iscsi_enable_histogram_request, name), spdk_json_decode_string}, 1807 {"enable", offsetof(struct rpc_iscsi_enable_histogram_request, enable), spdk_json_decode_bool}, 1808 }; 1809 1810 struct iscsi_enable_histogram_ctx { 1811 struct spdk_jsonrpc_request *request; 1812 struct spdk_iscsi_tgt_node *target; 1813 bool enable; 1814 int status; 1815 struct spdk_thread *orig_thread; 1816 }; 1817 1818 static void 1819 rpc_iscsi_enable_histogram_done(void *_ctx) 1820 { 1821 struct iscsi_enable_histogram_ctx *ctx = _ctx; 1822 1823 if (ctx->status == 0) { 1824 spdk_jsonrpc_send_bool_response(ctx->request, true); 1825 } else { 1826 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1827 spdk_strerror(-ctx->status)); 1828 } 1829 1830 free(ctx); 1831 } 1832 1833 static void 1834 _iscsi_enable_histogram(void *_ctx) 1835 { 1836 struct iscsi_enable_histogram_ctx *ctx = _ctx; 1837 1838 ctx->status = iscsi_tgt_node_enable_histogram(ctx->target, ctx->enable); 1839 } 1840 1841 static void 1842 _rpc_iscsi_enable_histogram(void *_ctx) 1843 { 1844 struct iscsi_enable_histogram_ctx *ctx = _ctx; 1845 1846 pthread_mutex_lock(&ctx->target->mutex); 1847 _iscsi_enable_histogram(ctx); 1848 ctx->target->num_active_conns--; 1849 pthread_mutex_unlock(&ctx->target->mutex); 1850 1851 spdk_thread_send_msg(ctx->orig_thread, rpc_iscsi_enable_histogram_done, ctx); 1852 } 1853 1854 static void 1855 rpc_iscsi_enable_histogram(struct spdk_jsonrpc_request *request, 1856 const struct spdk_json_val *params) 1857 { 1858 struct rpc_iscsi_enable_histogram_request req = {NULL}; 1859 struct iscsi_enable_histogram_ctx *ctx; 1860 struct spdk_iscsi_tgt_node *target; 1861 struct spdk_thread *thread; 1862 spdk_msg_fn fn; 1863 1864 if (spdk_json_decode_object(params, rpc_iscsi_enable_histogram_request_decoders, 1865 SPDK_COUNTOF(rpc_iscsi_enable_histogram_request_decoders), 1866 &req)) { 1867 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1868 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1869 "spdk_json_decode_object failed"); 1870 return; 1871 } 1872 1873 ctx = calloc(1, sizeof(*ctx)); 1874 if (ctx == NULL) { 1875 SPDK_ERRLOG("Memory allocation failed\n"); 1876 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1877 "Memory allocation failed"); 1878 return; 1879 } 1880 1881 target = iscsi_find_tgt_node(req.name); 1882 1883 free(req.name); 1884 1885 if (target == NULL) { 1886 SPDK_ERRLOG("target is not found\n"); 1887 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1888 "Invalid parameters"); 1889 free(ctx); 1890 return; 1891 } 1892 1893 ctx->request = request; 1894 ctx->target = target; 1895 ctx->enable = req.enable; 1896 ctx->orig_thread = spdk_get_thread(); 1897 1898 pthread_mutex_lock(&ctx->target->mutex); 1899 if (target->pg == NULL) { 1900 _iscsi_enable_histogram(ctx); 1901 thread = ctx->orig_thread; 1902 fn = rpc_iscsi_enable_histogram_done; 1903 } else { 1904 /** 1905 * We get spdk thread of the target by using target->pg. 1906 * If target->num_active_conns >= 1, target->pg will not change. 1907 * So, It is safer to increase and decrease target->num_active_conns 1908 * while updating target->histogram. 1909 */ 1910 target->num_active_conns++; 1911 thread = spdk_io_channel_get_thread(spdk_io_channel_from_ctx(target->pg)); 1912 fn = _rpc_iscsi_enable_histogram; 1913 } 1914 pthread_mutex_unlock(&ctx->target->mutex); 1915 1916 spdk_thread_send_msg(thread, fn, ctx); 1917 } 1918 1919 SPDK_RPC_REGISTER("iscsi_enable_histogram", rpc_iscsi_enable_histogram, SPDK_RPC_RUNTIME) 1920 1921 struct rpc_iscsi_get_histogram_request { 1922 char *name; 1923 }; 1924 1925 static const struct spdk_json_object_decoder rpc_iscsi_get_histogram_request_decoders[] = { 1926 {"name", offsetof(struct rpc_iscsi_get_histogram_request, name), spdk_json_decode_string} 1927 }; 1928 1929 static void 1930 free_rpc_iscsi_get_histogram_request(struct rpc_iscsi_get_histogram_request *r) 1931 { 1932 free(r->name); 1933 } 1934 1935 static void 1936 rpc_iscsi_get_histogram(struct spdk_jsonrpc_request *request, 1937 const struct spdk_json_val *params) 1938 { 1939 struct rpc_iscsi_get_histogram_request req = {NULL}; 1940 struct spdk_iscsi_tgt_node *target; 1941 struct spdk_json_write_ctx *w; 1942 char *encoded_histogram; 1943 size_t src_len, dst_len; 1944 int rc; 1945 1946 if (spdk_json_decode_object(params, rpc_iscsi_get_histogram_request_decoders, 1947 SPDK_COUNTOF(rpc_iscsi_get_histogram_request_decoders), 1948 &req)) { 1949 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1950 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1951 "spdk_json_decode_object failed"); 1952 goto free_req; 1953 } 1954 1955 target = iscsi_find_tgt_node(req.name); 1956 if (target == NULL) { 1957 SPDK_ERRLOG("target is not found\n"); 1958 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1959 "target not found"); 1960 goto free_req; 1961 } 1962 1963 if (!target->histogram) { 1964 SPDK_ERRLOG("target's histogram function is not enabled\n"); 1965 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1966 "target's histogram function is not enabled"); 1967 goto free_req; 1968 } 1969 1970 src_len = SPDK_HISTOGRAM_NUM_BUCKETS(target->histogram) * sizeof(uint64_t); 1971 dst_len = spdk_base64_get_encoded_strlen(src_len) + 1; 1972 encoded_histogram = malloc(dst_len); 1973 if (encoded_histogram == NULL) { 1974 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1975 spdk_strerror(ENOMEM)); 1976 goto free_req; 1977 } 1978 1979 rc = spdk_base64_encode(encoded_histogram, target->histogram->bucket, src_len); 1980 if (rc != 0) { 1981 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1982 spdk_strerror(-rc)); 1983 goto free_encoded_histogram; 1984 } 1985 1986 w = spdk_jsonrpc_begin_result(request); 1987 1988 spdk_json_write_object_begin(w); 1989 spdk_json_write_named_string(w, "histogram", encoded_histogram); 1990 spdk_json_write_named_int64(w, "bucket_shift", target->histogram->bucket_shift); 1991 spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz()); 1992 1993 spdk_json_write_object_end(w); 1994 spdk_jsonrpc_end_result(request, w); 1995 1996 free_encoded_histogram: 1997 free(encoded_histogram); 1998 free_req: 1999 free_rpc_iscsi_get_histogram_request(&req); 2000 } 2001 2002 SPDK_RPC_REGISTER("iscsi_get_histogram", rpc_iscsi_get_histogram, SPDK_RPC_RUNTIME) 2003