1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 5 * Copyright (c) Intel Corporation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "iscsi/iscsi.h" 36 #include "iscsi/conn.h" 37 #include "iscsi/tgt_node.h" 38 #include "iscsi/portal_grp.h" 39 #include "iscsi/init_grp.h" 40 41 #include "spdk/rpc.h" 42 #include "spdk/util.h" 43 #include "spdk/event.h" 44 45 #include "spdk_internal/log.h" 46 47 static void 48 spdk_rpc_get_initiator_groups(struct spdk_jsonrpc_request *request, 49 const struct spdk_json_val *params) 50 { 51 struct spdk_json_write_ctx *w; 52 53 if (params != NULL) { 54 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 55 "get_initiator_groups requires no parameters"); 56 return; 57 } 58 59 w = spdk_jsonrpc_begin_result(request); 60 if (w == NULL) { 61 return; 62 } 63 64 spdk_json_write_array_begin(w); 65 spdk_iscsi_init_grps_info_json(w); 66 spdk_json_write_array_end(w); 67 68 spdk_jsonrpc_end_result(request, w); 69 } 70 SPDK_RPC_REGISTER("get_initiator_groups", spdk_rpc_get_initiator_groups, SPDK_RPC_RUNTIME) 71 72 struct rpc_initiator_list { 73 size_t num_initiators; 74 char *initiators[MAX_INITIATOR]; 75 }; 76 77 static int 78 decode_rpc_initiator_list(const struct spdk_json_val *val, void *out) 79 { 80 struct rpc_initiator_list *list = out; 81 82 return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR, 83 &list->num_initiators, sizeof(char *)); 84 } 85 86 static void 87 free_rpc_initiator_list(struct rpc_initiator_list *list) 88 { 89 size_t i; 90 91 for (i = 0; i < list->num_initiators; i++) { 92 free(list->initiators[i]); 93 } 94 } 95 96 struct rpc_netmask_list { 97 size_t num_netmasks; 98 char *netmasks[MAX_NETMASK]; 99 }; 100 101 static int 102 decode_rpc_netmask_list(const struct spdk_json_val *val, void *out) 103 { 104 struct rpc_netmask_list *list = out; 105 106 return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK, 107 &list->num_netmasks, sizeof(char *)); 108 } 109 110 static void 111 free_rpc_netmask_list(struct rpc_netmask_list *list) 112 { 113 size_t i; 114 115 for (i = 0; i < list->num_netmasks; i++) { 116 free(list->netmasks[i]); 117 } 118 } 119 120 struct rpc_initiator_group { 121 int32_t tag; 122 struct rpc_initiator_list initiator_list; 123 struct rpc_netmask_list netmask_list; 124 }; 125 126 static void 127 free_rpc_initiator_group(struct rpc_initiator_group *ig) 128 { 129 free_rpc_initiator_list(&ig->initiator_list); 130 free_rpc_netmask_list(&ig->netmask_list); 131 } 132 133 static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = { 134 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 135 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list}, 136 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list}, 137 }; 138 139 static void 140 spdk_rpc_add_initiator_group(struct spdk_jsonrpc_request *request, 141 const struct spdk_json_val *params) 142 { 143 struct rpc_initiator_group req = {}; 144 struct spdk_json_write_ctx *w; 145 146 if (spdk_json_decode_object(params, rpc_initiator_group_decoders, 147 SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) { 148 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 149 goto invalid; 150 } 151 152 if (req.initiator_list.num_initiators == 0 || 153 req.netmask_list.num_netmasks == 0) { 154 goto invalid; 155 } 156 157 if (spdk_iscsi_init_grp_create_from_initiator_list(req.tag, 158 req.initiator_list.num_initiators, 159 req.initiator_list.initiators, 160 req.netmask_list.num_netmasks, 161 req.netmask_list.netmasks)) { 162 SPDK_ERRLOG("create_from_initiator_list failed\n"); 163 goto invalid; 164 } 165 166 free_rpc_initiator_group(&req); 167 168 w = spdk_jsonrpc_begin_result(request); 169 if (w == NULL) { 170 return; 171 } 172 173 spdk_json_write_bool(w, true); 174 spdk_jsonrpc_end_result(request, w); 175 return; 176 177 invalid: 178 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 179 free_rpc_initiator_group(&req); 180 } 181 SPDK_RPC_REGISTER("add_initiator_group", spdk_rpc_add_initiator_group, SPDK_RPC_RUNTIME) 182 183 static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = { 184 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 185 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true}, 186 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true}, 187 }; 188 189 static void 190 spdk_rpc_add_initiators_to_initiator_group(struct spdk_jsonrpc_request *request, 191 const struct spdk_json_val *params) 192 { 193 struct rpc_initiator_group req = {}; 194 struct spdk_json_write_ctx *w; 195 196 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 197 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 198 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 199 goto invalid; 200 } 201 202 if (spdk_iscsi_init_grp_add_initiators_from_initiator_list(req.tag, 203 req.initiator_list.num_initiators, 204 req.initiator_list.initiators, 205 req.netmask_list.num_netmasks, 206 req.netmask_list.netmasks)) { 207 SPDK_ERRLOG("add_initiators_from_initiator_list failed\n"); 208 goto invalid; 209 } 210 211 free_rpc_initiator_group(&req); 212 213 w = spdk_jsonrpc_begin_result(request); 214 if (w == NULL) { 215 return; 216 } 217 218 spdk_json_write_bool(w, true); 219 spdk_jsonrpc_end_result(request, w); 220 return; 221 222 invalid: 223 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 224 free_rpc_initiator_group(&req); 225 } 226 SPDK_RPC_REGISTER("add_initiators_to_initiator_group", 227 spdk_rpc_add_initiators_to_initiator_group, SPDK_RPC_RUNTIME) 228 229 static void 230 spdk_rpc_delete_initiators_from_initiator_group(struct spdk_jsonrpc_request *request, 231 const struct spdk_json_val *params) 232 { 233 struct rpc_initiator_group req = {}; 234 struct spdk_json_write_ctx *w; 235 236 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 237 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 238 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 239 goto invalid; 240 } 241 242 if (spdk_iscsi_init_grp_delete_initiators_from_initiator_list(req.tag, 243 req.initiator_list.num_initiators, 244 req.initiator_list.initiators, 245 req.netmask_list.num_netmasks, 246 req.netmask_list.netmasks)) { 247 SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n"); 248 goto invalid; 249 } 250 251 free_rpc_initiator_group(&req); 252 253 w = spdk_jsonrpc_begin_result(request); 254 if (w == NULL) { 255 return; 256 } 257 258 spdk_json_write_bool(w, true); 259 spdk_jsonrpc_end_result(request, w); 260 return; 261 262 invalid: 263 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 264 free_rpc_initiator_group(&req); 265 } 266 SPDK_RPC_REGISTER("delete_initiators_from_initiator_group", 267 spdk_rpc_delete_initiators_from_initiator_group, SPDK_RPC_RUNTIME) 268 269 struct rpc_delete_initiator_group { 270 int32_t tag; 271 }; 272 273 static const struct spdk_json_object_decoder rpc_delete_initiator_group_decoders[] = { 274 {"tag", offsetof(struct rpc_delete_initiator_group, tag), spdk_json_decode_int32}, 275 }; 276 277 static void 278 spdk_rpc_delete_initiator_group(struct spdk_jsonrpc_request *request, 279 const struct spdk_json_val *params) 280 { 281 struct rpc_delete_initiator_group req = {}; 282 struct spdk_json_write_ctx *w; 283 struct spdk_iscsi_init_grp *ig; 284 285 if (spdk_json_decode_object(params, rpc_delete_initiator_group_decoders, 286 SPDK_COUNTOF(rpc_delete_initiator_group_decoders), 287 &req)) { 288 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 289 goto invalid; 290 } 291 292 ig = spdk_iscsi_init_grp_unregister(req.tag); 293 if (!ig) { 294 goto invalid; 295 } 296 spdk_iscsi_tgt_node_delete_map(NULL, ig); 297 spdk_iscsi_init_grp_destroy(ig); 298 299 w = spdk_jsonrpc_begin_result(request); 300 if (w == NULL) { 301 return; 302 } 303 304 spdk_json_write_bool(w, true); 305 spdk_jsonrpc_end_result(request, w); 306 return; 307 308 invalid: 309 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 310 } 311 SPDK_RPC_REGISTER("delete_initiator_group", spdk_rpc_delete_initiator_group, SPDK_RPC_RUNTIME) 312 313 static void 314 spdk_rpc_get_target_nodes(struct spdk_jsonrpc_request *request, 315 const struct spdk_json_val *params) 316 { 317 struct spdk_json_write_ctx *w; 318 319 if (params != NULL) { 320 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 321 "get_target_nodes requires no parameters"); 322 return; 323 } 324 325 w = spdk_jsonrpc_begin_result(request); 326 if (w == NULL) { 327 return; 328 } 329 330 spdk_json_write_array_begin(w); 331 spdk_iscsi_tgt_nodes_info_json(w); 332 spdk_json_write_array_end(w); 333 334 spdk_jsonrpc_end_result(request, w); 335 } 336 SPDK_RPC_REGISTER("get_target_nodes", spdk_rpc_get_target_nodes, SPDK_RPC_RUNTIME) 337 338 struct rpc_pg_ig_map { 339 int32_t pg_tag; 340 int32_t ig_tag; 341 }; 342 343 static const struct spdk_json_object_decoder rpc_pg_ig_map_decoders[] = { 344 {"pg_tag", offsetof(struct rpc_pg_ig_map, pg_tag), spdk_json_decode_int32}, 345 {"ig_tag", offsetof(struct rpc_pg_ig_map, ig_tag), spdk_json_decode_int32}, 346 }; 347 348 static int 349 decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out) 350 { 351 struct rpc_pg_ig_map *pg_ig_map = out; 352 353 return spdk_json_decode_object(val, rpc_pg_ig_map_decoders, 354 SPDK_COUNTOF(rpc_pg_ig_map_decoders), 355 pg_ig_map); 356 } 357 358 struct rpc_pg_ig_maps { 359 size_t num_maps; 360 struct rpc_pg_ig_map maps[MAX_TARGET_MAP]; 361 }; 362 363 static int 364 decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out) 365 { 366 struct rpc_pg_ig_maps *pg_ig_maps = out; 367 368 return spdk_json_decode_array(val, decode_rpc_pg_ig_map, pg_ig_maps->maps, 369 MAX_TARGET_MAP, &pg_ig_maps->num_maps, 370 sizeof(struct rpc_pg_ig_map)); 371 } 372 373 #define RPC_CONSTRUCT_TARGET_NODE_MAX_LUN 64 374 375 struct rpc_lun { 376 char *bdev_name; 377 int32_t lun_id; 378 }; 379 380 static const struct spdk_json_object_decoder rpc_lun_decoders[] = { 381 {"bdev_name", offsetof(struct rpc_lun, bdev_name), spdk_json_decode_string}, 382 {"lun_id", offsetof(struct rpc_lun, lun_id), spdk_json_decode_int32}, 383 }; 384 385 static int 386 decode_rpc_lun(const struct spdk_json_val *val, void *out) 387 { 388 struct rpc_lun *lun = out; 389 390 return spdk_json_decode_object(val, rpc_lun_decoders, 391 SPDK_COUNTOF(rpc_lun_decoders), lun); 392 } 393 394 struct rpc_luns { 395 size_t num_luns; 396 struct rpc_lun luns[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN]; 397 }; 398 399 static int 400 decode_rpc_luns(const struct spdk_json_val *val, void *out) 401 { 402 struct rpc_luns *luns = out; 403 404 return spdk_json_decode_array(val, decode_rpc_lun, luns->luns, 405 RPC_CONSTRUCT_TARGET_NODE_MAX_LUN, 406 &luns->num_luns, sizeof(struct rpc_lun)); 407 } 408 409 static void 410 free_rpc_luns(struct rpc_luns *p) 411 { 412 size_t i; 413 414 for (i = 0; i < p->num_luns; i++) { 415 free(p->luns[i].bdev_name); 416 } 417 } 418 419 struct rpc_target_node { 420 char *name; 421 char *alias_name; 422 423 struct rpc_pg_ig_maps pg_ig_maps; 424 struct rpc_luns luns; 425 426 int32_t queue_depth; 427 bool disable_chap; 428 bool require_chap; 429 bool mutual_chap; 430 int32_t chap_group; 431 432 bool header_digest; 433 bool data_digest; 434 }; 435 436 static void 437 free_rpc_target_node(struct rpc_target_node *req) 438 { 439 free(req->name); 440 free(req->alias_name); 441 free_rpc_luns(&req->luns); 442 } 443 444 static const struct spdk_json_object_decoder rpc_target_node_decoders[] = { 445 {"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string}, 446 {"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string}, 447 {"pg_ig_maps", offsetof(struct rpc_target_node, pg_ig_maps), decode_rpc_pg_ig_maps}, 448 {"luns", offsetof(struct rpc_target_node, luns), decode_rpc_luns}, 449 {"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32}, 450 {"disable_chap", offsetof(struct rpc_target_node, disable_chap), spdk_json_decode_bool, true}, 451 {"require_chap", offsetof(struct rpc_target_node, require_chap), spdk_json_decode_bool, true}, 452 {"mutual_chap", offsetof(struct rpc_target_node, mutual_chap), spdk_json_decode_bool, true}, 453 {"chap_group", offsetof(struct rpc_target_node, chap_group), spdk_json_decode_int32, true}, 454 {"header_digest", offsetof(struct rpc_target_node, header_digest), spdk_json_decode_bool, true}, 455 {"data_digest", offsetof(struct rpc_target_node, data_digest), spdk_json_decode_bool, true}, 456 }; 457 458 static void 459 spdk_rpc_construct_target_node(struct spdk_jsonrpc_request *request, 460 const struct spdk_json_val *params) 461 { 462 struct rpc_target_node req = {}; 463 struct spdk_json_write_ctx *w; 464 struct spdk_iscsi_tgt_node *target; 465 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 466 char *bdev_names[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN] = {0}; 467 int32_t lun_ids[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN] = {0}; 468 size_t i; 469 470 if (spdk_json_decode_object(params, rpc_target_node_decoders, 471 SPDK_COUNTOF(rpc_target_node_decoders), 472 &req)) { 473 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 474 goto invalid; 475 } 476 477 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 478 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 479 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 480 } 481 482 for (i = 0; i < req.luns.num_luns; i++) { 483 bdev_names[i] = req.luns.luns[i].bdev_name; 484 lun_ids[i] = req.luns.luns[i].lun_id; 485 } 486 487 /* 488 * Use default parameters in a few places: 489 * index = -1 : automatically pick an index for the new target node 490 * alias = NULL 491 */ 492 target = spdk_iscsi_tgt_node_construct(-1, req.name, req.alias_name, 493 pg_tags, 494 ig_tags, 495 req.pg_ig_maps.num_maps, 496 (const char **)bdev_names, 497 lun_ids, 498 req.luns.num_luns, 499 req.queue_depth, 500 req.disable_chap, 501 req.require_chap, 502 req.mutual_chap, 503 req.chap_group, 504 req.header_digest, 505 req.data_digest); 506 507 if (target == NULL) { 508 goto invalid; 509 } 510 511 free_rpc_target_node(&req); 512 513 w = spdk_jsonrpc_begin_result(request); 514 if (w == NULL) { 515 return; 516 } 517 518 spdk_json_write_bool(w, true); 519 spdk_jsonrpc_end_result(request, w); 520 return; 521 522 invalid: 523 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 524 free_rpc_target_node(&req); 525 } 526 SPDK_RPC_REGISTER("construct_target_node", spdk_rpc_construct_target_node, SPDK_RPC_RUNTIME) 527 528 struct rpc_tgt_node_pg_ig_maps { 529 char *name; 530 struct rpc_pg_ig_maps pg_ig_maps; 531 }; 532 533 static const struct spdk_json_object_decoder rpc_tgt_node_pg_ig_maps_decoders[] = { 534 {"name", offsetof(struct rpc_tgt_node_pg_ig_maps, name), spdk_json_decode_string}, 535 {"pg_ig_maps", offsetof(struct rpc_tgt_node_pg_ig_maps, pg_ig_maps), decode_rpc_pg_ig_maps}, 536 }; 537 538 static void 539 spdk_rpc_add_pg_ig_maps(struct spdk_jsonrpc_request *request, 540 const struct spdk_json_val *params) 541 { 542 struct rpc_tgt_node_pg_ig_maps req = {}; 543 struct spdk_json_write_ctx *w; 544 struct spdk_iscsi_tgt_node *target; 545 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 546 size_t i; 547 int rc; 548 549 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 550 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 551 &req)) { 552 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 553 goto invalid; 554 } 555 556 target = spdk_iscsi_find_tgt_node(req.name); 557 if (target == NULL) { 558 SPDK_ERRLOG("target is not found\n"); 559 goto invalid; 560 } 561 562 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 563 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 564 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 565 } 566 567 rc = spdk_iscsi_tgt_node_add_pg_ig_maps(target, pg_tags, ig_tags, 568 req.pg_ig_maps.num_maps); 569 if (rc < 0) { 570 SPDK_ERRLOG("add pg-ig maps failed\n"); 571 goto invalid; 572 } 573 574 free(req.name); 575 576 w = spdk_jsonrpc_begin_result(request); 577 if (w != NULL) { 578 spdk_json_write_bool(w, true); 579 spdk_jsonrpc_end_result(request, w); 580 } 581 return; 582 583 invalid: 584 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 585 "Invalid parameters"); 586 free(req.name); 587 } 588 SPDK_RPC_REGISTER("add_pg_ig_maps", spdk_rpc_add_pg_ig_maps, SPDK_RPC_RUNTIME) 589 590 static void 591 spdk_rpc_delete_pg_ig_maps(struct spdk_jsonrpc_request *request, 592 const struct spdk_json_val *params) 593 { 594 struct rpc_tgt_node_pg_ig_maps req = {}; 595 struct spdk_json_write_ctx *w; 596 struct spdk_iscsi_tgt_node *target; 597 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 598 size_t i; 599 int rc; 600 601 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 602 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 603 &req)) { 604 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 605 goto invalid; 606 } 607 608 target = spdk_iscsi_find_tgt_node(req.name); 609 if (target == NULL) { 610 SPDK_ERRLOG("target is not found\n"); 611 goto invalid; 612 } 613 614 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 615 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 616 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 617 } 618 619 rc = spdk_iscsi_tgt_node_delete_pg_ig_maps(target, pg_tags, ig_tags, 620 req.pg_ig_maps.num_maps); 621 if (rc < 0) { 622 SPDK_ERRLOG("remove pg-ig maps failed\n"); 623 goto invalid; 624 } 625 626 free(req.name); 627 628 w = spdk_jsonrpc_begin_result(request); 629 if (w != NULL) { 630 spdk_json_write_bool(w, true); 631 spdk_jsonrpc_end_result(request, w); 632 } 633 return; 634 635 invalid: 636 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 637 "Invalid parameters"); 638 free(req.name); 639 } 640 SPDK_RPC_REGISTER("delete_pg_ig_maps", spdk_rpc_delete_pg_ig_maps, SPDK_RPC_RUNTIME) 641 642 struct rpc_delete_target_node { 643 char *name; 644 }; 645 646 static void 647 free_rpc_delete_target_node(struct rpc_delete_target_node *r) 648 { 649 free(r->name); 650 } 651 652 static const struct spdk_json_object_decoder rpc_delete_target_node_decoders[] = { 653 {"name", offsetof(struct rpc_delete_target_node, name), spdk_json_decode_string}, 654 }; 655 656 static void 657 spdk_rpc_delete_target_node(struct spdk_jsonrpc_request *request, 658 const struct spdk_json_val *params) 659 { 660 struct rpc_delete_target_node req = {}; 661 struct spdk_json_write_ctx *w; 662 663 if (spdk_json_decode_object(params, rpc_delete_target_node_decoders, 664 SPDK_COUNTOF(rpc_delete_target_node_decoders), 665 &req)) { 666 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 667 goto invalid; 668 } 669 670 if (req.name == NULL) { 671 SPDK_ERRLOG("missing name param\n"); 672 goto invalid; 673 } 674 675 if (spdk_iscsi_shutdown_tgt_node_by_name(req.name)) { 676 SPDK_ERRLOG("shutdown_tgt_node_by_name failed\n"); 677 goto invalid; 678 } 679 680 free_rpc_delete_target_node(&req); 681 682 w = spdk_jsonrpc_begin_result(request); 683 if (w == NULL) { 684 return; 685 } 686 687 spdk_json_write_bool(w, true); 688 spdk_jsonrpc_end_result(request, w); 689 return; 690 691 invalid: 692 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 693 free_rpc_delete_target_node(&req); 694 } 695 SPDK_RPC_REGISTER("delete_target_node", spdk_rpc_delete_target_node, SPDK_RPC_RUNTIME) 696 697 static void 698 spdk_rpc_get_portal_groups(struct spdk_jsonrpc_request *request, 699 const struct spdk_json_val *params) 700 { 701 struct spdk_json_write_ctx *w; 702 703 if (params != NULL) { 704 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 705 "get_portal_groups requires no parameters"); 706 return; 707 } 708 709 w = spdk_jsonrpc_begin_result(request); 710 if (w == NULL) { 711 return; 712 } 713 714 spdk_json_write_array_begin(w); 715 spdk_iscsi_portal_grps_info_json(w); 716 spdk_json_write_array_end(w); 717 718 spdk_jsonrpc_end_result(request, w); 719 } 720 SPDK_RPC_REGISTER("get_portal_groups", spdk_rpc_get_portal_groups, SPDK_RPC_RUNTIME) 721 722 struct rpc_portal { 723 char *host; 724 char *port; 725 char *cpumask; 726 }; 727 728 struct rpc_portal_list { 729 size_t num_portals; 730 struct rpc_portal portals[MAX_PORTAL]; 731 }; 732 733 struct rpc_portal_group { 734 int32_t tag; 735 struct rpc_portal_list portal_list; 736 }; 737 738 static void 739 free_rpc_portal(struct rpc_portal *portal) 740 { 741 free(portal->host); 742 free(portal->port); 743 free(portal->cpumask); 744 } 745 746 static void 747 free_rpc_portal_list(struct rpc_portal_list *pl) 748 { 749 size_t i; 750 751 for (i = 0; i < pl->num_portals; i++) { 752 free_rpc_portal(&pl->portals[i]); 753 } 754 pl->num_portals = 0; 755 } 756 757 static void 758 free_rpc_portal_group(struct rpc_portal_group *pg) 759 { 760 free_rpc_portal_list(&pg->portal_list); 761 } 762 763 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 764 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 765 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 766 {"cpumask", offsetof(struct rpc_portal, cpumask), spdk_json_decode_string, true}, 767 }; 768 769 static int 770 decode_rpc_portal(const struct spdk_json_val *val, void *out) 771 { 772 struct rpc_portal *portal = out; 773 774 return spdk_json_decode_object(val, rpc_portal_decoders, 775 SPDK_COUNTOF(rpc_portal_decoders), 776 portal); 777 } 778 779 static int 780 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 781 { 782 struct rpc_portal_list *list = out; 783 784 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 785 sizeof(struct rpc_portal)); 786 } 787 788 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 789 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 790 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 791 }; 792 793 static void 794 spdk_rpc_add_portal_group(struct spdk_jsonrpc_request *request, 795 const struct spdk_json_val *params) 796 { 797 struct rpc_portal_group req = {}; 798 struct spdk_iscsi_portal_grp *pg = NULL; 799 struct spdk_iscsi_portal *portal; 800 struct spdk_json_write_ctx *w; 801 size_t i = 0; 802 int rc = -1; 803 804 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 805 SPDK_COUNTOF(rpc_portal_group_decoders), 806 &req)) { 807 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 808 goto out; 809 } 810 811 pg = spdk_iscsi_portal_grp_create(req.tag); 812 if (pg == NULL) { 813 SPDK_ERRLOG("portal_grp_create failed\n"); 814 goto out; 815 } 816 for (i = 0; i < req.portal_list.num_portals; i++) { 817 portal = spdk_iscsi_portal_create(req.portal_list.portals[i].host, 818 req.portal_list.portals[i].port, 819 req.portal_list.portals[i].cpumask); 820 if (portal == NULL) { 821 SPDK_ERRLOG("portal_create failed\n"); 822 goto out; 823 } 824 spdk_iscsi_portal_grp_add_portal(pg, portal); 825 } 826 827 rc = spdk_iscsi_portal_grp_open(pg); 828 if (rc != 0) { 829 SPDK_ERRLOG("portal_grp_open failed\n"); 830 goto out; 831 } 832 833 rc = spdk_iscsi_portal_grp_register(pg); 834 if (rc != 0) { 835 SPDK_ERRLOG("portal_grp_register failed\n"); 836 } 837 838 out: 839 if (rc == 0) { 840 w = spdk_jsonrpc_begin_result(request); 841 if (w != NULL) { 842 spdk_json_write_bool(w, true); 843 spdk_jsonrpc_end_result(request, w); 844 } 845 } else { 846 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 847 848 if (pg != NULL) { 849 spdk_iscsi_portal_grp_release(pg); 850 } 851 } 852 free_rpc_portal_group(&req); 853 } 854 SPDK_RPC_REGISTER("add_portal_group", spdk_rpc_add_portal_group, SPDK_RPC_RUNTIME) 855 856 struct rpc_delete_portal_group { 857 int32_t tag; 858 }; 859 860 static const struct spdk_json_object_decoder rpc_delete_portal_group_decoders[] = { 861 {"tag", offsetof(struct rpc_delete_portal_group, tag), spdk_json_decode_int32}, 862 }; 863 864 static void 865 spdk_rpc_delete_portal_group(struct spdk_jsonrpc_request *request, 866 const struct spdk_json_val *params) 867 { 868 struct rpc_delete_portal_group req = {}; 869 struct spdk_json_write_ctx *w; 870 struct spdk_iscsi_portal_grp *pg; 871 872 if (spdk_json_decode_object(params, rpc_delete_portal_group_decoders, 873 SPDK_COUNTOF(rpc_delete_portal_group_decoders), 874 &req)) { 875 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 876 goto invalid; 877 } 878 879 pg = spdk_iscsi_portal_grp_unregister(req.tag); 880 if (!pg) { 881 goto invalid; 882 } 883 884 spdk_iscsi_tgt_node_delete_map(pg, NULL); 885 spdk_iscsi_portal_grp_release(pg); 886 887 w = spdk_jsonrpc_begin_result(request); 888 if (w == NULL) { 889 return; 890 } 891 892 spdk_json_write_bool(w, true); 893 spdk_jsonrpc_end_result(request, w); 894 return; 895 896 invalid: 897 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 898 } 899 SPDK_RPC_REGISTER("delete_portal_group", spdk_rpc_delete_portal_group, SPDK_RPC_RUNTIME) 900 901 static void 902 spdk_rpc_get_iscsi_connections(struct spdk_jsonrpc_request *request, 903 const struct spdk_json_val *params) 904 { 905 struct spdk_json_write_ctx *w; 906 struct spdk_iscsi_conn *conns = g_conns_array; 907 int i; 908 uint16_t tsih; 909 910 if (params != NULL) { 911 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 912 "get_iscsi_connections requires no parameters"); 913 return; 914 } 915 916 w = spdk_jsonrpc_begin_result(request); 917 if (w == NULL) { 918 return; 919 } 920 921 spdk_json_write_array_begin(w); 922 923 for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) { 924 struct spdk_iscsi_conn *c = &conns[i]; 925 926 if (!c->is_valid) { 927 continue; 928 } 929 930 spdk_json_write_object_begin(w); 931 932 spdk_json_write_name(w, "id"); 933 spdk_json_write_int32(w, c->id); 934 935 spdk_json_write_name(w, "cid"); 936 spdk_json_write_int32(w, c->cid); 937 938 /* 939 * If we try to return data for a connection that has not 940 * logged in yet, the session will not be set. So in this 941 * case, return -1 for the tsih rather than segfaulting 942 * on the null c->sess. 943 */ 944 if (c->sess == NULL) { 945 tsih = -1; 946 } else { 947 tsih = c->sess->tsih; 948 } 949 spdk_json_write_name(w, "tsih"); 950 spdk_json_write_int32(w, tsih); 951 952 spdk_json_write_name(w, "lcore_id"); 953 spdk_json_write_int32(w, c->lcore); 954 955 spdk_json_write_name(w, "initiator_addr"); 956 spdk_json_write_string(w, c->initiator_addr); 957 958 spdk_json_write_name(w, "target_addr"); 959 spdk_json_write_string(w, c->target_addr); 960 961 spdk_json_write_name(w, "target_node_name"); 962 spdk_json_write_string(w, c->target_short_name); 963 964 spdk_json_write_object_end(w); 965 } 966 spdk_json_write_array_end(w); 967 968 spdk_jsonrpc_end_result(request, w); 969 } 970 SPDK_RPC_REGISTER("get_iscsi_connections", spdk_rpc_get_iscsi_connections, SPDK_RPC_RUNTIME) 971 972 struct rpc_target_lun { 973 char *name; 974 char *bdev_name; 975 int32_t lun_id; 976 }; 977 978 static void 979 free_rpc_target_lun(struct rpc_target_lun *req) 980 { 981 free(req->name); 982 free(req->bdev_name); 983 } 984 985 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 986 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 987 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 988 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 989 }; 990 991 static void 992 spdk_rpc_target_node_add_lun(struct spdk_jsonrpc_request *request, 993 const struct spdk_json_val *params) 994 { 995 struct rpc_target_lun req = {}; 996 struct spdk_json_write_ctx *w; 997 struct spdk_iscsi_tgt_node *target; 998 int rc; 999 1000 req.lun_id = -1; 1001 1002 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 1003 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 1004 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1005 goto invalid; 1006 } 1007 1008 target = spdk_iscsi_find_tgt_node(req.name); 1009 if (target == NULL) { 1010 SPDK_ERRLOG("target is not found\n"); 1011 goto invalid; 1012 } 1013 1014 rc = spdk_iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 1015 if (rc < 0) { 1016 SPDK_ERRLOG("add lun failed\n"); 1017 goto invalid; 1018 } 1019 1020 free_rpc_target_lun(&req); 1021 1022 w = spdk_jsonrpc_begin_result(request); 1023 if (w == NULL) { 1024 return; 1025 } 1026 1027 spdk_json_write_bool(w, true); 1028 spdk_jsonrpc_end_result(request, w); 1029 return; 1030 1031 invalid: 1032 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1033 "Invalid parameters"); 1034 free_rpc_target_lun(&req); 1035 } 1036 SPDK_RPC_REGISTER("target_node_add_lun", spdk_rpc_target_node_add_lun, SPDK_RPC_RUNTIME) 1037 1038 static void 1039 spdk_rpc_get_iscsi_global_params(struct spdk_jsonrpc_request *request, 1040 const struct spdk_json_val *params) 1041 { 1042 struct spdk_json_write_ctx *w; 1043 1044 if (params != NULL) { 1045 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1046 "get_iscsi_global_params requires no parameters"); 1047 return; 1048 } 1049 1050 w = spdk_jsonrpc_begin_result(request); 1051 if (w == NULL) { 1052 return; 1053 } 1054 1055 spdk_iscsi_opts_info_json(w); 1056 1057 spdk_jsonrpc_end_result(request, w); 1058 } 1059 SPDK_RPC_REGISTER("get_iscsi_global_params", spdk_rpc_get_iscsi_global_params, SPDK_RPC_RUNTIME) 1060