1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2a6dbe372Spaul luse * Copyright (C) 2016 Intel Corporation. All rights reserved. 336ac75b9SAlexey Marchuk * Copyright (c) 2018-2021 Mellanox Technologies LTD. All rights reserved. 497385af1SAlexey Marchuk * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5a54a6a26SSeth Howell */ 6a54a6a26SSeth Howell 7a54a6a26SSeth Howell #include "spdk/bdev.h" 8a54a6a26SSeth Howell #include "spdk/log.h" 9a54a6a26SSeth Howell #include "spdk/rpc.h" 10a54a6a26SSeth Howell #include "spdk/env.h" 11a54a6a26SSeth Howell #include "spdk/nvme.h" 12a54a6a26SSeth Howell #include "spdk/nvmf.h" 13a54a6a26SSeth Howell #include "spdk/string.h" 14a54a6a26SSeth Howell #include "spdk/util.h" 154cc04a12SShuhei Matsumoto #include "spdk/bit_array.h" 16e2d54380Skyuho.son #include "spdk/config.h" 17a54a6a26SSeth Howell 1844e2f510SSeth Howell #include "spdk_internal/assert.h" 19a54a6a26SSeth Howell 202167c68dSJan Kryl #include "nvmf_internal.h" 212167c68dSJan Kryl 22ecbceb22SMarcin Spiewak static int rpc_ana_state_parse(const char *str, enum spdk_nvme_ana_state *ana_state); 23ecbceb22SMarcin Spiewak 24a54a6a26SSeth Howell static int 25a54a6a26SSeth Howell json_write_hex_str(struct spdk_json_write_ctx *w, const void *data, size_t size) 26a54a6a26SSeth Howell { 27a54a6a26SSeth Howell static const char hex_char[16] = "0123456789ABCDEF"; 28a54a6a26SSeth Howell const uint8_t *buf = data; 29a54a6a26SSeth Howell char *str, *out; 30a54a6a26SSeth Howell int rc; 31a54a6a26SSeth Howell 32a54a6a26SSeth Howell str = malloc(size * 2 + 1); 33a54a6a26SSeth Howell if (str == NULL) { 34a54a6a26SSeth Howell return -1; 35a54a6a26SSeth Howell } 36a54a6a26SSeth Howell 37a54a6a26SSeth Howell out = str; 38a54a6a26SSeth Howell while (size--) { 39a54a6a26SSeth Howell unsigned byte = *buf++; 40a54a6a26SSeth Howell 41a54a6a26SSeth Howell out[0] = hex_char[(byte >> 4) & 0xF]; 42a54a6a26SSeth Howell out[1] = hex_char[byte & 0xF]; 43a54a6a26SSeth Howell 44a54a6a26SSeth Howell out += 2; 45a54a6a26SSeth Howell } 46a54a6a26SSeth Howell *out = '\0'; 47a54a6a26SSeth Howell 48a54a6a26SSeth Howell rc = spdk_json_write_string(w, str); 49a54a6a26SSeth Howell free(str); 50a54a6a26SSeth Howell 51a54a6a26SSeth Howell return rc; 52a54a6a26SSeth Howell } 53a54a6a26SSeth Howell 54a54a6a26SSeth Howell static int 55a54a6a26SSeth Howell hex_nybble_to_num(char c) 56a54a6a26SSeth Howell { 57a54a6a26SSeth Howell if (c >= '0' && c <= '9') { 58a54a6a26SSeth Howell return c - '0'; 59a54a6a26SSeth Howell } 60a54a6a26SSeth Howell 61a54a6a26SSeth Howell if (c >= 'a' && c <= 'f') { 62a54a6a26SSeth Howell return c - 'a' + 0xA; 63a54a6a26SSeth Howell } 64a54a6a26SSeth Howell 65a54a6a26SSeth Howell if (c >= 'A' && c <= 'F') { 66a54a6a26SSeth Howell return c - 'A' + 0xA; 67a54a6a26SSeth Howell } 68a54a6a26SSeth Howell 69a54a6a26SSeth Howell return -1; 70a54a6a26SSeth Howell } 71a54a6a26SSeth Howell 72a54a6a26SSeth Howell static int 73a54a6a26SSeth Howell hex_byte_to_num(const char *str) 74a54a6a26SSeth Howell { 75a54a6a26SSeth Howell int hi, lo; 76a54a6a26SSeth Howell 77a54a6a26SSeth Howell hi = hex_nybble_to_num(str[0]); 78a54a6a26SSeth Howell if (hi < 0) { 79a54a6a26SSeth Howell return hi; 80a54a6a26SSeth Howell } 81a54a6a26SSeth Howell 82a54a6a26SSeth Howell lo = hex_nybble_to_num(str[1]); 83a54a6a26SSeth Howell if (lo < 0) { 84a54a6a26SSeth Howell return lo; 85a54a6a26SSeth Howell } 86a54a6a26SSeth Howell 87a54a6a26SSeth Howell return hi * 16 + lo; 88a54a6a26SSeth Howell } 89a54a6a26SSeth Howell 90a54a6a26SSeth Howell static int 91a54a6a26SSeth Howell decode_hex_string_be(const char *str, uint8_t *out, size_t size) 92a54a6a26SSeth Howell { 93a54a6a26SSeth Howell size_t i; 94a54a6a26SSeth Howell 95a54a6a26SSeth Howell /* Decode a string in "ABCDEF012345" format to its binary representation */ 96a54a6a26SSeth Howell for (i = 0; i < size; i++) { 97a54a6a26SSeth Howell int num = hex_byte_to_num(str); 98a54a6a26SSeth Howell 99a54a6a26SSeth Howell if (num < 0) { 100a54a6a26SSeth Howell /* Invalid hex byte or end of string */ 101a54a6a26SSeth Howell return -1; 102a54a6a26SSeth Howell } 103a54a6a26SSeth Howell 104a54a6a26SSeth Howell out[i] = (uint8_t)num; 105a54a6a26SSeth Howell str += 2; 106a54a6a26SSeth Howell } 107a54a6a26SSeth Howell 108a54a6a26SSeth Howell if (i != size || *str != '\0') { 109a54a6a26SSeth Howell /* Length mismatch */ 110a54a6a26SSeth Howell return -1; 111a54a6a26SSeth Howell } 112a54a6a26SSeth Howell 113a54a6a26SSeth Howell return 0; 114a54a6a26SSeth Howell } 115a54a6a26SSeth Howell 116a54a6a26SSeth Howell static int 117a54a6a26SSeth Howell decode_ns_nguid(const struct spdk_json_val *val, void *out) 118a54a6a26SSeth Howell { 119a54a6a26SSeth Howell char *str = NULL; 120a54a6a26SSeth Howell int rc; 121a54a6a26SSeth Howell 122a54a6a26SSeth Howell rc = spdk_json_decode_string(val, &str); 123a54a6a26SSeth Howell if (rc == 0) { 124a54a6a26SSeth Howell /* 16-byte NGUID */ 125a54a6a26SSeth Howell rc = decode_hex_string_be(str, out, 16); 126a54a6a26SSeth Howell } 127a54a6a26SSeth Howell 128a54a6a26SSeth Howell free(str); 129a54a6a26SSeth Howell return rc; 130a54a6a26SSeth Howell } 131a54a6a26SSeth Howell 132a54a6a26SSeth Howell static int 133a54a6a26SSeth Howell decode_ns_eui64(const struct spdk_json_val *val, void *out) 134a54a6a26SSeth Howell { 135a54a6a26SSeth Howell char *str = NULL; 136a54a6a26SSeth Howell int rc; 137a54a6a26SSeth Howell 138a54a6a26SSeth Howell rc = spdk_json_decode_string(val, &str); 139a54a6a26SSeth Howell if (rc == 0) { 140a54a6a26SSeth Howell /* 8-byte EUI-64 */ 141a54a6a26SSeth Howell rc = decode_hex_string_be(str, out, 8); 142a54a6a26SSeth Howell } 143a54a6a26SSeth Howell 144a54a6a26SSeth Howell free(str); 145a54a6a26SSeth Howell return rc; 146a54a6a26SSeth Howell } 147a54a6a26SSeth Howell 148f8433aadSSeth Howell struct rpc_get_subsystem { 149dfafab22SJacek Kalwas char *nqn; 150f8433aadSSeth Howell char *tgt_name; 151f8433aadSSeth Howell }; 152f8433aadSSeth Howell 153f8433aadSSeth Howell static const struct spdk_json_object_decoder rpc_get_subsystem_decoders[] = { 154dfafab22SJacek Kalwas {"nqn", offsetof(struct rpc_get_subsystem, nqn), spdk_json_decode_string, true}, 155f8433aadSSeth Howell {"tgt_name", offsetof(struct rpc_get_subsystem, tgt_name), spdk_json_decode_string, true}, 156f8433aadSSeth Howell }; 157f8433aadSSeth Howell 158a54a6a26SSeth Howell static void 159a54a6a26SSeth Howell dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct spdk_nvmf_subsystem *subsystem) 160a54a6a26SSeth Howell { 161a54a6a26SSeth Howell struct spdk_nvmf_host *host; 162c79d4eefSJacek Kalwas struct spdk_nvmf_subsystem_listener *listener; 163a54a6a26SSeth Howell 164a54a6a26SSeth Howell spdk_json_write_object_begin(w); 165a54a6a26SSeth Howell 166a54a6a26SSeth Howell spdk_json_write_named_string(w, "nqn", spdk_nvmf_subsystem_get_nqn(subsystem)); 167a54a6a26SSeth Howell spdk_json_write_name(w, "subtype"); 168a54a6a26SSeth Howell if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) { 169a54a6a26SSeth Howell spdk_json_write_string(w, "NVMe"); 170a54a6a26SSeth Howell } else { 171a54a6a26SSeth Howell spdk_json_write_string(w, "Discovery"); 172a54a6a26SSeth Howell } 173a54a6a26SSeth Howell 174a54a6a26SSeth Howell spdk_json_write_named_array_begin(w, "listen_addresses"); 175a54a6a26SSeth Howell 176a54a6a26SSeth Howell for (listener = spdk_nvmf_subsystem_get_first_listener(subsystem); listener != NULL; 177a54a6a26SSeth Howell listener = spdk_nvmf_subsystem_get_next_listener(subsystem, listener)) { 178a54a6a26SSeth Howell const struct spdk_nvme_transport_id *trid; 179a54a6a26SSeth Howell 180c79d4eefSJacek Kalwas trid = spdk_nvmf_subsystem_listener_get_trid(listener); 181a54a6a26SSeth Howell 182a54a6a26SSeth Howell spdk_json_write_object_begin(w); 183f5260201SWojciech Panfil nvmf_transport_listen_dump_trid(trid, w); 184a54a6a26SSeth Howell spdk_json_write_object_end(w); 185a54a6a26SSeth Howell } 186a54a6a26SSeth Howell spdk_json_write_array_end(w); 187a54a6a26SSeth Howell 188a54a6a26SSeth Howell spdk_json_write_named_bool(w, "allow_any_host", 189a54a6a26SSeth Howell spdk_nvmf_subsystem_get_allow_any_host(subsystem)); 190a54a6a26SSeth Howell 191a54a6a26SSeth Howell spdk_json_write_named_array_begin(w, "hosts"); 192a54a6a26SSeth Howell 193a54a6a26SSeth Howell for (host = spdk_nvmf_subsystem_get_first_host(subsystem); host != NULL; 194a54a6a26SSeth Howell host = spdk_nvmf_subsystem_get_next_host(subsystem, host)) { 195a54a6a26SSeth Howell spdk_json_write_object_begin(w); 196a54a6a26SSeth Howell spdk_json_write_named_string(w, "nqn", spdk_nvmf_host_get_nqn(host)); 1973f4f8ad0SKonrad Sztyber if (host->dhchap_key != NULL) { 1983f4f8ad0SKonrad Sztyber spdk_json_write_named_string(w, "dhchap_key", 1993f4f8ad0SKonrad Sztyber spdk_key_get_name(host->dhchap_key)); 2003f4f8ad0SKonrad Sztyber } 201aa13730dSKonrad Sztyber if (host->dhchap_ctrlr_key != NULL) { 202aa13730dSKonrad Sztyber spdk_json_write_named_string(w, "dhchap_ctrlr_key", 203aa13730dSKonrad Sztyber spdk_key_get_name(host->dhchap_ctrlr_key)); 204aa13730dSKonrad Sztyber } 205a54a6a26SSeth Howell spdk_json_write_object_end(w); 206a54a6a26SSeth Howell } 207a54a6a26SSeth Howell spdk_json_write_array_end(w); 208a54a6a26SSeth Howell 209a54a6a26SSeth Howell if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) { 210a54a6a26SSeth Howell struct spdk_nvmf_ns *ns; 211a54a6a26SSeth Howell struct spdk_nvmf_ns_opts ns_opts; 212a54a6a26SSeth Howell uint32_t max_namespaces; 213a54a6a26SSeth Howell 214a54a6a26SSeth Howell spdk_json_write_named_string(w, "serial_number", spdk_nvmf_subsystem_get_sn(subsystem)); 215a54a6a26SSeth Howell 216a54a6a26SSeth Howell spdk_json_write_named_string(w, "model_number", spdk_nvmf_subsystem_get_mn(subsystem)); 217a54a6a26SSeth Howell 218a54a6a26SSeth Howell max_namespaces = spdk_nvmf_subsystem_get_max_namespaces(subsystem); 219a54a6a26SSeth Howell if (max_namespaces != 0) { 220a54a6a26SSeth Howell spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces); 221a54a6a26SSeth Howell } 222a54a6a26SSeth Howell 223be6a01efSJonathan Teh spdk_json_write_named_uint32(w, "min_cntlid", spdk_nvmf_subsystem_get_min_cntlid(subsystem)); 224be6a01efSJonathan Teh spdk_json_write_named_uint32(w, "max_cntlid", spdk_nvmf_subsystem_get_max_cntlid(subsystem)); 225be6a01efSJonathan Teh 226a54a6a26SSeth Howell spdk_json_write_named_array_begin(w, "namespaces"); 227a54a6a26SSeth Howell for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL; 228a54a6a26SSeth Howell ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) { 229a54a6a26SSeth Howell spdk_nvmf_ns_get_opts(ns, &ns_opts, sizeof(ns_opts)); 230a54a6a26SSeth Howell spdk_json_write_object_begin(w); 231a54a6a26SSeth Howell spdk_json_write_named_int32(w, "nsid", spdk_nvmf_ns_get_id(ns)); 232a54a6a26SSeth Howell spdk_json_write_named_string(w, "bdev_name", 233a54a6a26SSeth Howell spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns))); 234a54a6a26SSeth Howell /* NOTE: "name" is kept for compatibility only - new code should use bdev_name. */ 235a54a6a26SSeth Howell spdk_json_write_named_string(w, "name", 236a54a6a26SSeth Howell spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns))); 237a54a6a26SSeth Howell 238a54a6a26SSeth Howell if (!spdk_mem_all_zero(ns_opts.nguid, sizeof(ns_opts.nguid))) { 239a54a6a26SSeth Howell spdk_json_write_name(w, "nguid"); 240a54a6a26SSeth Howell json_write_hex_str(w, ns_opts.nguid, sizeof(ns_opts.nguid)); 241a54a6a26SSeth Howell } 242a54a6a26SSeth Howell 243a54a6a26SSeth Howell if (!spdk_mem_all_zero(ns_opts.eui64, sizeof(ns_opts.eui64))) { 244a54a6a26SSeth Howell spdk_json_write_name(w, "eui64"); 245a54a6a26SSeth Howell json_write_hex_str(w, ns_opts.eui64, sizeof(ns_opts.eui64)); 246a54a6a26SSeth Howell } 247a54a6a26SSeth Howell 24895a367d6SArtur Paszkiewicz if (!spdk_uuid_is_null(&ns_opts.uuid)) { 2498cffbe01SKonrad Sztyber spdk_json_write_named_uuid(w, "uuid", &ns_opts.uuid); 250a54a6a26SSeth Howell } 251a54a6a26SSeth Howell 252fb5650ceSAbhineet Pandey if (spdk_nvmf_subsystem_get_ana_reporting(subsystem)) { 253694fa34dSShuhei Matsumoto spdk_json_write_named_uint32(w, "anagrpid", ns_opts.anagrpid); 254694fa34dSShuhei Matsumoto } 255694fa34dSShuhei Matsumoto 256a54a6a26SSeth Howell spdk_json_write_object_end(w); 257a54a6a26SSeth Howell } 258a54a6a26SSeth Howell spdk_json_write_array_end(w); 259a54a6a26SSeth Howell } 260a54a6a26SSeth Howell spdk_json_write_object_end(w); 261a54a6a26SSeth Howell } 262a54a6a26SSeth Howell 263a54a6a26SSeth Howell static void 264e569a578SSeth Howell rpc_nvmf_get_subsystems(struct spdk_jsonrpc_request *request, 265a54a6a26SSeth Howell const struct spdk_json_val *params) 266a54a6a26SSeth Howell { 267f8433aadSSeth Howell struct rpc_get_subsystem req = { 0 }; 268a54a6a26SSeth Howell struct spdk_json_write_ctx *w; 269dfafab22SJacek Kalwas struct spdk_nvmf_subsystem *subsystem = NULL; 270a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 271a54a6a26SSeth Howell 272f8433aadSSeth Howell if (params) { 273f8433aadSSeth Howell if (spdk_json_decode_object(params, rpc_get_subsystem_decoders, 274f8433aadSSeth Howell SPDK_COUNTOF(rpc_get_subsystem_decoders), 275f8433aadSSeth Howell &req)) { 276f8433aadSSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 277f8433aadSSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 278a54a6a26SSeth Howell return; 279a54a6a26SSeth Howell } 280f8433aadSSeth Howell } 281a54a6a26SSeth Howell 282f8433aadSSeth Howell tgt = spdk_nvmf_get_tgt(req.tgt_name); 283a54a6a26SSeth Howell if (!tgt) { 284a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 285a54a6a26SSeth Howell "Unable to find a target."); 286f8433aadSSeth Howell free(req.tgt_name); 287dfafab22SJacek Kalwas free(req.nqn); 288a54a6a26SSeth Howell return; 289a54a6a26SSeth Howell } 290a54a6a26SSeth Howell 291dfafab22SJacek Kalwas if (req.nqn) { 292dfafab22SJacek Kalwas subsystem = spdk_nvmf_tgt_find_subsystem(tgt, req.nqn); 293dfafab22SJacek Kalwas if (!subsystem) { 294dfafab22SJacek Kalwas SPDK_ERRLOG("subsystem '%s' does not exist\n", req.nqn); 295dfafab22SJacek Kalwas spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 296dfafab22SJacek Kalwas free(req.tgt_name); 297dfafab22SJacek Kalwas free(req.nqn); 298dfafab22SJacek Kalwas return; 299dfafab22SJacek Kalwas } 300dfafab22SJacek Kalwas } 301dfafab22SJacek Kalwas 302a54a6a26SSeth Howell w = spdk_jsonrpc_begin_result(request); 303a54a6a26SSeth Howell spdk_json_write_array_begin(w); 304dfafab22SJacek Kalwas 305dfafab22SJacek Kalwas if (subsystem) { 306a54a6a26SSeth Howell dump_nvmf_subsystem(w, subsystem); 307dfafab22SJacek Kalwas } else { 308dfafab22SJacek Kalwas for (subsystem = spdk_nvmf_subsystem_get_first(tgt); subsystem != NULL; 309dfafab22SJacek Kalwas subsystem = spdk_nvmf_subsystem_get_next(subsystem)) { 310dfafab22SJacek Kalwas dump_nvmf_subsystem(w, subsystem); 311a54a6a26SSeth Howell } 312dfafab22SJacek Kalwas } 313dfafab22SJacek Kalwas 314a54a6a26SSeth Howell spdk_json_write_array_end(w); 315a54a6a26SSeth Howell spdk_jsonrpc_end_result(request, w); 316f8433aadSSeth Howell free(req.tgt_name); 317dfafab22SJacek Kalwas free(req.nqn); 318a54a6a26SSeth Howell } 319e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_get_subsystems", rpc_nvmf_get_subsystems, SPDK_RPC_RUNTIME) 320a54a6a26SSeth Howell 321a54a6a26SSeth Howell struct rpc_subsystem_create { 322a54a6a26SSeth Howell char *nqn; 323a54a6a26SSeth Howell char *serial_number; 324a54a6a26SSeth Howell char *model_number; 325f8433aadSSeth Howell char *tgt_name; 326a54a6a26SSeth Howell uint32_t max_namespaces; 327a54a6a26SSeth Howell bool allow_any_host; 3281da94ed7SShuhei Matsumoto bool ana_reporting; 329be6a01efSJonathan Teh uint16_t min_cntlid; 330be6a01efSJonathan Teh uint16_t max_cntlid; 331c7feb85dSHaoqian He uint64_t max_discard_size_kib; 332c7feb85dSHaoqian He uint64_t max_write_zeroes_size_kib; 33360241941SKarl Bonde Torp bool passthrough; 334a54a6a26SSeth Howell }; 335a54a6a26SSeth Howell 336a54a6a26SSeth Howell static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = { 337a54a6a26SSeth Howell {"nqn", offsetof(struct rpc_subsystem_create, nqn), spdk_json_decode_string}, 338a54a6a26SSeth Howell {"serial_number", offsetof(struct rpc_subsystem_create, serial_number), spdk_json_decode_string, true}, 339a54a6a26SSeth Howell {"model_number", offsetof(struct rpc_subsystem_create, model_number), spdk_json_decode_string, true}, 340f8433aadSSeth Howell {"tgt_name", offsetof(struct rpc_subsystem_create, tgt_name), spdk_json_decode_string, true}, 341a54a6a26SSeth Howell {"max_namespaces", offsetof(struct rpc_subsystem_create, max_namespaces), spdk_json_decode_uint32, true}, 342a54a6a26SSeth Howell {"allow_any_host", offsetof(struct rpc_subsystem_create, allow_any_host), spdk_json_decode_bool, true}, 3431da94ed7SShuhei Matsumoto {"ana_reporting", offsetof(struct rpc_subsystem_create, ana_reporting), spdk_json_decode_bool, true}, 344be6a01efSJonathan Teh {"min_cntlid", offsetof(struct rpc_subsystem_create, min_cntlid), spdk_json_decode_uint16, true}, 345be6a01efSJonathan Teh {"max_cntlid", offsetof(struct rpc_subsystem_create, max_cntlid), spdk_json_decode_uint16, true}, 346c7feb85dSHaoqian He {"max_discard_size_kib", offsetof(struct rpc_subsystem_create, max_discard_size_kib), spdk_json_decode_uint64, true}, 347c7feb85dSHaoqian He {"max_write_zeroes_size_kib", offsetof(struct rpc_subsystem_create, max_write_zeroes_size_kib), spdk_json_decode_uint64, true}, 34860241941SKarl Bonde Torp {"passthrough", offsetof(struct rpc_subsystem_create, passthrough), spdk_json_decode_bool, true}, 349a54a6a26SSeth Howell }; 350a54a6a26SSeth Howell 351a54a6a26SSeth Howell static void 352e569a578SSeth Howell rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem, 353a54a6a26SSeth Howell void *cb_arg, int status) 354a54a6a26SSeth Howell { 355a54a6a26SSeth Howell struct spdk_jsonrpc_request *request = cb_arg; 356a54a6a26SSeth Howell 357c29247e1SAlexey Marchuk if (!status) { 358d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 359c29247e1SAlexey Marchuk } else { 360c29247e1SAlexey Marchuk spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 361c29247e1SAlexey Marchuk "Subsystem %s start failed", 362c29247e1SAlexey Marchuk subsystem->subnqn); 36397385af1SAlexey Marchuk spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 364c29247e1SAlexey Marchuk } 365a54a6a26SSeth Howell } 366a54a6a26SSeth Howell 367a54a6a26SSeth Howell static void 368e569a578SSeth Howell rpc_nvmf_create_subsystem(struct spdk_jsonrpc_request *request, 369a54a6a26SSeth Howell const struct spdk_json_val *params) 370a54a6a26SSeth Howell { 371a54a6a26SSeth Howell struct rpc_subsystem_create *req; 372c29247e1SAlexey Marchuk struct spdk_nvmf_subsystem *subsystem = NULL; 373a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 374c29247e1SAlexey Marchuk int rc = -1; 375a54a6a26SSeth Howell 376a54a6a26SSeth Howell req = calloc(1, sizeof(*req)); 377a54a6a26SSeth Howell if (!req) { 378c29247e1SAlexey Marchuk SPDK_ERRLOG("Memory allocation failed\n"); 379c29247e1SAlexey Marchuk spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 380c29247e1SAlexey Marchuk "Memory allocation failed"); 381c29247e1SAlexey Marchuk return; 382a54a6a26SSeth Howell } 383be6a01efSJonathan Teh req->min_cntlid = NVMF_MIN_CNTLID; 384be6a01efSJonathan Teh req->max_cntlid = NVMF_MAX_CNTLID; 385a54a6a26SSeth Howell 386a54a6a26SSeth Howell if (spdk_json_decode_object(params, rpc_subsystem_create_decoders, 387a54a6a26SSeth Howell SPDK_COUNTOF(rpc_subsystem_create_decoders), 388a54a6a26SSeth Howell req)) { 389a54a6a26SSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 390c29247e1SAlexey Marchuk spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 391c29247e1SAlexey Marchuk goto cleanup; 392a54a6a26SSeth Howell } 393a54a6a26SSeth Howell 394f8433aadSSeth Howell tgt = spdk_nvmf_get_tgt(req->tgt_name); 395a54a6a26SSeth Howell if (!tgt) { 396c29247e1SAlexey Marchuk SPDK_ERRLOG("Unable to find target %s\n", req->tgt_name); 397c29247e1SAlexey Marchuk spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 398c29247e1SAlexey Marchuk "Unable to find target %s", req->tgt_name); 399c29247e1SAlexey Marchuk goto cleanup; 400a54a6a26SSeth Howell } 401a54a6a26SSeth Howell 402a54a6a26SSeth Howell subsystem = spdk_nvmf_subsystem_create(tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME, 403a54a6a26SSeth Howell req->max_namespaces); 404a54a6a26SSeth Howell if (!subsystem) { 405c29247e1SAlexey Marchuk SPDK_ERRLOG("Unable to create subsystem %s\n", req->nqn); 406c29247e1SAlexey Marchuk spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 407c29247e1SAlexey Marchuk "Unable to create subsystem %s", req->nqn); 408c29247e1SAlexey Marchuk goto cleanup; 409a54a6a26SSeth Howell } 410a54a6a26SSeth Howell 411a54a6a26SSeth Howell if (req->serial_number) { 412a54a6a26SSeth Howell if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) { 413a54a6a26SSeth Howell SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number); 414c29247e1SAlexey Marchuk spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 415c29247e1SAlexey Marchuk "Invalid SN %s", req->serial_number); 416c29247e1SAlexey Marchuk goto cleanup; 417a54a6a26SSeth Howell } 418a54a6a26SSeth Howell } 419a54a6a26SSeth Howell 420a54a6a26SSeth Howell if (req->model_number) { 421a54a6a26SSeth Howell if (spdk_nvmf_subsystem_set_mn(subsystem, req->model_number)) { 422a54a6a26SSeth Howell SPDK_ERRLOG("Subsystem %s: invalid model number '%s'\n", req->nqn, req->model_number); 423c29247e1SAlexey Marchuk spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 424c29247e1SAlexey Marchuk "Invalid MN %s", req->model_number); 425c29247e1SAlexey Marchuk goto cleanup; 426a54a6a26SSeth Howell } 427a54a6a26SSeth Howell } 428a54a6a26SSeth Howell 429a54a6a26SSeth Howell spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host); 430a54a6a26SSeth Howell 4311da94ed7SShuhei Matsumoto spdk_nvmf_subsystem_set_ana_reporting(subsystem, req->ana_reporting); 4321da94ed7SShuhei Matsumoto 433096538c8SAbhineet Pandey if (spdk_nvmf_subsystem_set_cntlid_range(subsystem, req->min_cntlid, req->max_cntlid)) { 434be6a01efSJonathan Teh SPDK_ERRLOG("Subsystem %s: invalid cntlid range [%u-%u]\n", req->nqn, req->min_cntlid, 435be6a01efSJonathan Teh req->max_cntlid); 436be6a01efSJonathan Teh spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 437be6a01efSJonathan Teh "Invalid cntlid range [%u-%u]", req->min_cntlid, req->max_cntlid); 438be6a01efSJonathan Teh goto cleanup; 439be6a01efSJonathan Teh } 440be6a01efSJonathan Teh 441c7feb85dSHaoqian He subsystem->max_discard_size_kib = req->max_discard_size_kib; 442c7feb85dSHaoqian He 443c7feb85dSHaoqian He /* max_write_zeroes_size_kib must be aligned to 4 and power of 2 */ 444c7feb85dSHaoqian He if (req->max_write_zeroes_size_kib == 0 || (req->max_write_zeroes_size_kib > 2 && 445c7feb85dSHaoqian He spdk_u64_is_pow2(req->max_write_zeroes_size_kib))) { 446c7feb85dSHaoqian He subsystem->max_write_zeroes_size_kib = req->max_write_zeroes_size_kib; 447c7feb85dSHaoqian He } else { 448c7feb85dSHaoqian He SPDK_ERRLOG("Subsystem %s: invalid max_write_zeroes_size_kib %"PRIu64"\n", req->nqn, 449c7feb85dSHaoqian He req->max_write_zeroes_size_kib); 450c7feb85dSHaoqian He spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 4519b143bcaSPierre Lestringant "Invalid max_write_zeroes_size_kib %"PRIu64, req->max_write_zeroes_size_kib); 452c7feb85dSHaoqian He goto cleanup; 453c7feb85dSHaoqian He } 454c7feb85dSHaoqian He 45560241941SKarl Bonde Torp subsystem->passthrough = req->passthrough; 45660241941SKarl Bonde Torp 457c29247e1SAlexey Marchuk rc = spdk_nvmf_subsystem_start(subsystem, 458e569a578SSeth Howell rpc_nvmf_subsystem_started, 459a54a6a26SSeth Howell request); 46097385af1SAlexey Marchuk if (rc) { 46197385af1SAlexey Marchuk spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 46297385af1SAlexey Marchuk "Failed to start subsystem"); 46397385af1SAlexey Marchuk } 464a54a6a26SSeth Howell 465c29247e1SAlexey Marchuk cleanup: 466a54a6a26SSeth Howell free(req->nqn); 467f8433aadSSeth Howell free(req->tgt_name); 468a54a6a26SSeth Howell free(req->serial_number); 469a54a6a26SSeth Howell free(req->model_number); 470a54a6a26SSeth Howell free(req); 471c29247e1SAlexey Marchuk 472c29247e1SAlexey Marchuk if (rc && subsystem) { 47397385af1SAlexey Marchuk spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL); 474c29247e1SAlexey Marchuk } 475a54a6a26SSeth Howell } 476e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_create_subsystem", rpc_nvmf_create_subsystem, SPDK_RPC_RUNTIME) 477a54a6a26SSeth Howell 478a54a6a26SSeth Howell struct rpc_delete_subsystem { 479a54a6a26SSeth Howell char *nqn; 480f8433aadSSeth Howell char *tgt_name; 481a54a6a26SSeth Howell }; 482a54a6a26SSeth Howell 483a54a6a26SSeth Howell static void 484a54a6a26SSeth Howell free_rpc_delete_subsystem(struct rpc_delete_subsystem *r) 485a54a6a26SSeth Howell { 486a54a6a26SSeth Howell free(r->nqn); 487f8433aadSSeth Howell free(r->tgt_name); 488a54a6a26SSeth Howell } 489a54a6a26SSeth Howell 4908dd1cd21SBen Walker static void 4918dd1cd21SBen Walker rpc_nvmf_subsystem_destroy_complete_cb(void *cb_arg) 49297385af1SAlexey Marchuk { 49397385af1SAlexey Marchuk struct spdk_jsonrpc_request *request = cb_arg; 49497385af1SAlexey Marchuk 49597385af1SAlexey Marchuk spdk_jsonrpc_send_bool_response(request, true); 49697385af1SAlexey Marchuk } 49797385af1SAlexey Marchuk 498a54a6a26SSeth Howell static void 499e569a578SSeth Howell rpc_nvmf_subsystem_stopped(struct spdk_nvmf_subsystem *subsystem, 500a54a6a26SSeth Howell void *cb_arg, int status) 501a54a6a26SSeth Howell { 502a54a6a26SSeth Howell struct spdk_jsonrpc_request *request = cb_arg; 50397385af1SAlexey Marchuk int rc; 504a54a6a26SSeth Howell 5059cb21ad6SSeth Howell nvmf_subsystem_remove_all_listeners(subsystem, true); 50697385af1SAlexey Marchuk rc = spdk_nvmf_subsystem_destroy(subsystem, rpc_nvmf_subsystem_destroy_complete_cb, request); 50797385af1SAlexey Marchuk if (rc) { 50897385af1SAlexey Marchuk if (rc == -EINPROGRESS) { 50997385af1SAlexey Marchuk /* response will be sent in completion callback */ 51097385af1SAlexey Marchuk return; 51197385af1SAlexey Marchuk } else { 51297385af1SAlexey Marchuk SPDK_ERRLOG("Subsystem destruction failed, rc %d\n", rc); 51397385af1SAlexey Marchuk spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 51497385af1SAlexey Marchuk "Subsystem destruction failed, rc %d", rc); 51597385af1SAlexey Marchuk return; 51697385af1SAlexey Marchuk } 51797385af1SAlexey Marchuk } 518d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 519a54a6a26SSeth Howell } 520a54a6a26SSeth Howell 521a54a6a26SSeth Howell static const struct spdk_json_object_decoder rpc_delete_subsystem_decoders[] = { 522a54a6a26SSeth Howell {"nqn", offsetof(struct rpc_delete_subsystem, nqn), spdk_json_decode_string}, 523f8433aadSSeth Howell {"tgt_name", offsetof(struct rpc_delete_subsystem, tgt_name), spdk_json_decode_string, true}, 524a54a6a26SSeth Howell }; 525a54a6a26SSeth Howell 526a54a6a26SSeth Howell static void 527e569a578SSeth Howell rpc_nvmf_delete_subsystem(struct spdk_jsonrpc_request *request, 528a54a6a26SSeth Howell const struct spdk_json_val *params) 529a54a6a26SSeth Howell { 530f8433aadSSeth Howell struct rpc_delete_subsystem req = { 0 }; 531a54a6a26SSeth Howell struct spdk_nvmf_subsystem *subsystem; 532a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 5338ff8bf07SSeth Howell int rc; 534a54a6a26SSeth Howell 535a54a6a26SSeth Howell if (spdk_json_decode_object(params, rpc_delete_subsystem_decoders, 536a54a6a26SSeth Howell SPDK_COUNTOF(rpc_delete_subsystem_decoders), 537a54a6a26SSeth Howell &req)) { 538a54a6a26SSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 539a54a6a26SSeth Howell goto invalid; 540a54a6a26SSeth Howell } 541a54a6a26SSeth Howell 542a54a6a26SSeth Howell if (req.nqn == NULL) { 543a54a6a26SSeth Howell SPDK_ERRLOG("missing name param\n"); 544a54a6a26SSeth Howell goto invalid; 545a54a6a26SSeth Howell } 546a54a6a26SSeth Howell 547f8433aadSSeth Howell tgt = spdk_nvmf_get_tgt(req.tgt_name); 548a54a6a26SSeth Howell if (!tgt) { 549a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 550a54a6a26SSeth Howell "Unable to find a target."); 551a54a6a26SSeth Howell goto invalid_custom_response; 552a54a6a26SSeth Howell } 553a54a6a26SSeth Howell 554a54a6a26SSeth Howell subsystem = spdk_nvmf_tgt_find_subsystem(tgt, req.nqn); 555a54a6a26SSeth Howell if (!subsystem) { 556a54a6a26SSeth Howell goto invalid; 557a54a6a26SSeth Howell } 558a54a6a26SSeth Howell 559a54a6a26SSeth Howell free_rpc_delete_subsystem(&req); 560a54a6a26SSeth Howell 5618ff8bf07SSeth Howell rc = spdk_nvmf_subsystem_stop(subsystem, 562e569a578SSeth Howell rpc_nvmf_subsystem_stopped, 563a54a6a26SSeth Howell request); 5648ff8bf07SSeth Howell if (rc == -EBUSY) { 5658ff8bf07SSeth Howell SPDK_ERRLOG("Subsystem currently in another state change try again later.\n"); 5668ff8bf07SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 5678ff8bf07SSeth Howell "Subsystem currently in another state change try again later."); 5688ff8bf07SSeth Howell } else if (rc != 0) { 5698ff8bf07SSeth Howell SPDK_ERRLOG("Unable to change state on subsystem. rc=%d\n", rc); 5708ff8bf07SSeth Howell spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 5718ff8bf07SSeth Howell "Unable to change state on subsystem. rc=%d", rc); 5728ff8bf07SSeth Howell } 573a54a6a26SSeth Howell 574a54a6a26SSeth Howell return; 575a54a6a26SSeth Howell 576a54a6a26SSeth Howell invalid: 577a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 578a54a6a26SSeth Howell invalid_custom_response: 579a54a6a26SSeth Howell free_rpc_delete_subsystem(&req); 580a54a6a26SSeth Howell } 581e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_delete_subsystem", rpc_nvmf_delete_subsystem, SPDK_RPC_RUNTIME) 582a54a6a26SSeth Howell 583a54a6a26SSeth Howell struct rpc_listen_address { 5848ee34f93SJim Harris char *trtype; 585a54a6a26SSeth Howell char *adrfam; 586a54a6a26SSeth Howell char *traddr; 587a54a6a26SSeth Howell char *trsvcid; 588a54a6a26SSeth Howell }; 589a54a6a26SSeth Howell 590a54a6a26SSeth Howell static const struct spdk_json_object_decoder rpc_listen_address_decoders[] = { 5918ee34f93SJim Harris {"trtype", offsetof(struct rpc_listen_address, trtype), spdk_json_decode_string, true}, 592a54a6a26SSeth Howell {"adrfam", offsetof(struct rpc_listen_address, adrfam), spdk_json_decode_string, true}, 593a54a6a26SSeth Howell {"traddr", offsetof(struct rpc_listen_address, traddr), spdk_json_decode_string}, 5949a1cf1c5SJacek Kalwas {"trsvcid", offsetof(struct rpc_listen_address, trsvcid), spdk_json_decode_string, true}, 595a54a6a26SSeth Howell }; 596a54a6a26SSeth Howell 597a54a6a26SSeth Howell static int 598a54a6a26SSeth Howell decode_rpc_listen_address(const struct spdk_json_val *val, void *out) 599a54a6a26SSeth Howell { 600a54a6a26SSeth Howell struct rpc_listen_address *req = (struct rpc_listen_address *)out; 601b93e775bSJacek Kalwas 602e43b1b86SKonrad Sztyber return spdk_json_decode_object(val, rpc_listen_address_decoders, 603e43b1b86SKonrad Sztyber SPDK_COUNTOF(rpc_listen_address_decoders), req); 604a54a6a26SSeth Howell } 605a54a6a26SSeth Howell 606a54a6a26SSeth Howell static void 607a54a6a26SSeth Howell free_rpc_listen_address(struct rpc_listen_address *r) 608a54a6a26SSeth Howell { 6098ee34f93SJim Harris free(r->trtype); 610a54a6a26SSeth Howell free(r->adrfam); 611a54a6a26SSeth Howell free(r->traddr); 612a54a6a26SSeth Howell free(r->trsvcid); 613a54a6a26SSeth Howell } 614a54a6a26SSeth Howell 615a54a6a26SSeth Howell enum nvmf_rpc_listen_op { 616a54a6a26SSeth Howell NVMF_RPC_LISTEN_ADD, 617a54a6a26SSeth Howell NVMF_RPC_LISTEN_REMOVE, 618c8cb51d4SShuhei Matsumoto NVMF_RPC_LISTEN_SET_ANA_STATE, 619a54a6a26SSeth Howell }; 620a54a6a26SSeth Howell 621a54a6a26SSeth Howell struct nvmf_rpc_listener_ctx { 622a54a6a26SSeth Howell char *nqn; 623f8433aadSSeth Howell char *tgt_name; 624a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 625d1b0d2cbSSeth Howell struct spdk_nvmf_transport *transport; 626a54a6a26SSeth Howell struct spdk_nvmf_subsystem *subsystem; 627a54a6a26SSeth Howell struct rpc_listen_address address; 628c8cb51d4SShuhei Matsumoto char *ana_state_str; 629c8cb51d4SShuhei Matsumoto enum spdk_nvme_ana_state ana_state; 6306d716c47SShuhei Matsumoto uint32_t anagrpid; 631a54a6a26SSeth Howell 632a54a6a26SSeth Howell struct spdk_jsonrpc_request *request; 633a54a6a26SSeth Howell struct spdk_nvme_transport_id trid; 634a54a6a26SSeth Howell enum nvmf_rpc_listen_op op; 635a54a6a26SSeth Howell bool response_sent; 63687a062e6SJacek Kalwas struct spdk_nvmf_listen_opts opts; 6377662387cSKrzysztof Karas 638248c547dSKarl Bonde Torp /* Hole at bytes 705-711 */ 639248c547dSKarl Bonde Torp uint8_t reserved1[7]; 640248c547dSKarl Bonde Torp 641248c547dSKarl Bonde Torp /* Additional options for listener creation. 642248c547dSKarl Bonde Torp * Must be 8-byte aligned. */ 6437662387cSKrzysztof Karas struct spdk_nvmf_listener_opts listener_opts; 644a54a6a26SSeth Howell }; 645a54a6a26SSeth Howell 646a54a6a26SSeth Howell static const struct spdk_json_object_decoder nvmf_rpc_listener_decoder[] = { 647a54a6a26SSeth Howell {"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string}, 648a54a6a26SSeth Howell {"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address}, 649f8433aadSSeth Howell {"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true}, 6507662387cSKrzysztof Karas {"secure_channel", offsetof(struct nvmf_rpc_listener_ctx, listener_opts.secure_channel), spdk_json_decode_bool, true}, 651ecbceb22SMarcin Spiewak {"ana_state", offsetof(struct nvmf_rpc_listener_ctx, ana_state_str), spdk_json_decode_string, true}, 652248c547dSKarl Bonde Torp {"sock_impl", offsetof(struct nvmf_rpc_listener_ctx, listener_opts.sock_impl), spdk_json_decode_string, true}, 653a54a6a26SSeth Howell }; 654a54a6a26SSeth Howell 655a54a6a26SSeth Howell static void 656a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(struct nvmf_rpc_listener_ctx *ctx) 657a54a6a26SSeth Howell { 658a54a6a26SSeth Howell free(ctx->nqn); 659f8433aadSSeth Howell free(ctx->tgt_name); 660a54a6a26SSeth Howell free_rpc_listen_address(&ctx->address); 661c8cb51d4SShuhei Matsumoto free(ctx->ana_state_str); 662a54a6a26SSeth Howell free(ctx); 663a54a6a26SSeth Howell } 664a54a6a26SSeth Howell 665a54a6a26SSeth Howell static void 666a54a6a26SSeth Howell nvmf_rpc_listen_resumed(struct spdk_nvmf_subsystem *subsystem, 667a54a6a26SSeth Howell void *cb_arg, int status) 668a54a6a26SSeth Howell { 669a54a6a26SSeth Howell struct nvmf_rpc_listener_ctx *ctx = cb_arg; 670a54a6a26SSeth Howell struct spdk_jsonrpc_request *request; 671a54a6a26SSeth Howell 672a54a6a26SSeth Howell request = ctx->request; 673a54a6a26SSeth Howell if (ctx->response_sent) { 674a54a6a26SSeth Howell /* If an error occurred, the response has already been sent. */ 675a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 676a54a6a26SSeth Howell return; 677a54a6a26SSeth Howell } 678a54a6a26SSeth Howell 679a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 680a54a6a26SSeth Howell 681d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 682a54a6a26SSeth Howell } 683a54a6a26SSeth Howell 684a54a6a26SSeth Howell static void 6856fc8c8c2SBen Walker nvmf_rpc_subsystem_listen(void *cb_arg, int status) 6866fc8c8c2SBen Walker { 6876fc8c8c2SBen Walker struct nvmf_rpc_listener_ctx *ctx = cb_arg; 6886fc8c8c2SBen Walker 6896fc8c8c2SBen Walker if (status) { 6906fc8c8c2SBen Walker /* Destroy the listener that we just created. Ignore the error code because 6916fc8c8c2SBen Walker * the RPC is failing already anyway. */ 6926fc8c8c2SBen Walker spdk_nvmf_tgt_stop_listen(ctx->tgt, &ctx->trid); 6936fc8c8c2SBen Walker 6946fc8c8c2SBen Walker spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 6956fc8c8c2SBen Walker "Invalid parameters"); 6966fc8c8c2SBen Walker ctx->response_sent = true; 6976fc8c8c2SBen Walker } 6986fc8c8c2SBen Walker 6996fc8c8c2SBen Walker if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) { 7006fc8c8c2SBen Walker if (!ctx->response_sent) { 701c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 702c8cb51d4SShuhei Matsumoto "Internal error"); 7036fc8c8c2SBen Walker } 7046fc8c8c2SBen Walker nvmf_rpc_listener_ctx_free(ctx); 7056fc8c8c2SBen Walker /* Can't really do anything to recover here - subsystem will remain paused. */ 7066fc8c8c2SBen Walker } 7076fc8c8c2SBen Walker } 708d1b0d2cbSSeth Howell static void 709d1b0d2cbSSeth Howell nvmf_rpc_stop_listen_async_done(void *cb_arg, int status) 710d1b0d2cbSSeth Howell { 711d1b0d2cbSSeth Howell struct nvmf_rpc_listener_ctx *ctx = cb_arg; 712d1b0d2cbSSeth Howell 713d1b0d2cbSSeth Howell if (status) { 714c8cb51d4SShuhei Matsumoto SPDK_ERRLOG("Unable to stop listener.\n"); 715d1b0d2cbSSeth Howell spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 716c8cb51d4SShuhei Matsumoto "error stopping listener: %d", status); 717d1b0d2cbSSeth Howell ctx->response_sent = true; 718d1b0d2cbSSeth Howell } 719d1b0d2cbSSeth Howell 720d1b0d2cbSSeth Howell if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) { 721d1b0d2cbSSeth Howell if (!ctx->response_sent) { 722c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 723c8cb51d4SShuhei Matsumoto "Internal error"); 724c8cb51d4SShuhei Matsumoto } 725c8cb51d4SShuhei Matsumoto nvmf_rpc_listener_ctx_free(ctx); 726c8cb51d4SShuhei Matsumoto /* Can't really do anything to recover here - subsystem will remain paused. */ 727c8cb51d4SShuhei Matsumoto } 728c8cb51d4SShuhei Matsumoto } 729c8cb51d4SShuhei Matsumoto 730c8cb51d4SShuhei Matsumoto static void 731c8cb51d4SShuhei Matsumoto nvmf_rpc_set_ana_state_done(void *cb_arg, int status) 732c8cb51d4SShuhei Matsumoto { 733c8cb51d4SShuhei Matsumoto struct nvmf_rpc_listener_ctx *ctx = cb_arg; 734c8cb51d4SShuhei Matsumoto 735c8cb51d4SShuhei Matsumoto if (status) { 736c8cb51d4SShuhei Matsumoto SPDK_ERRLOG("Unable to set ANA state.\n"); 737c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 738c8cb51d4SShuhei Matsumoto "error setting ANA state: %d", status); 739c8cb51d4SShuhei Matsumoto ctx->response_sent = true; 740c8cb51d4SShuhei Matsumoto } 741c8cb51d4SShuhei Matsumoto 742c8cb51d4SShuhei Matsumoto if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) { 743c8cb51d4SShuhei Matsumoto if (!ctx->response_sent) { 744c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 745c8cb51d4SShuhei Matsumoto "Internal error"); 746d1b0d2cbSSeth Howell } 747d1b0d2cbSSeth Howell nvmf_rpc_listener_ctx_free(ctx); 748d1b0d2cbSSeth Howell /* Can't really do anything to recover here - subsystem will remain paused. */ 749d1b0d2cbSSeth Howell } 750d1b0d2cbSSeth Howell } 7516fc8c8c2SBen Walker 7526fc8c8c2SBen Walker static void 753c40f35b7SBen Walker nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem, 754c40f35b7SBen Walker void *cb_arg, int status) 755a54a6a26SSeth Howell { 756a54a6a26SSeth Howell struct nvmf_rpc_listener_ctx *ctx = cb_arg; 757c40f35b7SBen Walker int rc; 758a54a6a26SSeth Howell 75951ed4866SJacek Kalwas switch (ctx->op) { 76051ed4866SJacek Kalwas case NVMF_RPC_LISTEN_ADD: 761ee9e3438SJacek Kalwas if (nvmf_subsystem_find_listener(subsystem, &ctx->trid)) { 762ee9e3438SJacek Kalwas SPDK_ERRLOG("Listener already exists\n"); 7635d5e4d33SSlawomir Ptak spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 7645d5e4d33SSlawomir Ptak "Invalid parameters"); 7655d5e4d33SSlawomir Ptak ctx->response_sent = true; 76651ed4866SJacek Kalwas break; 7676fc8c8c2SBen Walker } 7686fc8c8c2SBen Walker 76951ed4866SJacek Kalwas rc = spdk_nvmf_tgt_listen_ext(ctx->tgt, &ctx->trid, &ctx->opts); 77051ed4866SJacek Kalwas if (rc) { 771a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 772a54a6a26SSeth Howell "Invalid parameters"); 773a54a6a26SSeth Howell ctx->response_sent = true; 77451ed4866SJacek Kalwas break; 775a54a6a26SSeth Howell } 77651ed4866SJacek Kalwas 77751ed4866SJacek Kalwas spdk_nvmf_subsystem_add_listener_ext(ctx->subsystem, &ctx->trid, nvmf_rpc_subsystem_listen, ctx, 77851ed4866SJacek Kalwas &ctx->listener_opts); 779d1b0d2cbSSeth Howell return; 78051ed4866SJacek Kalwas case NVMF_RPC_LISTEN_REMOVE: 78151ed4866SJacek Kalwas rc = spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid); 78251ed4866SJacek Kalwas if (rc) { 783f209637cSAlexey Marchuk SPDK_ERRLOG("Unable to remove listener, rc %d\n", rc); 784f209637cSAlexey Marchuk spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 785f209637cSAlexey Marchuk "Invalid parameters"); 786f209637cSAlexey Marchuk ctx->response_sent = true; 78751ed4866SJacek Kalwas break; 78851ed4866SJacek Kalwas } 78951ed4866SJacek Kalwas 79051ed4866SJacek Kalwas spdk_nvmf_transport_stop_listen_async(ctx->transport, &ctx->trid, subsystem, 79151ed4866SJacek Kalwas nvmf_rpc_stop_listen_async_done, ctx); 79251ed4866SJacek Kalwas return; 79351ed4866SJacek Kalwas case NVMF_RPC_LISTEN_SET_ANA_STATE: 794fb5650ceSAbhineet Pandey spdk_nvmf_subsystem_set_ana_state(subsystem, &ctx->trid, ctx->ana_state, ctx->anagrpid, 795c8cb51d4SShuhei Matsumoto nvmf_rpc_set_ana_state_done, ctx); 796c8cb51d4SShuhei Matsumoto return; 79751ed4866SJacek Kalwas default: 79844e2f510SSeth Howell SPDK_UNREACHABLE(); 799a54a6a26SSeth Howell } 800a54a6a26SSeth Howell 801a54a6a26SSeth Howell if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) { 802a54a6a26SSeth Howell if (!ctx->response_sent) { 803c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 804c8cb51d4SShuhei Matsumoto "Internal error"); 805a54a6a26SSeth Howell } 80651ed4866SJacek Kalwas 807a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 808a54a6a26SSeth Howell /* Can't really do anything to recover here - subsystem will remain paused. */ 809a54a6a26SSeth Howell } 810a54a6a26SSeth Howell } 811a54a6a26SSeth Howell 812a54a6a26SSeth Howell static int 813a54a6a26SSeth Howell rpc_listen_address_to_trid(const struct rpc_listen_address *address, 814a54a6a26SSeth Howell struct spdk_nvme_transport_id *trid) 815a54a6a26SSeth Howell { 816a54a6a26SSeth Howell size_t len; 817a54a6a26SSeth Howell 818a54a6a26SSeth Howell memset(trid, 0, sizeof(*trid)); 819a54a6a26SSeth Howell 8208ee34f93SJim Harris if (spdk_nvme_transport_id_populate_trstring(trid, address->trtype)) { 8218ee34f93SJim Harris SPDK_ERRLOG("Invalid trtype string: %s\n", address->trtype); 8227ed0904bSSeth Howell return -EINVAL; 8237ed0904bSSeth Howell } 8247ed0904bSSeth Howell 8258ee34f93SJim Harris if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->trtype)) { 8268ee34f93SJim Harris SPDK_ERRLOG("Invalid trtype type: %s\n", address->trtype); 827a54a6a26SSeth Howell return -EINVAL; 828a54a6a26SSeth Howell } 829a54a6a26SSeth Howell 830a54a6a26SSeth Howell if (address->adrfam) { 831a54a6a26SSeth Howell if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) { 832a54a6a26SSeth Howell SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam); 833a54a6a26SSeth Howell return -EINVAL; 834a54a6a26SSeth Howell } 835a54a6a26SSeth Howell } else { 836a54a6a26SSeth Howell trid->adrfam = SPDK_NVMF_ADRFAM_IPV4; 837a54a6a26SSeth Howell } 838a54a6a26SSeth Howell 839a54a6a26SSeth Howell len = strlen(address->traddr); 840a54a6a26SSeth Howell if (len > sizeof(trid->traddr) - 1) { 841a54a6a26SSeth Howell SPDK_ERRLOG("Transport address longer than %zu characters: %s\n", 842a54a6a26SSeth Howell sizeof(trid->traddr) - 1, address->traddr); 843a54a6a26SSeth Howell return -EINVAL; 844a54a6a26SSeth Howell } 845a54a6a26SSeth Howell memcpy(trid->traddr, address->traddr, len + 1); 846a54a6a26SSeth Howell 8479a1cf1c5SJacek Kalwas trid->trsvcid[0] = '\0'; 8489a1cf1c5SJacek Kalwas if (address->trsvcid) { 849a54a6a26SSeth Howell len = strlen(address->trsvcid); 850a54a6a26SSeth Howell if (len > sizeof(trid->trsvcid) - 1) { 851a54a6a26SSeth Howell SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n", 852a54a6a26SSeth Howell sizeof(trid->trsvcid) - 1, address->trsvcid); 853a54a6a26SSeth Howell return -EINVAL; 854a54a6a26SSeth Howell } 855a54a6a26SSeth Howell memcpy(trid->trsvcid, address->trsvcid, len + 1); 8569a1cf1c5SJacek Kalwas } 857a54a6a26SSeth Howell 858a54a6a26SSeth Howell return 0; 859a54a6a26SSeth Howell } 860a54a6a26SSeth Howell 861a54a6a26SSeth Howell static void 862e569a578SSeth Howell rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request, 863a54a6a26SSeth Howell const struct spdk_json_val *params) 864a54a6a26SSeth Howell { 865a54a6a26SSeth Howell struct nvmf_rpc_listener_ctx *ctx; 866a54a6a26SSeth Howell struct spdk_nvmf_subsystem *subsystem; 867a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 8688ff8bf07SSeth Howell int rc; 869a54a6a26SSeth Howell 870a54a6a26SSeth Howell ctx = calloc(1, sizeof(*ctx)); 871a54a6a26SSeth Howell if (!ctx) { 872a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 873a54a6a26SSeth Howell return; 874a54a6a26SSeth Howell } 875a54a6a26SSeth Howell 876a54a6a26SSeth Howell ctx->request = request; 877a54a6a26SSeth Howell 8787662387cSKrzysztof Karas spdk_nvmf_subsystem_listener_opts_init(&ctx->listener_opts, sizeof(ctx->listener_opts)); 8797662387cSKrzysztof Karas 88087a062e6SJacek Kalwas if (spdk_json_decode_object_relaxed(params, nvmf_rpc_listener_decoder, 881a54a6a26SSeth Howell SPDK_COUNTOF(nvmf_rpc_listener_decoder), 882a54a6a26SSeth Howell ctx)) { 88387a062e6SJacek Kalwas SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 884a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 885a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 886a54a6a26SSeth Howell return; 887a54a6a26SSeth Howell } 888a54a6a26SSeth Howell 889f8433aadSSeth Howell tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 890a54a6a26SSeth Howell if (!tgt) { 891a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find a target object.\n"); 892a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 893a54a6a26SSeth Howell "Unable to find a target."); 894a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 895a54a6a26SSeth Howell return; 896a54a6a26SSeth Howell } 897a54a6a26SSeth Howell ctx->tgt = tgt; 898a54a6a26SSeth Howell 899a54a6a26SSeth Howell subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 900a54a6a26SSeth Howell if (!subsystem) { 901a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 902a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 903a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 904a54a6a26SSeth Howell return; 905a54a6a26SSeth Howell } 906a54a6a26SSeth Howell 907a54a6a26SSeth Howell ctx->subsystem = subsystem; 908a54a6a26SSeth Howell 909a54a6a26SSeth Howell if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 910a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 911a54a6a26SSeth Howell "Invalid parameters"); 912a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 913a54a6a26SSeth Howell return; 914a54a6a26SSeth Howell } 915a54a6a26SSeth Howell 916a54a6a26SSeth Howell ctx->op = NVMF_RPC_LISTEN_ADD; 9179a1c2cabSJacek Kalwas spdk_nvmf_listen_opts_init(&ctx->opts, sizeof(ctx->opts)); 91887a062e6SJacek Kalwas ctx->opts.transport_specific = params; 91929773365SKonrad Sztyber if (spdk_nvmf_subsystem_get_allow_any_host(subsystem) && ctx->listener_opts.secure_channel) { 9204becb0d1SBoris Glimcher spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 9214becb0d1SBoris Glimcher "Cannot establish secure channel, when 'allow_any_host' is set"); 9224becb0d1SBoris Glimcher nvmf_rpc_listener_ctx_free(ctx); 9234becb0d1SBoris Glimcher return; 9244becb0d1SBoris Glimcher } 9257662387cSKrzysztof Karas ctx->opts.secure_channel = ctx->listener_opts.secure_channel; 926a54a6a26SSeth Howell 927ecbceb22SMarcin Spiewak if (ctx->ana_state_str) { 928ecbceb22SMarcin Spiewak if (rpc_ana_state_parse(ctx->ana_state_str, &ctx->ana_state)) { 929ecbceb22SMarcin Spiewak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 930ecbceb22SMarcin Spiewak "Invalid parameters"); 931ecbceb22SMarcin Spiewak nvmf_rpc_listener_ctx_free(ctx); 932ecbceb22SMarcin Spiewak return; 933ecbceb22SMarcin Spiewak } 934ecbceb22SMarcin Spiewak ctx->listener_opts.ana_state = ctx->ana_state; 935ecbceb22SMarcin Spiewak } 936ecbceb22SMarcin Spiewak 937248c547dSKarl Bonde Torp ctx->opts.sock_impl = ctx->listener_opts.sock_impl; 938248c547dSKarl Bonde Torp 939312a9d60SBen Walker rc = spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx); 9408ff8bf07SSeth Howell if (rc != 0) { 941a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 942a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 943a54a6a26SSeth Howell } 944a54a6a26SSeth Howell } 945e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_subsystem_add_listener", rpc_nvmf_subsystem_add_listener, 946a54a6a26SSeth Howell SPDK_RPC_RUNTIME); 947a54a6a26SSeth Howell 948a54a6a26SSeth Howell static void 949e569a578SSeth Howell rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request, 950a54a6a26SSeth Howell const struct spdk_json_val *params) 951a54a6a26SSeth Howell { 952a54a6a26SSeth Howell struct nvmf_rpc_listener_ctx *ctx; 953a54a6a26SSeth Howell struct spdk_nvmf_subsystem *subsystem; 954a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 9558ff8bf07SSeth Howell int rc; 956a54a6a26SSeth Howell 957a54a6a26SSeth Howell ctx = calloc(1, sizeof(*ctx)); 958a54a6a26SSeth Howell if (!ctx) { 959a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 960a54a6a26SSeth Howell return; 961a54a6a26SSeth Howell } 962a54a6a26SSeth Howell 963a54a6a26SSeth Howell ctx->request = request; 964a54a6a26SSeth Howell 965a54a6a26SSeth Howell if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder, 966a54a6a26SSeth Howell SPDK_COUNTOF(nvmf_rpc_listener_decoder), 967a54a6a26SSeth Howell ctx)) { 968a54a6a26SSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 969a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 970a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 971a54a6a26SSeth Howell return; 972a54a6a26SSeth Howell } 973a54a6a26SSeth Howell 974f8433aadSSeth Howell tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 975a54a6a26SSeth Howell if (!tgt) { 976a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find a target object.\n"); 977a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 978a54a6a26SSeth Howell "Unable to find a target."); 979a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 980a54a6a26SSeth Howell return; 981a54a6a26SSeth Howell } 982a54a6a26SSeth Howell ctx->tgt = tgt; 983a54a6a26SSeth Howell 984a54a6a26SSeth Howell subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 985a54a6a26SSeth Howell if (!subsystem) { 986a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 987a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 988a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 989a54a6a26SSeth Howell return; 990a54a6a26SSeth Howell } 991a54a6a26SSeth Howell 992a54a6a26SSeth Howell ctx->subsystem = subsystem; 993a54a6a26SSeth Howell 994a54a6a26SSeth Howell if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 995a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 996a54a6a26SSeth Howell "Invalid parameters"); 997a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 998a54a6a26SSeth Howell return; 999a54a6a26SSeth Howell } 1000a54a6a26SSeth Howell 1001d1b0d2cbSSeth Howell ctx->transport = spdk_nvmf_tgt_get_transport(tgt, ctx->trid.trstring); 1002d1b0d2cbSSeth Howell if (!ctx->transport) { 1003de8ac98bSJacek Kalwas SPDK_ERRLOG("Unable to find %s transport. The transport must be created first also make sure it is properly registered.\n", 1004de8ac98bSJacek Kalwas ctx->trid.trstring); 1005d1b0d2cbSSeth Howell spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1006d1b0d2cbSSeth Howell "Invalid parameters"); 1007d1b0d2cbSSeth Howell nvmf_rpc_listener_ctx_free(ctx); 1008d1b0d2cbSSeth Howell return; 1009d1b0d2cbSSeth Howell } 1010d1b0d2cbSSeth Howell 1011a54a6a26SSeth Howell ctx->op = NVMF_RPC_LISTEN_REMOVE; 1012a54a6a26SSeth Howell 1013312a9d60SBen Walker rc = spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx); 10148ff8bf07SSeth Howell if (rc != 0) { 1015a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1016a54a6a26SSeth Howell nvmf_rpc_listener_ctx_free(ctx); 1017a54a6a26SSeth Howell } 1018a54a6a26SSeth Howell } 1019e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", rpc_nvmf_subsystem_remove_listener, 1020a54a6a26SSeth Howell SPDK_RPC_RUNTIME); 1021a54a6a26SSeth Howell 1022470e8518SSlawomir Ptak struct nvmf_rpc_referral_ctx { 1023470e8518SSlawomir Ptak char *tgt_name; 1024470e8518SSlawomir Ptak struct rpc_listen_address address; 1025470e8518SSlawomir Ptak bool secure_channel; 1026020c4e11SKonrad Sztyber char *subnqn; 1027470e8518SSlawomir Ptak }; 1028470e8518SSlawomir Ptak 1029470e8518SSlawomir Ptak static const struct spdk_json_object_decoder nvmf_rpc_referral_decoder[] = { 1030470e8518SSlawomir Ptak {"address", offsetof(struct nvmf_rpc_referral_ctx, address), decode_rpc_listen_address}, 1031470e8518SSlawomir Ptak {"tgt_name", offsetof(struct nvmf_rpc_referral_ctx, tgt_name), spdk_json_decode_string, true}, 1032470e8518SSlawomir Ptak {"secure_channel", offsetof(struct nvmf_rpc_referral_ctx, secure_channel), spdk_json_decode_bool, true}, 1033020c4e11SKonrad Sztyber {"subnqn", offsetof(struct nvmf_rpc_referral_ctx, subnqn), spdk_json_decode_string, true}, 1034470e8518SSlawomir Ptak }; 1035470e8518SSlawomir Ptak 1036470e8518SSlawomir Ptak static void 1037470e8518SSlawomir Ptak nvmf_rpc_referral_ctx_free(struct nvmf_rpc_referral_ctx *ctx) 1038470e8518SSlawomir Ptak { 1039470e8518SSlawomir Ptak free(ctx->tgt_name); 1040020c4e11SKonrad Sztyber free(ctx->subnqn); 1041470e8518SSlawomir Ptak free_rpc_listen_address(&ctx->address); 1042470e8518SSlawomir Ptak } 1043470e8518SSlawomir Ptak 1044470e8518SSlawomir Ptak static void 1045470e8518SSlawomir Ptak rpc_nvmf_add_referral(struct spdk_jsonrpc_request *request, 1046470e8518SSlawomir Ptak const struct spdk_json_val *params) 1047470e8518SSlawomir Ptak { 1048ec37689bSKonrad Sztyber struct nvmf_rpc_referral_ctx ctx = {}; 1049bd2bd356SKonrad Sztyber struct spdk_nvme_transport_id trid = {}; 1050470e8518SSlawomir Ptak struct spdk_nvmf_tgt *tgt; 1051206ace4aSKonrad Sztyber struct spdk_nvmf_referral_opts opts = {}; 1052470e8518SSlawomir Ptak int rc; 1053470e8518SSlawomir Ptak 1054470e8518SSlawomir Ptak if (spdk_json_decode_object_relaxed(params, nvmf_rpc_referral_decoder, 1055470e8518SSlawomir Ptak SPDK_COUNTOF(nvmf_rpc_referral_decoder), 1056ec37689bSKonrad Sztyber &ctx)) { 1057470e8518SSlawomir Ptak SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 1058470e8518SSlawomir Ptak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1059ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1060470e8518SSlawomir Ptak return; 1061470e8518SSlawomir Ptak } 1062470e8518SSlawomir Ptak 1063ec37689bSKonrad Sztyber tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 1064470e8518SSlawomir Ptak if (!tgt) { 1065470e8518SSlawomir Ptak SPDK_ERRLOG("Unable to find a target object.\n"); 1066470e8518SSlawomir Ptak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1067470e8518SSlawomir Ptak "Unable to find a target."); 1068ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1069470e8518SSlawomir Ptak return; 1070470e8518SSlawomir Ptak } 1071470e8518SSlawomir Ptak 1072ec37689bSKonrad Sztyber if (rpc_listen_address_to_trid(&ctx.address, &trid)) { 1073bd2bd356SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1074470e8518SSlawomir Ptak "Invalid parameters"); 1075ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1076470e8518SSlawomir Ptak return; 1077470e8518SSlawomir Ptak } 1078470e8518SSlawomir Ptak 1079020c4e11SKonrad Sztyber if (ctx.subnqn != NULL) { 1080020c4e11SKonrad Sztyber rc = snprintf(trid.subnqn, sizeof(trid.subnqn), "%s", ctx.subnqn); 1081020c4e11SKonrad Sztyber if (rc < 0 || (size_t)rc >= sizeof(trid.subnqn)) { 1082020c4e11SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1083020c4e11SKonrad Sztyber "Invalid subsystem NQN"); 1084020c4e11SKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1085020c4e11SKonrad Sztyber return; 1086020c4e11SKonrad Sztyber } 1087020c4e11SKonrad Sztyber } 1088020c4e11SKonrad Sztyber 1089bd2bd356SKonrad Sztyber if ((trid.trtype == SPDK_NVME_TRANSPORT_TCP || 1090bd2bd356SKonrad Sztyber trid.trtype == SPDK_NVME_TRANSPORT_RDMA) && 1091bd2bd356SKonrad Sztyber !strlen(trid.trsvcid)) { 1092470e8518SSlawomir Ptak SPDK_ERRLOG("Service ID is required.\n"); 1093470e8518SSlawomir Ptak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1094470e8518SSlawomir Ptak "Service ID is required."); 1095ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1096470e8518SSlawomir Ptak return; 1097470e8518SSlawomir Ptak } 1098470e8518SSlawomir Ptak 1099206ace4aSKonrad Sztyber opts.size = SPDK_SIZEOF(&opts, secure_channel); 1100206ace4aSKonrad Sztyber opts.trid = trid; 1101206ace4aSKonrad Sztyber opts.secure_channel = ctx.secure_channel; 1102206ace4aSKonrad Sztyber 1103206ace4aSKonrad Sztyber rc = spdk_nvmf_tgt_add_referral(tgt, &opts); 1104470e8518SSlawomir Ptak if (rc != 0) { 1105470e8518SSlawomir Ptak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1106470e8518SSlawomir Ptak "Internal error"); 1107ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1108470e8518SSlawomir Ptak return; 1109470e8518SSlawomir Ptak } 1110470e8518SSlawomir Ptak 1111ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1112470e8518SSlawomir Ptak 1113470e8518SSlawomir Ptak spdk_jsonrpc_send_bool_response(request, true); 1114470e8518SSlawomir Ptak } 1115470e8518SSlawomir Ptak 1116470e8518SSlawomir Ptak SPDK_RPC_REGISTER("nvmf_discovery_add_referral", rpc_nvmf_add_referral, 1117470e8518SSlawomir Ptak SPDK_RPC_RUNTIME); 1118470e8518SSlawomir Ptak 1119470e8518SSlawomir Ptak static void 1120470e8518SSlawomir Ptak rpc_nvmf_remove_referral(struct spdk_jsonrpc_request *request, 1121470e8518SSlawomir Ptak const struct spdk_json_val *params) 1122470e8518SSlawomir Ptak { 1123ec37689bSKonrad Sztyber struct nvmf_rpc_referral_ctx ctx = {}; 1124bd2bd356SKonrad Sztyber struct spdk_nvme_transport_id trid = {}; 1125206ace4aSKonrad Sztyber struct spdk_nvmf_referral_opts opts = {}; 1126470e8518SSlawomir Ptak struct spdk_nvmf_tgt *tgt; 1127020c4e11SKonrad Sztyber int rc; 1128470e8518SSlawomir Ptak 1129470e8518SSlawomir Ptak if (spdk_json_decode_object(params, nvmf_rpc_referral_decoder, 1130470e8518SSlawomir Ptak SPDK_COUNTOF(nvmf_rpc_referral_decoder), 1131ec37689bSKonrad Sztyber &ctx)) { 1132470e8518SSlawomir Ptak SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1133470e8518SSlawomir Ptak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1134ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1135470e8518SSlawomir Ptak return; 1136470e8518SSlawomir Ptak } 1137470e8518SSlawomir Ptak 1138ec37689bSKonrad Sztyber tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 1139470e8518SSlawomir Ptak if (!tgt) { 1140470e8518SSlawomir Ptak SPDK_ERRLOG("Unable to find a target object.\n"); 1141470e8518SSlawomir Ptak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1142470e8518SSlawomir Ptak "Unable to find a target."); 1143ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1144470e8518SSlawomir Ptak return; 1145470e8518SSlawomir Ptak } 1146470e8518SSlawomir Ptak 1147ec37689bSKonrad Sztyber if (rpc_listen_address_to_trid(&ctx.address, &trid)) { 1148bd2bd356SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1149470e8518SSlawomir Ptak "Invalid parameters"); 1150ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1151470e8518SSlawomir Ptak return; 1152470e8518SSlawomir Ptak } 1153470e8518SSlawomir Ptak 1154020c4e11SKonrad Sztyber if (ctx.subnqn != NULL) { 1155020c4e11SKonrad Sztyber rc = snprintf(trid.subnqn, sizeof(trid.subnqn), "%s", ctx.subnqn); 1156020c4e11SKonrad Sztyber if (rc < 0 || (size_t)rc >= sizeof(trid.subnqn)) { 1157020c4e11SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1158020c4e11SKonrad Sztyber "Invalid subsystem NQN"); 1159020c4e11SKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1160020c4e11SKonrad Sztyber return; 1161020c4e11SKonrad Sztyber } 1162020c4e11SKonrad Sztyber } 1163020c4e11SKonrad Sztyber 1164206ace4aSKonrad Sztyber opts.size = SPDK_SIZEOF(&opts, secure_channel); 1165206ace4aSKonrad Sztyber opts.trid = trid; 1166206ace4aSKonrad Sztyber 1167206ace4aSKonrad Sztyber if (spdk_nvmf_tgt_remove_referral(tgt, &opts)) { 1168470e8518SSlawomir Ptak SPDK_ERRLOG("Failed to remove referral.\n"); 1169470e8518SSlawomir Ptak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1170470e8518SSlawomir Ptak "Unable to remove a referral."); 1171ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1172470e8518SSlawomir Ptak return; 1173470e8518SSlawomir Ptak } 1174470e8518SSlawomir Ptak 1175ec37689bSKonrad Sztyber nvmf_rpc_referral_ctx_free(&ctx); 1176470e8518SSlawomir Ptak 1177470e8518SSlawomir Ptak spdk_jsonrpc_send_bool_response(request, true); 1178470e8518SSlawomir Ptak } 1179470e8518SSlawomir Ptak 1180470e8518SSlawomir Ptak SPDK_RPC_REGISTER("nvmf_discovery_remove_referral", rpc_nvmf_remove_referral, 1181470e8518SSlawomir Ptak SPDK_RPC_RUNTIME); 1182470e8518SSlawomir Ptak 1183470e8518SSlawomir Ptak static void 1184470e8518SSlawomir Ptak dump_nvmf_referral(struct spdk_json_write_ctx *w, 1185470e8518SSlawomir Ptak struct spdk_nvmf_referral *referral) 1186470e8518SSlawomir Ptak { 1187470e8518SSlawomir Ptak spdk_json_write_object_begin(w); 1188470e8518SSlawomir Ptak 1189470e8518SSlawomir Ptak spdk_json_write_named_object_begin(w, "address"); 1190470e8518SSlawomir Ptak nvmf_transport_listen_dump_trid(&referral->trid, w); 1191470e8518SSlawomir Ptak spdk_json_write_object_end(w); 1192470e8518SSlawomir Ptak spdk_json_write_named_bool(w, "secure_channel", 1193470e8518SSlawomir Ptak referral->entry.treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_REQUIRED); 1194020c4e11SKonrad Sztyber spdk_json_write_named_string(w, "subnqn", referral->trid.subnqn); 1195470e8518SSlawomir Ptak 1196470e8518SSlawomir Ptak spdk_json_write_object_end(w); 1197470e8518SSlawomir Ptak } 1198470e8518SSlawomir Ptak 1199470e8518SSlawomir Ptak struct rpc_get_referrals_ctx { 1200470e8518SSlawomir Ptak char *tgt_name; 1201470e8518SSlawomir Ptak }; 1202470e8518SSlawomir Ptak 1203470e8518SSlawomir Ptak static const struct spdk_json_object_decoder rpc_get_referrals_decoders[] = { 1204470e8518SSlawomir Ptak {"tgt_name", offsetof(struct rpc_get_referrals_ctx, tgt_name), spdk_json_decode_string, true}, 1205470e8518SSlawomir Ptak }; 1206470e8518SSlawomir Ptak 1207470e8518SSlawomir Ptak static void 1208470e8518SSlawomir Ptak free_rpc_get_referrals_ctx(struct rpc_get_referrals_ctx *ctx) 1209470e8518SSlawomir Ptak { 1210470e8518SSlawomir Ptak free(ctx->tgt_name); 1211470e8518SSlawomir Ptak free(ctx); 1212470e8518SSlawomir Ptak } 1213470e8518SSlawomir Ptak 1214470e8518SSlawomir Ptak static void 1215470e8518SSlawomir Ptak rpc_nvmf_get_referrals(struct spdk_jsonrpc_request *request, 1216470e8518SSlawomir Ptak const struct spdk_json_val *params) 1217470e8518SSlawomir Ptak { 1218470e8518SSlawomir Ptak struct rpc_get_referrals_ctx *ctx; 1219470e8518SSlawomir Ptak struct spdk_nvmf_tgt *tgt; 1220470e8518SSlawomir Ptak struct spdk_json_write_ctx *w; 1221470e8518SSlawomir Ptak struct spdk_nvmf_referral *referral; 1222470e8518SSlawomir Ptak 1223470e8518SSlawomir Ptak ctx = calloc(1, sizeof(*ctx)); 1224470e8518SSlawomir Ptak if (!ctx) { 1225470e8518SSlawomir Ptak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1226470e8518SSlawomir Ptak "Out of memory"); 1227470e8518SSlawomir Ptak return; 1228470e8518SSlawomir Ptak } 1229470e8518SSlawomir Ptak 1230470e8518SSlawomir Ptak if (params) { 1231470e8518SSlawomir Ptak if (spdk_json_decode_object(params, rpc_get_referrals_decoders, 1232470e8518SSlawomir Ptak SPDK_COUNTOF(rpc_get_referrals_decoders), 1233470e8518SSlawomir Ptak ctx)) { 1234470e8518SSlawomir Ptak SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1235470e8518SSlawomir Ptak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1236470e8518SSlawomir Ptak "Invalid parameters"); 1237470e8518SSlawomir Ptak free_rpc_get_referrals_ctx(ctx); 1238470e8518SSlawomir Ptak return; 1239470e8518SSlawomir Ptak } 1240470e8518SSlawomir Ptak } 1241470e8518SSlawomir Ptak 1242470e8518SSlawomir Ptak tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1243470e8518SSlawomir Ptak if (!tgt) { 1244470e8518SSlawomir Ptak SPDK_ERRLOG("Unable to find a target object.\n"); 1245470e8518SSlawomir Ptak spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1246470e8518SSlawomir Ptak "Unable to find a target"); 1247470e8518SSlawomir Ptak free_rpc_get_referrals_ctx(ctx); 1248470e8518SSlawomir Ptak return; 1249470e8518SSlawomir Ptak } 1250470e8518SSlawomir Ptak 1251470e8518SSlawomir Ptak w = spdk_jsonrpc_begin_result(request); 1252470e8518SSlawomir Ptak 1253470e8518SSlawomir Ptak spdk_json_write_array_begin(w); 1254470e8518SSlawomir Ptak 1255470e8518SSlawomir Ptak TAILQ_FOREACH(referral, &tgt->referrals, link) { 1256470e8518SSlawomir Ptak dump_nvmf_referral(w, referral); 1257470e8518SSlawomir Ptak } 1258470e8518SSlawomir Ptak 1259470e8518SSlawomir Ptak spdk_json_write_array_end(w); 1260470e8518SSlawomir Ptak 1261470e8518SSlawomir Ptak spdk_jsonrpc_end_result(request, w); 1262470e8518SSlawomir Ptak 1263470e8518SSlawomir Ptak free_rpc_get_referrals_ctx(ctx); 1264470e8518SSlawomir Ptak } 1265470e8518SSlawomir Ptak SPDK_RPC_REGISTER("nvmf_discovery_get_referrals", rpc_nvmf_get_referrals, 1266470e8518SSlawomir Ptak SPDK_RPC_RUNTIME); 1267470e8518SSlawomir Ptak 1268c8cb51d4SShuhei Matsumoto static const struct spdk_json_object_decoder nvmf_rpc_set_ana_state_decoder[] = { 1269c8cb51d4SShuhei Matsumoto {"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string}, 1270c8cb51d4SShuhei Matsumoto {"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address}, 1271c8cb51d4SShuhei Matsumoto {"ana_state", offsetof(struct nvmf_rpc_listener_ctx, ana_state_str), spdk_json_decode_string}, 1272c8cb51d4SShuhei Matsumoto {"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true}, 12736d716c47SShuhei Matsumoto {"anagrpid", offsetof(struct nvmf_rpc_listener_ctx, anagrpid), spdk_json_decode_uint32, true}, 1274c8cb51d4SShuhei Matsumoto }; 1275c8cb51d4SShuhei Matsumoto 1276c8cb51d4SShuhei Matsumoto static int 1277c8cb51d4SShuhei Matsumoto rpc_ana_state_parse(const char *str, enum spdk_nvme_ana_state *ana_state) 1278c8cb51d4SShuhei Matsumoto { 1279c8cb51d4SShuhei Matsumoto if (ana_state == NULL || str == NULL) { 1280c8cb51d4SShuhei Matsumoto return -EINVAL; 1281c8cb51d4SShuhei Matsumoto } 1282c8cb51d4SShuhei Matsumoto 1283c8cb51d4SShuhei Matsumoto if (strcasecmp(str, "optimized") == 0) { 1284c8cb51d4SShuhei Matsumoto *ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE; 1285c8cb51d4SShuhei Matsumoto } else if (strcasecmp(str, "non_optimized") == 0) { 1286c8cb51d4SShuhei Matsumoto *ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE; 1287c8cb51d4SShuhei Matsumoto } else if (strcasecmp(str, "inaccessible") == 0) { 1288c8cb51d4SShuhei Matsumoto *ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE; 1289c8cb51d4SShuhei Matsumoto } else { 1290c8cb51d4SShuhei Matsumoto return -ENOENT; 1291c8cb51d4SShuhei Matsumoto } 1292c8cb51d4SShuhei Matsumoto 1293c8cb51d4SShuhei Matsumoto return 0; 1294c8cb51d4SShuhei Matsumoto } 1295c8cb51d4SShuhei Matsumoto 1296c8cb51d4SShuhei Matsumoto static void 1297c8cb51d4SShuhei Matsumoto rpc_nvmf_subsystem_listener_set_ana_state(struct spdk_jsonrpc_request *request, 1298c8cb51d4SShuhei Matsumoto const struct spdk_json_val *params) 1299c8cb51d4SShuhei Matsumoto { 1300c8cb51d4SShuhei Matsumoto struct nvmf_rpc_listener_ctx *ctx; 1301c8cb51d4SShuhei Matsumoto struct spdk_nvmf_subsystem *subsystem; 1302c8cb51d4SShuhei Matsumoto struct spdk_nvmf_tgt *tgt; 1303c8cb51d4SShuhei Matsumoto 1304c8cb51d4SShuhei Matsumoto ctx = calloc(1, sizeof(*ctx)); 1305c8cb51d4SShuhei Matsumoto if (!ctx) { 1306c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1307c8cb51d4SShuhei Matsumoto "Out of memory"); 1308c8cb51d4SShuhei Matsumoto return; 1309c8cb51d4SShuhei Matsumoto } 1310c8cb51d4SShuhei Matsumoto 1311c8cb51d4SShuhei Matsumoto ctx->request = request; 1312c8cb51d4SShuhei Matsumoto 1313c8cb51d4SShuhei Matsumoto if (spdk_json_decode_object(params, nvmf_rpc_set_ana_state_decoder, 1314c8cb51d4SShuhei Matsumoto SPDK_COUNTOF(nvmf_rpc_set_ana_state_decoder), 1315c8cb51d4SShuhei Matsumoto ctx)) { 1316c8cb51d4SShuhei Matsumoto SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1317c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1318c8cb51d4SShuhei Matsumoto "Invalid parameters"); 1319c8cb51d4SShuhei Matsumoto nvmf_rpc_listener_ctx_free(ctx); 1320c8cb51d4SShuhei Matsumoto return; 1321c8cb51d4SShuhei Matsumoto } 1322c8cb51d4SShuhei Matsumoto 1323c8cb51d4SShuhei Matsumoto tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1324c8cb51d4SShuhei Matsumoto if (!tgt) { 1325c8cb51d4SShuhei Matsumoto SPDK_ERRLOG("Unable to find a target object.\n"); 1326c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 13279b143bcaSPierre Lestringant "Unable to find a target."); 1328c8cb51d4SShuhei Matsumoto nvmf_rpc_listener_ctx_free(ctx); 1329c8cb51d4SShuhei Matsumoto return; 1330c8cb51d4SShuhei Matsumoto } 1331c8cb51d4SShuhei Matsumoto 1332c8cb51d4SShuhei Matsumoto ctx->tgt = tgt; 1333c8cb51d4SShuhei Matsumoto 1334c8cb51d4SShuhei Matsumoto subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1335c8cb51d4SShuhei Matsumoto if (!subsystem) { 1336c8cb51d4SShuhei Matsumoto SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1337c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1338c8cb51d4SShuhei Matsumoto "Unable to find subsystem with NQN %s", 1339c8cb51d4SShuhei Matsumoto ctx->nqn); 1340c8cb51d4SShuhei Matsumoto nvmf_rpc_listener_ctx_free(ctx); 1341c8cb51d4SShuhei Matsumoto return; 1342c8cb51d4SShuhei Matsumoto } 1343c8cb51d4SShuhei Matsumoto 1344c8cb51d4SShuhei Matsumoto ctx->subsystem = subsystem; 1345c8cb51d4SShuhei Matsumoto 1346c8cb51d4SShuhei Matsumoto if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) { 1347c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1348c8cb51d4SShuhei Matsumoto "Invalid parameters"); 1349c8cb51d4SShuhei Matsumoto nvmf_rpc_listener_ctx_free(ctx); 1350c8cb51d4SShuhei Matsumoto return; 1351c8cb51d4SShuhei Matsumoto } 1352c8cb51d4SShuhei Matsumoto 1353c8cb51d4SShuhei Matsumoto if (rpc_ana_state_parse(ctx->ana_state_str, &ctx->ana_state)) { 1354c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1355c8cb51d4SShuhei Matsumoto "Invalid parameters"); 1356c8cb51d4SShuhei Matsumoto nvmf_rpc_listener_ctx_free(ctx); 1357c8cb51d4SShuhei Matsumoto return; 1358c8cb51d4SShuhei Matsumoto } 1359c8cb51d4SShuhei Matsumoto 1360c8cb51d4SShuhei Matsumoto ctx->op = NVMF_RPC_LISTEN_SET_ANA_STATE; 1361c8cb51d4SShuhei Matsumoto 1362312a9d60SBen Walker if (spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx)) { 1363c8cb51d4SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1364c8cb51d4SShuhei Matsumoto "Internal error"); 1365c8cb51d4SShuhei Matsumoto nvmf_rpc_listener_ctx_free(ctx); 1366c8cb51d4SShuhei Matsumoto } 1367c8cb51d4SShuhei Matsumoto } 1368c8cb51d4SShuhei Matsumoto SPDK_RPC_REGISTER("nvmf_subsystem_listener_set_ana_state", 1369c8cb51d4SShuhei Matsumoto rpc_nvmf_subsystem_listener_set_ana_state, SPDK_RPC_RUNTIME); 1370c8cb51d4SShuhei Matsumoto 1371aafada11SJacek Kalwas struct nvmf_rpc_ns_params { 1372a54a6a26SSeth Howell char *bdev_name; 1373a54a6a26SSeth Howell char *ptpl_file; 1374a54a6a26SSeth Howell uint32_t nsid; 1375a54a6a26SSeth Howell char nguid[16]; 1376a54a6a26SSeth Howell char eui64[8]; 1377a54a6a26SSeth Howell struct spdk_uuid uuid; 1378694fa34dSShuhei Matsumoto uint32_t anagrpid; 1379d37555b4SJonas Pfefferle bool no_auto_visible; 1380afdec00eSShuhei Matsumoto bool hide_metadata; 1381a54a6a26SSeth Howell }; 1382a54a6a26SSeth Howell 1383a54a6a26SSeth Howell static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = { 1384aafada11SJacek Kalwas {"nsid", offsetof(struct nvmf_rpc_ns_params, nsid), spdk_json_decode_uint32, true}, 1385aafada11SJacek Kalwas {"bdev_name", offsetof(struct nvmf_rpc_ns_params, bdev_name), spdk_json_decode_string}, 1386aafada11SJacek Kalwas {"ptpl_file", offsetof(struct nvmf_rpc_ns_params, ptpl_file), spdk_json_decode_string, true}, 1387aafada11SJacek Kalwas {"nguid", offsetof(struct nvmf_rpc_ns_params, nguid), decode_ns_nguid, true}, 1388aafada11SJacek Kalwas {"eui64", offsetof(struct nvmf_rpc_ns_params, eui64), decode_ns_eui64, true}, 1389aafada11SJacek Kalwas {"uuid", offsetof(struct nvmf_rpc_ns_params, uuid), spdk_json_decode_uuid, true}, 1390aafada11SJacek Kalwas {"anagrpid", offsetof(struct nvmf_rpc_ns_params, anagrpid), spdk_json_decode_uint32, true}, 1391d37555b4SJonas Pfefferle {"no_auto_visible", offsetof(struct nvmf_rpc_ns_params, no_auto_visible), spdk_json_decode_bool, true}, 1392afdec00eSShuhei Matsumoto {"hide_metadata", offsetof(struct nvmf_rpc_ns_params, hide_metadata), spdk_json_decode_bool, true}, 1393a54a6a26SSeth Howell }; 1394a54a6a26SSeth Howell 1395a54a6a26SSeth Howell static int 1396a54a6a26SSeth Howell decode_rpc_ns_params(const struct spdk_json_val *val, void *out) 1397a54a6a26SSeth Howell { 1398aafada11SJacek Kalwas struct nvmf_rpc_ns_params *ns_params = out; 1399a54a6a26SSeth Howell 1400a54a6a26SSeth Howell return spdk_json_decode_object(val, rpc_ns_params_decoders, 1401a54a6a26SSeth Howell SPDK_COUNTOF(rpc_ns_params_decoders), 1402a54a6a26SSeth Howell ns_params); 1403a54a6a26SSeth Howell } 1404a54a6a26SSeth Howell 1405a54a6a26SSeth Howell struct nvmf_rpc_ns_ctx { 1406a54a6a26SSeth Howell char *nqn; 1407f8433aadSSeth Howell char *tgt_name; 1408aafada11SJacek Kalwas struct nvmf_rpc_ns_params ns_params; 1409a54a6a26SSeth Howell 1410a54a6a26SSeth Howell struct spdk_jsonrpc_request *request; 14115e952d84SJacek Kalwas const struct spdk_json_val *params; 1412a54a6a26SSeth Howell bool response_sent; 1413a54a6a26SSeth Howell }; 1414a54a6a26SSeth Howell 1415a54a6a26SSeth Howell static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = { 1416a54a6a26SSeth Howell {"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string}, 1417a54a6a26SSeth Howell {"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params}, 1418f8433aadSSeth Howell {"tgt_name", offsetof(struct nvmf_rpc_ns_ctx, tgt_name), spdk_json_decode_string, true}, 1419a54a6a26SSeth Howell }; 1420a54a6a26SSeth Howell 1421a54a6a26SSeth Howell static void 1422a54a6a26SSeth Howell nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx) 1423a54a6a26SSeth Howell { 1424a54a6a26SSeth Howell free(ctx->nqn); 1425f8433aadSSeth Howell free(ctx->tgt_name); 1426a54a6a26SSeth Howell free(ctx->ns_params.bdev_name); 1427a54a6a26SSeth Howell free(ctx->ns_params.ptpl_file); 1428a54a6a26SSeth Howell free(ctx); 1429a54a6a26SSeth Howell } 1430a54a6a26SSeth Howell 1431a54a6a26SSeth Howell static void 14321b249c38SSeth Howell nvmf_rpc_ns_failback_resumed(struct spdk_nvmf_subsystem *subsystem, 14331b249c38SSeth Howell void *cb_arg, int status) 14341b249c38SSeth Howell { 14351b249c38SSeth Howell struct nvmf_rpc_ns_ctx *ctx = cb_arg; 14361b249c38SSeth Howell struct spdk_jsonrpc_request *request = ctx->request; 14371b249c38SSeth Howell 14381b249c38SSeth Howell if (status) { 14391b249c38SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 14401b249c38SSeth Howell "Unable to add ns, subsystem in invalid state"); 14411b249c38SSeth Howell } else { 14421b249c38SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 14431b249c38SSeth Howell "Unable to add ns, subsystem in active state"); 14441b249c38SSeth Howell } 14451b249c38SSeth Howell 14461b249c38SSeth Howell nvmf_rpc_ns_ctx_free(ctx); 14471b249c38SSeth Howell } 14481b249c38SSeth Howell 14491b249c38SSeth Howell static void 1450a54a6a26SSeth Howell nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 1451a54a6a26SSeth Howell void *cb_arg, int status) 1452a54a6a26SSeth Howell { 1453a54a6a26SSeth Howell struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1454a54a6a26SSeth Howell struct spdk_jsonrpc_request *request = ctx->request; 1455a54a6a26SSeth Howell uint32_t nsid = ctx->ns_params.nsid; 1456a54a6a26SSeth Howell bool response_sent = ctx->response_sent; 1457a54a6a26SSeth Howell struct spdk_json_write_ctx *w; 14581b249c38SSeth Howell int rc; 14591b249c38SSeth Howell 14601b249c38SSeth Howell /* The case where the call to add the namespace was successful, but the subsystem couldn't be resumed. */ 14611b249c38SSeth Howell if (status && !ctx->response_sent) { 14621b249c38SSeth Howell rc = spdk_nvmf_subsystem_remove_ns(subsystem, nsid); 14631b249c38SSeth Howell if (rc != 0) { 14641b249c38SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 14651b249c38SSeth Howell "Unable to add ns, subsystem in invalid state"); 14661b249c38SSeth Howell nvmf_rpc_ns_ctx_free(ctx); 14671b249c38SSeth Howell return; 14681b249c38SSeth Howell } 14691b249c38SSeth Howell 14701b249c38SSeth Howell rc = spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_failback_resumed, ctx); 14711b249c38SSeth Howell if (rc != 0) { 14721b249c38SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 14731b249c38SSeth Howell nvmf_rpc_ns_ctx_free(ctx); 14741b249c38SSeth Howell return; 14751b249c38SSeth Howell } 14761b249c38SSeth Howell 14771b249c38SSeth Howell return; 14781b249c38SSeth Howell } 1479a54a6a26SSeth Howell 1480a54a6a26SSeth Howell nvmf_rpc_ns_ctx_free(ctx); 1481a54a6a26SSeth Howell 1482a54a6a26SSeth Howell if (response_sent) { 1483a54a6a26SSeth Howell return; 1484a54a6a26SSeth Howell } 1485a54a6a26SSeth Howell 1486a54a6a26SSeth Howell w = spdk_jsonrpc_begin_result(request); 1487a54a6a26SSeth Howell spdk_json_write_uint32(w, nsid); 1488a54a6a26SSeth Howell spdk_jsonrpc_end_result(request, w); 1489a54a6a26SSeth Howell } 1490a54a6a26SSeth Howell 1491a54a6a26SSeth Howell static void 1492a54a6a26SSeth Howell nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem, 1493a54a6a26SSeth Howell void *cb_arg, int status) 1494a54a6a26SSeth Howell { 1495a54a6a26SSeth Howell struct nvmf_rpc_ns_ctx *ctx = cb_arg; 1496a54a6a26SSeth Howell struct spdk_nvmf_ns_opts ns_opts; 1497a54a6a26SSeth Howell 1498a54a6a26SSeth Howell spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts)); 1499a54a6a26SSeth Howell ns_opts.nsid = ctx->ns_params.nsid; 15005e952d84SJacek Kalwas ns_opts.transport_specific = ctx->params; 1501a54a6a26SSeth Howell 1502a54a6a26SSeth Howell SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ctx->ns_params.nguid), "size mismatch"); 1503a54a6a26SSeth Howell memcpy(ns_opts.nguid, ctx->ns_params.nguid, sizeof(ns_opts.nguid)); 1504a54a6a26SSeth Howell 1505a54a6a26SSeth Howell SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch"); 1506a54a6a26SSeth Howell memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64)); 1507a54a6a26SSeth Howell 150895a367d6SArtur Paszkiewicz if (!spdk_uuid_is_null(&ctx->ns_params.uuid)) { 1509a54a6a26SSeth Howell ns_opts.uuid = ctx->ns_params.uuid; 1510a54a6a26SSeth Howell } 1511a54a6a26SSeth Howell 1512694fa34dSShuhei Matsumoto ns_opts.anagrpid = ctx->ns_params.anagrpid; 1513d37555b4SJonas Pfefferle ns_opts.no_auto_visible = ctx->ns_params.no_auto_visible; 1514afdec00eSShuhei Matsumoto ns_opts.hide_metadata = ctx->ns_params.hide_metadata; 1515694fa34dSShuhei Matsumoto 1516a22d8a53SShuhei Matsumoto ctx->ns_params.nsid = spdk_nvmf_subsystem_add_ns_ext(subsystem, ctx->ns_params.bdev_name, 1517a22d8a53SShuhei Matsumoto &ns_opts, sizeof(ns_opts), 1518a54a6a26SSeth Howell ctx->ns_params.ptpl_file); 1519a54a6a26SSeth Howell if (ctx->ns_params.nsid == 0) { 1520a54a6a26SSeth Howell SPDK_ERRLOG("Unable to add namespace\n"); 1521a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1522a54a6a26SSeth Howell "Invalid parameters"); 1523a54a6a26SSeth Howell ctx->response_sent = true; 1524a54a6a26SSeth Howell goto resume; 1525a54a6a26SSeth Howell } 1526a54a6a26SSeth Howell 1527a54a6a26SSeth Howell resume: 1528a54a6a26SSeth Howell if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_resumed, ctx)) { 1529a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1530a54a6a26SSeth Howell nvmf_rpc_ns_ctx_free(ctx); 1531a54a6a26SSeth Howell } 1532a54a6a26SSeth Howell } 1533a54a6a26SSeth Howell 1534a54a6a26SSeth Howell static void 1535e569a578SSeth Howell rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request, 1536a54a6a26SSeth Howell const struct spdk_json_val *params) 1537a54a6a26SSeth Howell { 1538a54a6a26SSeth Howell struct nvmf_rpc_ns_ctx *ctx; 1539a54a6a26SSeth Howell struct spdk_nvmf_subsystem *subsystem; 1540a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 15418ff8bf07SSeth Howell int rc; 1542a54a6a26SSeth Howell 1543a54a6a26SSeth Howell ctx = calloc(1, sizeof(*ctx)); 1544a54a6a26SSeth Howell if (!ctx) { 1545a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1546a54a6a26SSeth Howell return; 1547a54a6a26SSeth Howell } 1548a54a6a26SSeth Howell 15495e952d84SJacek Kalwas if (spdk_json_decode_object_relaxed(params, nvmf_rpc_subsystem_ns_decoder, 15505e952d84SJacek Kalwas SPDK_COUNTOF(nvmf_rpc_subsystem_ns_decoder), ctx)) { 1551a54a6a26SSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1552a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1553a54a6a26SSeth Howell nvmf_rpc_ns_ctx_free(ctx); 1554a54a6a26SSeth Howell return; 1555a54a6a26SSeth Howell } 1556a54a6a26SSeth Howell 1557a54a6a26SSeth Howell ctx->request = request; 15585e952d84SJacek Kalwas ctx->params = params; 1559a54a6a26SSeth Howell ctx->response_sent = false; 1560a54a6a26SSeth Howell 1561f8433aadSSeth Howell tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1562a54a6a26SSeth Howell if (!tgt) { 1563a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find a target object.\n"); 1564a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1565a54a6a26SSeth Howell "Unable to find a target."); 1566a54a6a26SSeth Howell nvmf_rpc_ns_ctx_free(ctx); 1567a54a6a26SSeth Howell return; 1568a54a6a26SSeth Howell } 1569a54a6a26SSeth Howell 1570a54a6a26SSeth Howell subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1571a54a6a26SSeth Howell if (!subsystem) { 1572a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1573a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1574a54a6a26SSeth Howell nvmf_rpc_ns_ctx_free(ctx); 1575a54a6a26SSeth Howell return; 1576a54a6a26SSeth Howell } 1577a54a6a26SSeth Howell 1578312a9d60SBen Walker rc = spdk_nvmf_subsystem_pause(subsystem, ctx->ns_params.nsid, nvmf_rpc_ns_paused, ctx); 15798ff8bf07SSeth Howell if (rc != 0) { 1580a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1581a54a6a26SSeth Howell nvmf_rpc_ns_ctx_free(ctx); 1582a54a6a26SSeth Howell } 1583a54a6a26SSeth Howell } 1584e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", rpc_nvmf_subsystem_add_ns, SPDK_RPC_RUNTIME) 1585a54a6a26SSeth Howell 1586698b2423SShuhei Matsumoto struct nvmf_rpc_ana_group_ctx { 1587698b2423SShuhei Matsumoto char *nqn; 1588698b2423SShuhei Matsumoto char *tgt_name; 1589698b2423SShuhei Matsumoto uint32_t nsid; 1590698b2423SShuhei Matsumoto uint32_t anagrpid; 1591698b2423SShuhei Matsumoto 1592698b2423SShuhei Matsumoto struct spdk_jsonrpc_request *request; 1593698b2423SShuhei Matsumoto bool response_sent; 1594698b2423SShuhei Matsumoto }; 1595698b2423SShuhei Matsumoto 1596698b2423SShuhei Matsumoto static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ana_group_decoder[] = { 1597698b2423SShuhei Matsumoto {"nqn", offsetof(struct nvmf_rpc_ana_group_ctx, nqn), spdk_json_decode_string}, 1598698b2423SShuhei Matsumoto {"nsid", offsetof(struct nvmf_rpc_ana_group_ctx, nsid), spdk_json_decode_uint32}, 1599698b2423SShuhei Matsumoto {"anagrpid", offsetof(struct nvmf_rpc_ana_group_ctx, anagrpid), spdk_json_decode_uint32}, 1600698b2423SShuhei Matsumoto {"tgt_name", offsetof(struct nvmf_rpc_ana_group_ctx, tgt_name), spdk_json_decode_string, true}, 1601698b2423SShuhei Matsumoto }; 1602698b2423SShuhei Matsumoto 1603698b2423SShuhei Matsumoto static void 1604698b2423SShuhei Matsumoto nvmf_rpc_ana_group_ctx_free(struct nvmf_rpc_ana_group_ctx *ctx) 1605698b2423SShuhei Matsumoto { 1606698b2423SShuhei Matsumoto free(ctx->nqn); 1607698b2423SShuhei Matsumoto free(ctx->tgt_name); 1608698b2423SShuhei Matsumoto free(ctx); 1609698b2423SShuhei Matsumoto } 1610698b2423SShuhei Matsumoto 1611698b2423SShuhei Matsumoto static void 1612698b2423SShuhei Matsumoto nvmf_rpc_anagrpid_resumed(struct spdk_nvmf_subsystem *subsystem, 1613698b2423SShuhei Matsumoto void *cb_arg, int status) 1614698b2423SShuhei Matsumoto { 1615698b2423SShuhei Matsumoto struct nvmf_rpc_ana_group_ctx *ctx = cb_arg; 1616698b2423SShuhei Matsumoto struct spdk_jsonrpc_request *request = ctx->request; 1617698b2423SShuhei Matsumoto bool response_sent = ctx->response_sent; 1618698b2423SShuhei Matsumoto 1619698b2423SShuhei Matsumoto nvmf_rpc_ana_group_ctx_free(ctx); 1620698b2423SShuhei Matsumoto 1621698b2423SShuhei Matsumoto if (response_sent) { 1622698b2423SShuhei Matsumoto return; 1623698b2423SShuhei Matsumoto } 1624698b2423SShuhei Matsumoto 1625698b2423SShuhei Matsumoto spdk_jsonrpc_send_bool_response(request, true); 1626698b2423SShuhei Matsumoto } 1627698b2423SShuhei Matsumoto 1628698b2423SShuhei Matsumoto static void 1629698b2423SShuhei Matsumoto nvmf_rpc_ana_group(struct spdk_nvmf_subsystem *subsystem, 1630698b2423SShuhei Matsumoto void *cb_arg, int status) 1631698b2423SShuhei Matsumoto { 1632698b2423SShuhei Matsumoto struct nvmf_rpc_ana_group_ctx *ctx = cb_arg; 1633698b2423SShuhei Matsumoto int rc; 1634698b2423SShuhei Matsumoto 1635698b2423SShuhei Matsumoto rc = spdk_nvmf_subsystem_set_ns_ana_group(subsystem, ctx->nsid, ctx->anagrpid); 1636698b2423SShuhei Matsumoto if (rc != 0) { 1637698b2423SShuhei Matsumoto SPDK_ERRLOG("Unable to change ANA group ID\n"); 1638698b2423SShuhei Matsumoto spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1639698b2423SShuhei Matsumoto "Invalid parameters"); 1640698b2423SShuhei Matsumoto ctx->response_sent = true; 1641698b2423SShuhei Matsumoto } 1642698b2423SShuhei Matsumoto 1643698b2423SShuhei Matsumoto if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_anagrpid_resumed, ctx)) { 1644698b2423SShuhei Matsumoto if (!ctx->response_sent) { 1645698b2423SShuhei Matsumoto spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1646698b2423SShuhei Matsumoto "Internal error"); 1647698b2423SShuhei Matsumoto } 1648698b2423SShuhei Matsumoto nvmf_rpc_ana_group_ctx_free(ctx); 1649698b2423SShuhei Matsumoto } 1650698b2423SShuhei Matsumoto } 1651698b2423SShuhei Matsumoto 1652698b2423SShuhei Matsumoto static void 1653698b2423SShuhei Matsumoto rpc_nvmf_subsystem_set_ns_ana_group(struct spdk_jsonrpc_request *request, 1654698b2423SShuhei Matsumoto const struct spdk_json_val *params) 1655698b2423SShuhei Matsumoto { 1656698b2423SShuhei Matsumoto struct nvmf_rpc_ana_group_ctx *ctx; 1657698b2423SShuhei Matsumoto struct spdk_nvmf_subsystem *subsystem; 1658698b2423SShuhei Matsumoto struct spdk_nvmf_tgt *tgt; 1659698b2423SShuhei Matsumoto int rc; 1660698b2423SShuhei Matsumoto 1661698b2423SShuhei Matsumoto ctx = calloc(1, sizeof(*ctx)); 1662698b2423SShuhei Matsumoto if (!ctx) { 1663698b2423SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1664698b2423SShuhei Matsumoto return; 1665698b2423SShuhei Matsumoto } 1666698b2423SShuhei Matsumoto 1667698b2423SShuhei Matsumoto if (spdk_json_decode_object(params, nvmf_rpc_subsystem_ana_group_decoder, 1668698b2423SShuhei Matsumoto SPDK_COUNTOF(nvmf_rpc_subsystem_ana_group_decoder), ctx)) { 1669698b2423SShuhei Matsumoto SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1670698b2423SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1671698b2423SShuhei Matsumoto nvmf_rpc_ana_group_ctx_free(ctx); 1672698b2423SShuhei Matsumoto return; 1673698b2423SShuhei Matsumoto } 1674698b2423SShuhei Matsumoto 1675698b2423SShuhei Matsumoto ctx->request = request; 1676698b2423SShuhei Matsumoto ctx->response_sent = false; 1677698b2423SShuhei Matsumoto 1678698b2423SShuhei Matsumoto tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1679698b2423SShuhei Matsumoto if (!tgt) { 1680698b2423SShuhei Matsumoto SPDK_ERRLOG("Unable to find a target object.\n"); 1681698b2423SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1682698b2423SShuhei Matsumoto "Unable to find a target."); 1683698b2423SShuhei Matsumoto nvmf_rpc_ana_group_ctx_free(ctx); 1684698b2423SShuhei Matsumoto return; 1685698b2423SShuhei Matsumoto } 1686698b2423SShuhei Matsumoto 1687698b2423SShuhei Matsumoto subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1688698b2423SShuhei Matsumoto if (!subsystem) { 1689698b2423SShuhei Matsumoto SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1690698b2423SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1691698b2423SShuhei Matsumoto nvmf_rpc_ana_group_ctx_free(ctx); 1692698b2423SShuhei Matsumoto return; 1693698b2423SShuhei Matsumoto } 1694698b2423SShuhei Matsumoto 1695698b2423SShuhei Matsumoto rc = spdk_nvmf_subsystem_pause(subsystem, ctx->nsid, nvmf_rpc_ana_group, ctx); 1696698b2423SShuhei Matsumoto if (rc != 0) { 1697698b2423SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1698698b2423SShuhei Matsumoto nvmf_rpc_ana_group_ctx_free(ctx); 1699698b2423SShuhei Matsumoto } 1700698b2423SShuhei Matsumoto } 1701698b2423SShuhei Matsumoto SPDK_RPC_REGISTER("nvmf_subsystem_set_ns_ana_group", rpc_nvmf_subsystem_set_ns_ana_group, 1702698b2423SShuhei Matsumoto SPDK_RPC_RUNTIME) 1703698b2423SShuhei Matsumoto 1704a54a6a26SSeth Howell struct nvmf_rpc_remove_ns_ctx { 1705a54a6a26SSeth Howell char *nqn; 1706f8433aadSSeth Howell char *tgt_name; 1707a54a6a26SSeth Howell uint32_t nsid; 1708a54a6a26SSeth Howell 1709a54a6a26SSeth Howell struct spdk_jsonrpc_request *request; 1710a54a6a26SSeth Howell bool response_sent; 1711a54a6a26SSeth Howell }; 1712a54a6a26SSeth Howell 1713a54a6a26SSeth Howell static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = { 1714a54a6a26SSeth Howell {"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string}, 1715a54a6a26SSeth Howell {"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32}, 1716f8433aadSSeth Howell {"tgt_name", offsetof(struct nvmf_rpc_remove_ns_ctx, tgt_name), spdk_json_decode_string, true}, 1717a54a6a26SSeth Howell }; 1718a54a6a26SSeth Howell 1719a54a6a26SSeth Howell static void 1720a54a6a26SSeth Howell nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx) 1721a54a6a26SSeth Howell { 1722a54a6a26SSeth Howell free(ctx->nqn); 1723f8433aadSSeth Howell free(ctx->tgt_name); 1724a54a6a26SSeth Howell free(ctx); 1725a54a6a26SSeth Howell } 1726a54a6a26SSeth Howell 1727a54a6a26SSeth Howell static void 1728a54a6a26SSeth Howell nvmf_rpc_remove_ns_resumed(struct spdk_nvmf_subsystem *subsystem, 1729a54a6a26SSeth Howell void *cb_arg, int status) 1730a54a6a26SSeth Howell { 1731a54a6a26SSeth Howell struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1732a54a6a26SSeth Howell struct spdk_jsonrpc_request *request = ctx->request; 1733a54a6a26SSeth Howell bool response_sent = ctx->response_sent; 1734a54a6a26SSeth Howell 1735a54a6a26SSeth Howell nvmf_rpc_remove_ns_ctx_free(ctx); 1736a54a6a26SSeth Howell 1737a54a6a26SSeth Howell if (response_sent) { 1738a54a6a26SSeth Howell return; 1739a54a6a26SSeth Howell } 1740a54a6a26SSeth Howell 1741d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 1742a54a6a26SSeth Howell } 1743a54a6a26SSeth Howell 1744a54a6a26SSeth Howell static void 1745a54a6a26SSeth Howell nvmf_rpc_remove_ns_paused(struct spdk_nvmf_subsystem *subsystem, 1746a54a6a26SSeth Howell void *cb_arg, int status) 1747a54a6a26SSeth Howell { 1748a54a6a26SSeth Howell struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg; 1749a54a6a26SSeth Howell int ret; 1750a54a6a26SSeth Howell 1751a54a6a26SSeth Howell ret = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid); 1752a54a6a26SSeth Howell if (ret < 0) { 1753a54a6a26SSeth Howell SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid); 1754a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1755a54a6a26SSeth Howell "Invalid parameters"); 1756a54a6a26SSeth Howell ctx->response_sent = true; 1757a54a6a26SSeth Howell } 1758a54a6a26SSeth Howell 1759a54a6a26SSeth Howell if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx)) { 1760a54a6a26SSeth Howell if (!ctx->response_sent) { 1761a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1762a54a6a26SSeth Howell } 1763a54a6a26SSeth Howell nvmf_rpc_remove_ns_ctx_free(ctx); 1764a54a6a26SSeth Howell } 1765a54a6a26SSeth Howell } 1766a54a6a26SSeth Howell 1767a54a6a26SSeth Howell static void 1768e569a578SSeth Howell rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request, 1769a54a6a26SSeth Howell const struct spdk_json_val *params) 1770a54a6a26SSeth Howell { 1771a54a6a26SSeth Howell struct nvmf_rpc_remove_ns_ctx *ctx; 1772a54a6a26SSeth Howell struct spdk_nvmf_subsystem *subsystem; 1773a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 17748ff8bf07SSeth Howell int rc; 1775a54a6a26SSeth Howell 1776a54a6a26SSeth Howell ctx = calloc(1, sizeof(*ctx)); 1777a54a6a26SSeth Howell if (!ctx) { 1778a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1779a54a6a26SSeth Howell return; 1780a54a6a26SSeth Howell } 1781a54a6a26SSeth Howell 1782a54a6a26SSeth Howell if (spdk_json_decode_object(params, nvmf_rpc_subsystem_remove_ns_decoder, 1783a54a6a26SSeth Howell SPDK_COUNTOF(nvmf_rpc_subsystem_remove_ns_decoder), 1784a54a6a26SSeth Howell ctx)) { 1785a54a6a26SSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1786a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1787a54a6a26SSeth Howell nvmf_rpc_remove_ns_ctx_free(ctx); 1788a54a6a26SSeth Howell return; 1789a54a6a26SSeth Howell } 1790a54a6a26SSeth Howell 1791f8433aadSSeth Howell tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1792a54a6a26SSeth Howell if (!tgt) { 1793a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find a target object.\n"); 1794a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1795a54a6a26SSeth Howell "Unable to find a target."); 1796a54a6a26SSeth Howell nvmf_rpc_remove_ns_ctx_free(ctx); 1797a54a6a26SSeth Howell return; 1798a54a6a26SSeth Howell } 1799a54a6a26SSeth Howell 1800a54a6a26SSeth Howell ctx->request = request; 1801a54a6a26SSeth Howell ctx->response_sent = false; 1802a54a6a26SSeth Howell 1803a54a6a26SSeth Howell subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1804a54a6a26SSeth Howell if (!subsystem) { 1805a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1806a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1807a54a6a26SSeth Howell nvmf_rpc_remove_ns_ctx_free(ctx); 1808a54a6a26SSeth Howell return; 1809a54a6a26SSeth Howell } 1810a54a6a26SSeth Howell 1811312a9d60SBen Walker rc = spdk_nvmf_subsystem_pause(subsystem, ctx->nsid, nvmf_rpc_remove_ns_paused, ctx); 18128ff8bf07SSeth Howell if (rc != 0) { 1813a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1814a54a6a26SSeth Howell nvmf_rpc_remove_ns_ctx_free(ctx); 1815a54a6a26SSeth Howell } 1816a54a6a26SSeth Howell } 1817e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_subsystem_remove_ns", rpc_nvmf_subsystem_remove_ns, SPDK_RPC_RUNTIME) 1818a54a6a26SSeth Howell 1819d37555b4SJonas Pfefferle struct nvmf_rpc_ns_visible_ctx { 1820d37555b4SJonas Pfefferle struct spdk_jsonrpc_request *request; 1821d37555b4SJonas Pfefferle char *nqn; 1822d37555b4SJonas Pfefferle uint32_t nsid; 1823d37555b4SJonas Pfefferle char *host; 1824d37555b4SJonas Pfefferle char *tgt_name; 1825d37555b4SJonas Pfefferle bool visible; 1826d37555b4SJonas Pfefferle bool response_sent; 1827d37555b4SJonas Pfefferle }; 1828d37555b4SJonas Pfefferle 1829d37555b4SJonas Pfefferle static const struct spdk_json_object_decoder nvmf_rpc_ns_visible_decoder[] = { 1830d37555b4SJonas Pfefferle {"nqn", offsetof(struct nvmf_rpc_ns_visible_ctx, nqn), spdk_json_decode_string}, 1831d37555b4SJonas Pfefferle {"nsid", offsetof(struct nvmf_rpc_ns_visible_ctx, nsid), spdk_json_decode_uint32}, 1832d37555b4SJonas Pfefferle {"host", offsetof(struct nvmf_rpc_ns_visible_ctx, host), spdk_json_decode_string}, 1833d37555b4SJonas Pfefferle {"tgt_name", offsetof(struct nvmf_rpc_ns_visible_ctx, tgt_name), spdk_json_decode_string, true}, 1834d37555b4SJonas Pfefferle }; 1835d37555b4SJonas Pfefferle 1836d37555b4SJonas Pfefferle static void 1837d37555b4SJonas Pfefferle nvmf_rpc_ns_visible_ctx_free(struct nvmf_rpc_ns_visible_ctx *ctx) 1838d37555b4SJonas Pfefferle { 1839d37555b4SJonas Pfefferle free(ctx->nqn); 1840d37555b4SJonas Pfefferle free(ctx->host); 1841d37555b4SJonas Pfefferle free(ctx->tgt_name); 1842d37555b4SJonas Pfefferle free(ctx); 1843d37555b4SJonas Pfefferle } 1844d37555b4SJonas Pfefferle 1845d37555b4SJonas Pfefferle static void 1846d37555b4SJonas Pfefferle nvmf_rpc_ns_visible_resumed(struct spdk_nvmf_subsystem *subsystem, 1847d37555b4SJonas Pfefferle void *cb_arg, int status) 1848d37555b4SJonas Pfefferle { 1849d37555b4SJonas Pfefferle struct nvmf_rpc_ns_visible_ctx *ctx = cb_arg; 1850d37555b4SJonas Pfefferle struct spdk_jsonrpc_request *request = ctx->request; 1851d37555b4SJonas Pfefferle bool response_sent = ctx->response_sent; 1852d37555b4SJonas Pfefferle 1853d37555b4SJonas Pfefferle nvmf_rpc_ns_visible_ctx_free(ctx); 1854d37555b4SJonas Pfefferle 1855d37555b4SJonas Pfefferle if (!response_sent) { 1856d37555b4SJonas Pfefferle spdk_jsonrpc_send_bool_response(request, true); 1857d37555b4SJonas Pfefferle } 1858d37555b4SJonas Pfefferle } 1859d37555b4SJonas Pfefferle 1860d37555b4SJonas Pfefferle static void 1861d37555b4SJonas Pfefferle nvmf_rpc_ns_visible_paused(struct spdk_nvmf_subsystem *subsystem, 1862d37555b4SJonas Pfefferle void *cb_arg, int status) 1863d37555b4SJonas Pfefferle { 1864d37555b4SJonas Pfefferle struct nvmf_rpc_ns_visible_ctx *ctx = cb_arg; 1865d37555b4SJonas Pfefferle int ret; 1866d37555b4SJonas Pfefferle 1867d37555b4SJonas Pfefferle if (ctx->visible) { 1868d37555b4SJonas Pfefferle ret = spdk_nvmf_ns_add_host(subsystem, ctx->nsid, ctx->host, 0); 1869d37555b4SJonas Pfefferle } else { 1870d37555b4SJonas Pfefferle ret = spdk_nvmf_ns_remove_host(subsystem, ctx->nsid, ctx->host, 0); 1871d37555b4SJonas Pfefferle } 1872d37555b4SJonas Pfefferle if (ret < 0) { 1873d37555b4SJonas Pfefferle SPDK_ERRLOG("Unable to add/remove %s to namespace ID %u\n", ctx->host, ctx->nsid); 1874d37555b4SJonas Pfefferle spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1875d37555b4SJonas Pfefferle "Invalid parameters"); 1876d37555b4SJonas Pfefferle ctx->response_sent = true; 1877d37555b4SJonas Pfefferle } 1878d37555b4SJonas Pfefferle 1879d37555b4SJonas Pfefferle if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_visible_resumed, ctx)) { 1880d37555b4SJonas Pfefferle if (!ctx->response_sent) { 1881d37555b4SJonas Pfefferle spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1882d37555b4SJonas Pfefferle } 1883d37555b4SJonas Pfefferle nvmf_rpc_ns_visible_ctx_free(ctx); 1884d37555b4SJonas Pfefferle } 1885d37555b4SJonas Pfefferle } 1886d37555b4SJonas Pfefferle 1887d37555b4SJonas Pfefferle static void 1888d37555b4SJonas Pfefferle nvmf_rpc_ns_visible(struct spdk_jsonrpc_request *request, 1889d37555b4SJonas Pfefferle const struct spdk_json_val *params, 1890d37555b4SJonas Pfefferle bool visible) 1891d37555b4SJonas Pfefferle { 1892d37555b4SJonas Pfefferle struct nvmf_rpc_ns_visible_ctx *ctx; 1893d37555b4SJonas Pfefferle struct spdk_nvmf_subsystem *subsystem; 1894d37555b4SJonas Pfefferle struct spdk_nvmf_tgt *tgt; 1895d37555b4SJonas Pfefferle int rc; 1896d37555b4SJonas Pfefferle 1897d37555b4SJonas Pfefferle ctx = calloc(1, sizeof(*ctx)); 1898d37555b4SJonas Pfefferle if (!ctx) { 1899d37555b4SJonas Pfefferle spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 1900d37555b4SJonas Pfefferle return; 1901d37555b4SJonas Pfefferle } 1902d37555b4SJonas Pfefferle ctx->visible = visible; 1903d37555b4SJonas Pfefferle 1904d37555b4SJonas Pfefferle if (spdk_json_decode_object(params, nvmf_rpc_ns_visible_decoder, 1905d37555b4SJonas Pfefferle SPDK_COUNTOF(nvmf_rpc_ns_visible_decoder), 1906d37555b4SJonas Pfefferle ctx)) { 1907d37555b4SJonas Pfefferle SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1908d37555b4SJonas Pfefferle spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1909d37555b4SJonas Pfefferle nvmf_rpc_ns_visible_ctx_free(ctx); 1910d37555b4SJonas Pfefferle return; 1911d37555b4SJonas Pfefferle } 1912d37555b4SJonas Pfefferle ctx->request = request; 1913d37555b4SJonas Pfefferle 1914d37555b4SJonas Pfefferle tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 1915d37555b4SJonas Pfefferle if (!tgt) { 1916d37555b4SJonas Pfefferle SPDK_ERRLOG("Unable to find a target object.\n"); 1917d37555b4SJonas Pfefferle spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1918d37555b4SJonas Pfefferle "Unable to find a target."); 1919d37555b4SJonas Pfefferle nvmf_rpc_ns_visible_ctx_free(ctx); 1920d37555b4SJonas Pfefferle return; 1921d37555b4SJonas Pfefferle } 1922d37555b4SJonas Pfefferle 1923d37555b4SJonas Pfefferle subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 1924d37555b4SJonas Pfefferle if (!subsystem) { 1925d37555b4SJonas Pfefferle SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 1926d37555b4SJonas Pfefferle spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1927d37555b4SJonas Pfefferle nvmf_rpc_ns_visible_ctx_free(ctx); 1928d37555b4SJonas Pfefferle return; 1929d37555b4SJonas Pfefferle } 1930d37555b4SJonas Pfefferle 1931d37555b4SJonas Pfefferle rc = spdk_nvmf_subsystem_pause(subsystem, ctx->nsid, nvmf_rpc_ns_visible_paused, ctx); 1932d37555b4SJonas Pfefferle if (rc != 0) { 1933d37555b4SJonas Pfefferle spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 1934d37555b4SJonas Pfefferle nvmf_rpc_ns_visible_ctx_free(ctx); 1935d37555b4SJonas Pfefferle } 1936d37555b4SJonas Pfefferle } 1937d37555b4SJonas Pfefferle 1938d37555b4SJonas Pfefferle static void 1939d37555b4SJonas Pfefferle rpc_nvmf_ns_add_host(struct spdk_jsonrpc_request *request, 1940d37555b4SJonas Pfefferle const struct spdk_json_val *params) 1941d37555b4SJonas Pfefferle { 1942d37555b4SJonas Pfefferle nvmf_rpc_ns_visible(request, params, true); 1943d37555b4SJonas Pfefferle } 1944d37555b4SJonas Pfefferle SPDK_RPC_REGISTER("nvmf_ns_add_host", rpc_nvmf_ns_add_host, SPDK_RPC_RUNTIME) 1945d37555b4SJonas Pfefferle 1946d37555b4SJonas Pfefferle static void 1947d37555b4SJonas Pfefferle rpc_nvmf_ns_remove_host(struct spdk_jsonrpc_request *request, 1948d37555b4SJonas Pfefferle const struct spdk_json_val *params) 1949d37555b4SJonas Pfefferle { 1950d37555b4SJonas Pfefferle nvmf_rpc_ns_visible(request, params, false); 1951d37555b4SJonas Pfefferle } 1952d37555b4SJonas Pfefferle SPDK_RPC_REGISTER("nvmf_ns_remove_host", rpc_nvmf_ns_remove_host, SPDK_RPC_RUNTIME) 1953d37555b4SJonas Pfefferle 1954a54a6a26SSeth Howell struct nvmf_rpc_host_ctx { 19556723bd0cSBen Walker struct spdk_jsonrpc_request *request; 1956a54a6a26SSeth Howell char *nqn; 1957a54a6a26SSeth Howell char *host; 1958f8433aadSSeth Howell char *tgt_name; 19593f4f8ad0SKonrad Sztyber char *dhchap_key; 1960aa13730dSKonrad Sztyber char *dhchap_ctrlr_key; 1961a54a6a26SSeth Howell bool allow_any_host; 1962a54a6a26SSeth Howell }; 1963a54a6a26SSeth Howell 1964a54a6a26SSeth Howell static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = { 1965a54a6a26SSeth Howell {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 1966a54a6a26SSeth Howell {"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string}, 1967f8433aadSSeth Howell {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 19683f4f8ad0SKonrad Sztyber {"dhchap_key", offsetof(struct nvmf_rpc_host_ctx, dhchap_key), spdk_json_decode_string, true}, 1969aa13730dSKonrad Sztyber {"dhchap_ctrlr_key", offsetof(struct nvmf_rpc_host_ctx, dhchap_ctrlr_key), spdk_json_decode_string, true}, 1970a54a6a26SSeth Howell }; 1971a54a6a26SSeth Howell 1972a54a6a26SSeth Howell static void 1973a54a6a26SSeth Howell nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx) 1974a54a6a26SSeth Howell { 1975a54a6a26SSeth Howell free(ctx->nqn); 1976a54a6a26SSeth Howell free(ctx->host); 1977f8433aadSSeth Howell free(ctx->tgt_name); 19783f4f8ad0SKonrad Sztyber free(ctx->dhchap_key); 1979aa13730dSKonrad Sztyber free(ctx->dhchap_ctrlr_key); 1980a54a6a26SSeth Howell } 1981a54a6a26SSeth Howell 1982a54a6a26SSeth Howell static void 1983e569a578SSeth Howell rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request, 1984a54a6a26SSeth Howell const struct spdk_json_val *params) 1985a54a6a26SSeth Howell { 1986ce594c1eSBen Walker struct nvmf_rpc_host_ctx ctx = {}; 1987a54a6a26SSeth Howell struct spdk_nvmf_subsystem *subsystem; 19883f4f8ad0SKonrad Sztyber struct spdk_nvmf_host_opts opts = {}; 1989a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 1990aa13730dSKonrad Sztyber struct spdk_key *key = NULL, *ckey = NULL; 19918ff8bf07SSeth Howell int rc; 1992a54a6a26SSeth Howell 19936803032dSKrzysztof Karas if (spdk_json_decode_object_relaxed(params, nvmf_rpc_subsystem_host_decoder, 1994a54a6a26SSeth Howell SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 1995ce594c1eSBen Walker &ctx)) { 1996a54a6a26SSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1997a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1998012e50f8SKonrad Sztyber goto out; 1999a54a6a26SSeth Howell } 2000a54a6a26SSeth Howell 2001ce594c1eSBen Walker tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 2002a54a6a26SSeth Howell if (!tgt) { 2003a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find a target object.\n"); 2004a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2005a54a6a26SSeth Howell "Unable to find a target."); 2006012e50f8SKonrad Sztyber goto out; 2007a54a6a26SSeth Howell } 2008a54a6a26SSeth Howell 2009ce594c1eSBen Walker subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn); 2010a54a6a26SSeth Howell if (!subsystem) { 2011ce594c1eSBen Walker SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn); 2012a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2013012e50f8SKonrad Sztyber goto out; 2014a54a6a26SSeth Howell } 2015a54a6a26SSeth Howell 20163f4f8ad0SKonrad Sztyber if (ctx.dhchap_key != NULL) { 20173f4f8ad0SKonrad Sztyber key = spdk_keyring_get_key(ctx.dhchap_key); 20183f4f8ad0SKonrad Sztyber if (key == NULL) { 20193f4f8ad0SKonrad Sztyber SPDK_ERRLOG("Unable to find DH-HMAC-CHAP key: %s\n", ctx.dhchap_key); 20203f4f8ad0SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 20213f4f8ad0SKonrad Sztyber "Invalid parameters"); 2022012e50f8SKonrad Sztyber goto out; 20238ff8bf07SSeth Howell } 20243f4f8ad0SKonrad Sztyber } 2025ce594c1eSBen Walker 2026aa13730dSKonrad Sztyber if (ctx.dhchap_ctrlr_key != NULL) { 2027aa13730dSKonrad Sztyber ckey = spdk_keyring_get_key(ctx.dhchap_ctrlr_key); 2028aa13730dSKonrad Sztyber if (ckey == NULL) { 2029aa13730dSKonrad Sztyber SPDK_ERRLOG("Unable to find DH-HMAC-CHAP ctrlr key: %s\n", 2030aa13730dSKonrad Sztyber ctx.dhchap_ctrlr_key); 2031aa13730dSKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2032aa13730dSKonrad Sztyber "Invalid parameters"); 2033aa13730dSKonrad Sztyber goto out; 2034aa13730dSKonrad Sztyber } 2035aa13730dSKonrad Sztyber } 2036aa13730dSKonrad Sztyber 2037aa13730dSKonrad Sztyber opts.size = SPDK_SIZEOF(&opts, dhchap_ctrlr_key); 20383f4f8ad0SKonrad Sztyber opts.params = params; 20393f4f8ad0SKonrad Sztyber opts.dhchap_key = key; 2040aa13730dSKonrad Sztyber opts.dhchap_ctrlr_key = ckey; 20413f4f8ad0SKonrad Sztyber rc = spdk_nvmf_subsystem_add_host_ext(subsystem, ctx.host, &opts); 20423f4f8ad0SKonrad Sztyber if (rc != 0) { 20433f4f8ad0SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 2044012e50f8SKonrad Sztyber goto out; 20453f4f8ad0SKonrad Sztyber } 20463f4f8ad0SKonrad Sztyber 2047d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 2048012e50f8SKonrad Sztyber out: 2049aa13730dSKonrad Sztyber spdk_keyring_put_key(ckey); 2050012e50f8SKonrad Sztyber spdk_keyring_put_key(key); 2051ce594c1eSBen Walker nvmf_rpc_host_ctx_free(&ctx); 2052a54a6a26SSeth Howell } 2053e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_subsystem_add_host", rpc_nvmf_subsystem_add_host, SPDK_RPC_RUNTIME) 2054a54a6a26SSeth Howell 2055a54a6a26SSeth Howell static void 20566723bd0cSBen Walker rpc_nvmf_subsystem_remove_host_done(void *_ctx, int status) 20576723bd0cSBen Walker { 20586723bd0cSBen Walker struct nvmf_rpc_host_ctx *ctx = _ctx; 20596723bd0cSBen Walker 2060d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(ctx->request, true); 20616723bd0cSBen Walker nvmf_rpc_host_ctx_free(ctx); 20626723bd0cSBen Walker free(ctx); 20636723bd0cSBen Walker } 20646723bd0cSBen Walker 20656723bd0cSBen Walker static void 2066e569a578SSeth Howell rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request, 2067a54a6a26SSeth Howell const struct spdk_json_val *params) 2068a54a6a26SSeth Howell { 20696723bd0cSBen Walker struct nvmf_rpc_host_ctx *ctx; 2070a54a6a26SSeth Howell struct spdk_nvmf_subsystem *subsystem; 2071a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 20728ff8bf07SSeth Howell int rc; 2073a54a6a26SSeth Howell 20746723bd0cSBen Walker ctx = calloc(1, sizeof(*ctx)); 20756723bd0cSBen Walker if (ctx == NULL) { 20766723bd0cSBen Walker SPDK_ERRLOG("Unable to allocate context to perform RPC\n"); 20776723bd0cSBen Walker spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 2078a54a6a26SSeth Howell return; 2079a54a6a26SSeth Howell } 2080a54a6a26SSeth Howell 20816723bd0cSBen Walker ctx->request = request; 20826723bd0cSBen Walker 20836723bd0cSBen Walker if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder, 20846723bd0cSBen Walker SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), 20856723bd0cSBen Walker ctx)) { 20866723bd0cSBen Walker SPDK_ERRLOG("spdk_json_decode_object failed\n"); 20876723bd0cSBen Walker spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 20886723bd0cSBen Walker nvmf_rpc_host_ctx_free(ctx); 20896723bd0cSBen Walker free(ctx); 20906723bd0cSBen Walker return; 20916723bd0cSBen Walker } 20926723bd0cSBen Walker 20936723bd0cSBen Walker tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2094a54a6a26SSeth Howell if (!tgt) { 2095a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find a target object.\n"); 2096a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2097a54a6a26SSeth Howell "Unable to find a target."); 20986723bd0cSBen Walker nvmf_rpc_host_ctx_free(ctx); 20996723bd0cSBen Walker free(ctx); 2100a54a6a26SSeth Howell return; 2101a54a6a26SSeth Howell } 2102a54a6a26SSeth Howell 21036723bd0cSBen Walker subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 2104a54a6a26SSeth Howell if (!subsystem) { 21056723bd0cSBen Walker SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 2106a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 21076723bd0cSBen Walker nvmf_rpc_host_ctx_free(ctx); 21086723bd0cSBen Walker free(ctx); 2109a54a6a26SSeth Howell return; 2110a54a6a26SSeth Howell } 2111a54a6a26SSeth Howell 21126723bd0cSBen Walker rc = spdk_nvmf_subsystem_remove_host(subsystem, ctx->host); 21138ff8bf07SSeth Howell if (rc != 0) { 2114a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 21156723bd0cSBen Walker nvmf_rpc_host_ctx_free(ctx); 21166723bd0cSBen Walker free(ctx); 2117ce594c1eSBen Walker return; 21188ff8bf07SSeth Howell } 2119ce594c1eSBen Walker 21206723bd0cSBen Walker rc = spdk_nvmf_subsystem_disconnect_host(subsystem, ctx->host, 21216723bd0cSBen Walker rpc_nvmf_subsystem_remove_host_done, 21226723bd0cSBen Walker ctx); 21236723bd0cSBen Walker if (rc != 0) { 21246723bd0cSBen Walker spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 21256723bd0cSBen Walker nvmf_rpc_host_ctx_free(ctx); 21266723bd0cSBen Walker free(ctx); 21276723bd0cSBen Walker return; 21286723bd0cSBen Walker } 2129a54a6a26SSeth Howell } 2130e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", rpc_nvmf_subsystem_remove_host, 2131a54a6a26SSeth Howell SPDK_RPC_RUNTIME) 2132a54a6a26SSeth Howell 21338a4b7226SKonrad Sztyber static void 21348a4b7226SKonrad Sztyber rpc_nvmf_subsystem_set_keys(struct spdk_jsonrpc_request *request, 21358a4b7226SKonrad Sztyber const struct spdk_json_val *params) 21368a4b7226SKonrad Sztyber { 21378a4b7226SKonrad Sztyber struct nvmf_rpc_host_ctx ctx = {}; 21388a4b7226SKonrad Sztyber struct spdk_nvmf_subsystem *subsystem; 21398a4b7226SKonrad Sztyber struct spdk_nvmf_subsystem_key_opts opts = {}; 21408a4b7226SKonrad Sztyber struct spdk_nvmf_tgt *tgt; 21418a4b7226SKonrad Sztyber struct spdk_key *key = NULL, *ckey = NULL; 21428a4b7226SKonrad Sztyber int rc; 21438a4b7226SKonrad Sztyber 21448a4b7226SKonrad Sztyber if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder, 21458a4b7226SKonrad Sztyber SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder), &ctx)) { 21468a4b7226SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 21478a4b7226SKonrad Sztyber "Invalid parameters"); 21488a4b7226SKonrad Sztyber goto out; 21498a4b7226SKonrad Sztyber } 21508a4b7226SKonrad Sztyber 21518a4b7226SKonrad Sztyber tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 21528a4b7226SKonrad Sztyber if (!tgt) { 21538a4b7226SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 21548a4b7226SKonrad Sztyber "Invalid parameters"); 21558a4b7226SKonrad Sztyber goto out; 21568a4b7226SKonrad Sztyber } 21578a4b7226SKonrad Sztyber subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn); 21588a4b7226SKonrad Sztyber if (!subsystem) { 21598a4b7226SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 21608a4b7226SKonrad Sztyber "Invalid parameters"); 21618a4b7226SKonrad Sztyber goto out; 21628a4b7226SKonrad Sztyber } 21638a4b7226SKonrad Sztyber 21648a4b7226SKonrad Sztyber if (ctx.dhchap_key != NULL) { 21658a4b7226SKonrad Sztyber key = spdk_keyring_get_key(ctx.dhchap_key); 21668a4b7226SKonrad Sztyber if (key == NULL) { 21678a4b7226SKonrad Sztyber SPDK_ERRLOG("Unable to find DH-HMAC-CHAP key: %s\n", ctx.dhchap_key); 21688a4b7226SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 21698a4b7226SKonrad Sztyber "Invalid parameters"); 21708a4b7226SKonrad Sztyber goto out; 21718a4b7226SKonrad Sztyber } 21728a4b7226SKonrad Sztyber } 21738a4b7226SKonrad Sztyber if (ctx.dhchap_ctrlr_key != NULL) { 21748a4b7226SKonrad Sztyber ckey = spdk_keyring_get_key(ctx.dhchap_ctrlr_key); 21758a4b7226SKonrad Sztyber if (ckey == NULL) { 21768a4b7226SKonrad Sztyber SPDK_ERRLOG("Unable to find DH-HMAC-CHAP ctrlr key: %s\n", 21778a4b7226SKonrad Sztyber ctx.dhchap_ctrlr_key); 21788a4b7226SKonrad Sztyber spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 21798a4b7226SKonrad Sztyber "Invalid parameters"); 21808a4b7226SKonrad Sztyber goto out; 21818a4b7226SKonrad Sztyber } 21828a4b7226SKonrad Sztyber } 21838a4b7226SKonrad Sztyber 21848a4b7226SKonrad Sztyber opts.size = SPDK_SIZEOF(&opts, dhchap_ctrlr_key); 21858a4b7226SKonrad Sztyber opts.dhchap_key = key; 21868a4b7226SKonrad Sztyber opts.dhchap_ctrlr_key = ckey; 21878a4b7226SKonrad Sztyber rc = spdk_nvmf_subsystem_set_keys(subsystem, ctx.host, &opts); 21888a4b7226SKonrad Sztyber if (rc != 0) { 21898a4b7226SKonrad Sztyber spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 21908a4b7226SKonrad Sztyber goto out; 21918a4b7226SKonrad Sztyber } 21928a4b7226SKonrad Sztyber 21938a4b7226SKonrad Sztyber spdk_jsonrpc_send_bool_response(request, true); 21948a4b7226SKonrad Sztyber out: 21958a4b7226SKonrad Sztyber spdk_keyring_put_key(ckey); 21968a4b7226SKonrad Sztyber spdk_keyring_put_key(key); 21978a4b7226SKonrad Sztyber nvmf_rpc_host_ctx_free(&ctx); 21988a4b7226SKonrad Sztyber } 21998a4b7226SKonrad Sztyber SPDK_RPC_REGISTER("nvmf_subsystem_set_keys", rpc_nvmf_subsystem_set_keys, SPDK_RPC_RUNTIME) 2200a54a6a26SSeth Howell 2201a54a6a26SSeth Howell static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = { 2202a54a6a26SSeth Howell {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string}, 2203a54a6a26SSeth Howell {"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool}, 2204f8433aadSSeth Howell {"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true}, 2205a54a6a26SSeth Howell }; 2206a54a6a26SSeth Howell 2207a54a6a26SSeth Howell static void 2208e569a578SSeth Howell rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request, 2209a54a6a26SSeth Howell const struct spdk_json_val *params) 2210a54a6a26SSeth Howell { 2211ce594c1eSBen Walker struct nvmf_rpc_host_ctx ctx = {}; 2212a54a6a26SSeth Howell struct spdk_nvmf_subsystem *subsystem; 2213a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 22148ff8bf07SSeth Howell int rc; 2215a54a6a26SSeth Howell 2216a54a6a26SSeth Howell if (spdk_json_decode_object(params, nvmf_rpc_subsystem_any_host_decoder, 2217a54a6a26SSeth Howell SPDK_COUNTOF(nvmf_rpc_subsystem_any_host_decoder), 2218ce594c1eSBen Walker &ctx)) { 2219a54a6a26SSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2220a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2221ce594c1eSBen Walker nvmf_rpc_host_ctx_free(&ctx); 2222a54a6a26SSeth Howell return; 2223a54a6a26SSeth Howell } 2224a54a6a26SSeth Howell 2225ce594c1eSBen Walker tgt = spdk_nvmf_get_tgt(ctx.tgt_name); 2226a54a6a26SSeth Howell if (!tgt) { 2227a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find a target object.\n"); 2228a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2229a54a6a26SSeth Howell "Unable to find a target."); 2230ce594c1eSBen Walker nvmf_rpc_host_ctx_free(&ctx); 2231a54a6a26SSeth Howell return; 2232a54a6a26SSeth Howell } 2233a54a6a26SSeth Howell 2234ce594c1eSBen Walker subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn); 2235a54a6a26SSeth Howell if (!subsystem) { 2236ce594c1eSBen Walker SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn); 2237a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2238ce594c1eSBen Walker nvmf_rpc_host_ctx_free(&ctx); 2239a54a6a26SSeth Howell return; 2240a54a6a26SSeth Howell } 2241a54a6a26SSeth Howell 2242ce594c1eSBen Walker rc = spdk_nvmf_subsystem_set_allow_any_host(subsystem, ctx.allow_any_host); 22438ff8bf07SSeth Howell if (rc != 0) { 2244a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 2245ce594c1eSBen Walker nvmf_rpc_host_ctx_free(&ctx); 2246ce594c1eSBen Walker return; 22478ff8bf07SSeth Howell } 2248ce594c1eSBen Walker 2249d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 2250ce594c1eSBen Walker nvmf_rpc_host_ctx_free(&ctx); 2251a54a6a26SSeth Howell } 2252e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", rpc_nvmf_subsystem_allow_any_host, 2253a54a6a26SSeth Howell SPDK_RPC_RUNTIME) 2254a54a6a26SSeth Howell 2255c9b89ef1SSeth Howell struct nvmf_rpc_target_ctx { 2256c9b89ef1SSeth Howell char *name; 2257c9b89ef1SSeth Howell uint32_t max_subsystems; 22583d8904c6SAlexey Marchuk char *discovery_filter; 2259c9b89ef1SSeth Howell }; 2260c9b89ef1SSeth Howell 22613d8904c6SAlexey Marchuk static int 22623d8904c6SAlexey Marchuk decode_discovery_filter(const struct spdk_json_val *val, void *out) 22633d8904c6SAlexey Marchuk { 2264dc9f61a3SKonrad Sztyber uint32_t *_filter = out; 2265dc9f61a3SKonrad Sztyber uint32_t filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY; 22663d8904c6SAlexey Marchuk char *tokens = spdk_json_strdup(val); 22673d8904c6SAlexey Marchuk char *tok; 2268*b37db069SXuQi char *sp = NULL; 22693d8904c6SAlexey Marchuk int rc = -EINVAL; 22703d8904c6SAlexey Marchuk bool all_specified = false; 22713d8904c6SAlexey Marchuk 22723d8904c6SAlexey Marchuk if (!tokens) { 22733d8904c6SAlexey Marchuk return -ENOMEM; 22743d8904c6SAlexey Marchuk } 22753d8904c6SAlexey Marchuk 2276*b37db069SXuQi tok = strtok_r(tokens, ",", &sp); 22773d8904c6SAlexey Marchuk while (tok) { 22783d8904c6SAlexey Marchuk if (strncmp(tok, "match_any", 9) == 0) { 22793d8904c6SAlexey Marchuk if (filter != SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY) { 22803d8904c6SAlexey Marchuk goto out; 22813d8904c6SAlexey Marchuk } 22823d8904c6SAlexey Marchuk filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY; 22833d8904c6SAlexey Marchuk all_specified = true; 22843d8904c6SAlexey Marchuk } else { 22853d8904c6SAlexey Marchuk if (all_specified) { 22863d8904c6SAlexey Marchuk goto out; 22873d8904c6SAlexey Marchuk } 22883d8904c6SAlexey Marchuk if (strncmp(tok, "transport", 9) == 0) { 22893d8904c6SAlexey Marchuk filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE; 22903d8904c6SAlexey Marchuk } else if (strncmp(tok, "address", 7) == 0) { 22913d8904c6SAlexey Marchuk filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS; 22923d8904c6SAlexey Marchuk } else if (strncmp(tok, "svcid", 5) == 0) { 22933d8904c6SAlexey Marchuk filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID; 22943d8904c6SAlexey Marchuk } else { 22953d8904c6SAlexey Marchuk SPDK_ERRLOG("Invalid value %s\n", tok); 22963d8904c6SAlexey Marchuk goto out; 22973d8904c6SAlexey Marchuk } 22983d8904c6SAlexey Marchuk } 22993d8904c6SAlexey Marchuk 2300*b37db069SXuQi tok = strtok_r(NULL, ",", &sp); 23013d8904c6SAlexey Marchuk } 23023d8904c6SAlexey Marchuk 23033d8904c6SAlexey Marchuk rc = 0; 23043d8904c6SAlexey Marchuk *_filter = filter; 23053d8904c6SAlexey Marchuk 23063d8904c6SAlexey Marchuk out: 23073d8904c6SAlexey Marchuk free(tokens); 23083d8904c6SAlexey Marchuk 23093d8904c6SAlexey Marchuk return rc; 23103d8904c6SAlexey Marchuk } 23113d8904c6SAlexey Marchuk 2312c9b89ef1SSeth Howell static const struct spdk_json_object_decoder nvmf_rpc_create_target_decoder[] = { 2313c9b89ef1SSeth Howell {"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string}, 2314c9b89ef1SSeth Howell {"max_subsystems", offsetof(struct nvmf_rpc_target_ctx, max_subsystems), spdk_json_decode_uint32, true}, 23153d8904c6SAlexey Marchuk {"discovery_filter", offsetof(struct nvmf_rpc_target_ctx, discovery_filter), decode_discovery_filter, true} 2316c9b89ef1SSeth Howell }; 2317c9b89ef1SSeth Howell 2318c9b89ef1SSeth Howell static void 2319e569a578SSeth Howell rpc_nvmf_create_target(struct spdk_jsonrpc_request *request, 2320c9b89ef1SSeth Howell const struct spdk_json_val *params) 2321c9b89ef1SSeth Howell { 2322c9b89ef1SSeth Howell struct spdk_nvmf_target_opts opts; 2323c9b89ef1SSeth Howell struct nvmf_rpc_target_ctx ctx = {0}; 2324c9b89ef1SSeth Howell struct spdk_nvmf_tgt *tgt; 2325c9b89ef1SSeth Howell struct spdk_json_write_ctx *w; 2326c9b89ef1SSeth Howell 2327c9b89ef1SSeth Howell /* Decode parameters the first time to get the transport type */ 2328c9b89ef1SSeth Howell if (spdk_json_decode_object(params, nvmf_rpc_create_target_decoder, 2329c9b89ef1SSeth Howell SPDK_COUNTOF(nvmf_rpc_create_target_decoder), 2330c9b89ef1SSeth Howell &ctx)) { 2331c9b89ef1SSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2332c9b89ef1SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 23333d8904c6SAlexey Marchuk goto out; 2334c9b89ef1SSeth Howell } 2335c9b89ef1SSeth Howell 2336c9b89ef1SSeth Howell snprintf(opts.name, NVMF_TGT_NAME_MAX_LENGTH, "%s", ctx.name); 2337c9b89ef1SSeth Howell opts.max_subsystems = ctx.max_subsystems; 233863454e89SKonrad Sztyber opts.size = SPDK_SIZEOF(&opts, discovery_filter); 2339c9b89ef1SSeth Howell 2340c9b89ef1SSeth Howell if (spdk_nvmf_get_tgt(opts.name) != NULL) { 2341c9b89ef1SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2342c9b89ef1SSeth Howell "Target already exists."); 23433d8904c6SAlexey Marchuk goto out; 2344c9b89ef1SSeth Howell } 2345c9b89ef1SSeth Howell 2346c9b89ef1SSeth Howell tgt = spdk_nvmf_tgt_create(&opts); 2347c9b89ef1SSeth Howell 2348c9b89ef1SSeth Howell if (tgt == NULL) { 2349c9b89ef1SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2350c9b89ef1SSeth Howell "Unable to create the requested target."); 23513d8904c6SAlexey Marchuk goto out; 2352c9b89ef1SSeth Howell } 2353c9b89ef1SSeth Howell 2354c9b89ef1SSeth Howell w = spdk_jsonrpc_begin_result(request); 2355c9b89ef1SSeth Howell spdk_json_write_string(w, spdk_nvmf_tgt_get_name(tgt)); 2356c9b89ef1SSeth Howell spdk_jsonrpc_end_result(request, w); 23573d8904c6SAlexey Marchuk out: 2358c9b89ef1SSeth Howell free(ctx.name); 23593d8904c6SAlexey Marchuk free(ctx.discovery_filter); 2360c9b89ef1SSeth Howell } 2361e2a4288cSMonica Kenguva /* private */ SPDK_RPC_REGISTER("nvmf_create_target", rpc_nvmf_create_target, SPDK_RPC_RUNTIME); 2362c9b89ef1SSeth Howell 2363099489b2SSeth Howell static const struct spdk_json_object_decoder nvmf_rpc_destroy_target_decoder[] = { 2364099489b2SSeth Howell {"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string}, 2365099489b2SSeth Howell }; 2366099489b2SSeth Howell 2367099489b2SSeth Howell static void 2368099489b2SSeth Howell nvmf_rpc_destroy_target_done(void *ctx, int status) 2369099489b2SSeth Howell { 2370099489b2SSeth Howell struct spdk_jsonrpc_request *request = ctx; 2371099489b2SSeth Howell 2372d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(request, true); 2373099489b2SSeth Howell } 2374099489b2SSeth Howell 2375099489b2SSeth Howell static void 2376e569a578SSeth Howell rpc_nvmf_delete_target(struct spdk_jsonrpc_request *request, 2377099489b2SSeth Howell const struct spdk_json_val *params) 2378099489b2SSeth Howell { 2379099489b2SSeth Howell struct nvmf_rpc_target_ctx ctx = {0}; 2380099489b2SSeth Howell struct spdk_nvmf_tgt *tgt; 2381099489b2SSeth Howell 2382099489b2SSeth Howell /* Decode parameters the first time to get the transport type */ 2383099489b2SSeth Howell if (spdk_json_decode_object(params, nvmf_rpc_destroy_target_decoder, 2384099489b2SSeth Howell SPDK_COUNTOF(nvmf_rpc_destroy_target_decoder), 2385099489b2SSeth Howell &ctx)) { 2386099489b2SSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2387099489b2SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2388099489b2SSeth Howell free(ctx.name); 2389099489b2SSeth Howell return; 2390099489b2SSeth Howell } 2391099489b2SSeth Howell 2392099489b2SSeth Howell tgt = spdk_nvmf_get_tgt(ctx.name); 2393099489b2SSeth Howell 2394099489b2SSeth Howell if (tgt == NULL) { 2395099489b2SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2396099489b2SSeth Howell "The specified target doesn't exist, cannot delete it."); 2397099489b2SSeth Howell free(ctx.name); 2398099489b2SSeth Howell return; 2399099489b2SSeth Howell } 2400099489b2SSeth Howell 2401099489b2SSeth Howell spdk_nvmf_tgt_destroy(tgt, nvmf_rpc_destroy_target_done, request); 2402099489b2SSeth Howell free(ctx.name); 2403099489b2SSeth Howell } 2404e2a4288cSMonica Kenguva /* private */ SPDK_RPC_REGISTER("nvmf_delete_target", rpc_nvmf_delete_target, SPDK_RPC_RUNTIME); 2405099489b2SSeth Howell 2406208e089aSSeth Howell static void 2407e569a578SSeth Howell rpc_nvmf_get_targets(struct spdk_jsonrpc_request *request, 2408208e089aSSeth Howell const struct spdk_json_val *params) 2409208e089aSSeth Howell { 2410208e089aSSeth Howell struct spdk_json_write_ctx *w; 2411208e089aSSeth Howell struct spdk_nvmf_tgt *tgt; 2412208e089aSSeth Howell const char *name; 2413208e089aSSeth Howell 2414208e089aSSeth Howell if (params != NULL) { 2415208e089aSSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 2416208e089aSSeth Howell "nvmf_get_targets has no parameters."); 2417208e089aSSeth Howell return; 2418208e089aSSeth Howell } 2419208e089aSSeth Howell 2420208e089aSSeth Howell w = spdk_jsonrpc_begin_result(request); 2421208e089aSSeth Howell spdk_json_write_array_begin(w); 2422208e089aSSeth Howell 2423208e089aSSeth Howell tgt = spdk_nvmf_get_first_tgt(); 2424208e089aSSeth Howell 2425208e089aSSeth Howell while (tgt != NULL) { 2426208e089aSSeth Howell name = spdk_nvmf_tgt_get_name(tgt); 2427208e089aSSeth Howell spdk_json_write_string(w, name); 2428208e089aSSeth Howell tgt = spdk_nvmf_get_next_tgt(tgt); 2429208e089aSSeth Howell } 2430208e089aSSeth Howell 2431208e089aSSeth Howell spdk_json_write_array_end(w); 2432208e089aSSeth Howell spdk_jsonrpc_end_result(request, w); 2433208e089aSSeth Howell } 2434e2a4288cSMonica Kenguva /* private */ SPDK_RPC_REGISTER("nvmf_get_targets", rpc_nvmf_get_targets, SPDK_RPC_RUNTIME); 2435208e089aSSeth Howell 2436a54a6a26SSeth Howell struct nvmf_rpc_create_transport_ctx { 2437a54a6a26SSeth Howell char *trtype; 2438f8433aadSSeth Howell char *tgt_name; 2439a54a6a26SSeth Howell struct spdk_nvmf_transport_opts opts; 2440a54a6a26SSeth Howell struct spdk_jsonrpc_request *request; 2441fb4398efSAlexey Marchuk struct spdk_nvmf_transport *transport; 2442fb4398efSAlexey Marchuk int status; 2443a54a6a26SSeth Howell }; 2444a54a6a26SSeth Howell 24451551197dSAlexey Marchuk /** 24461551197dSAlexey Marchuk * `max_qpairs_per_ctrlr` represents both admin and IO qpairs, that confuses 24471551197dSAlexey Marchuk * users when they configure a transport using RPC. So it was decided to 24481551197dSAlexey Marchuk * deprecate `max_qpairs_per_ctrlr` RPC parameter and use `max_io_qpairs_per_ctrlr` 24491551197dSAlexey Marchuk * But internal logic remains unchanged and SPDK expects that 24501551197dSAlexey Marchuk * spdk_nvmf_transport_opts::max_qpairs_per_ctrlr includes an admin qpair. 24511551197dSAlexey Marchuk * This function parses the number of IO qpairs and adds +1 for admin qpair. 24521551197dSAlexey Marchuk */ 24531551197dSAlexey Marchuk static int 24541551197dSAlexey Marchuk nvmf_rpc_decode_max_io_qpairs(const struct spdk_json_val *val, void *out) 24551551197dSAlexey Marchuk { 24561551197dSAlexey Marchuk uint16_t *i = out; 24571551197dSAlexey Marchuk int rc; 24581551197dSAlexey Marchuk 24591551197dSAlexey Marchuk rc = spdk_json_number_to_uint16(val, i); 24601551197dSAlexey Marchuk if (rc == 0) { 24611551197dSAlexey Marchuk (*i)++; 24621551197dSAlexey Marchuk } 24631551197dSAlexey Marchuk 24641551197dSAlexey Marchuk return rc; 24651551197dSAlexey Marchuk } 24661551197dSAlexey Marchuk 2467a54a6a26SSeth Howell static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[] = { 2468a54a6a26SSeth Howell { "trtype", offsetof(struct nvmf_rpc_create_transport_ctx, trtype), spdk_json_decode_string}, 2469a54a6a26SSeth Howell { 2470a54a6a26SSeth Howell "max_queue_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_queue_depth), 2471a54a6a26SSeth Howell spdk_json_decode_uint16, true 2472a54a6a26SSeth Howell }, 2473a54a6a26SSeth Howell { 24741551197dSAlexey Marchuk "max_io_qpairs_per_ctrlr", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_qpairs_per_ctrlr), 24751551197dSAlexey Marchuk nvmf_rpc_decode_max_io_qpairs, true 2476a54a6a26SSeth Howell }, 2477a54a6a26SSeth Howell { 2478a54a6a26SSeth Howell "in_capsule_data_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.in_capsule_data_size), 2479a54a6a26SSeth Howell spdk_json_decode_uint32, true 2480a54a6a26SSeth Howell }, 2481a54a6a26SSeth Howell { 2482a54a6a26SSeth Howell "max_io_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_io_size), 2483a54a6a26SSeth Howell spdk_json_decode_uint32, true 2484a54a6a26SSeth Howell }, 2485a54a6a26SSeth Howell { 2486a54a6a26SSeth Howell "io_unit_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.io_unit_size), 2487a54a6a26SSeth Howell spdk_json_decode_uint32, true 2488a54a6a26SSeth Howell }, 2489a54a6a26SSeth Howell { 2490a54a6a26SSeth Howell "max_aq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_aq_depth), 2491a54a6a26SSeth Howell spdk_json_decode_uint32, true 2492a54a6a26SSeth Howell }, 2493a54a6a26SSeth Howell { 2494a54a6a26SSeth Howell "num_shared_buffers", offsetof(struct nvmf_rpc_create_transport_ctx, opts.num_shared_buffers), 2495a54a6a26SSeth Howell spdk_json_decode_uint32, true 2496a54a6a26SSeth Howell }, 2497a54a6a26SSeth Howell { 2498a54a6a26SSeth Howell "buf_cache_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.buf_cache_size), 2499a54a6a26SSeth Howell spdk_json_decode_uint32, true 2500a54a6a26SSeth Howell }, 2501a54a6a26SSeth Howell { 2502a54a6a26SSeth Howell "dif_insert_or_strip", offsetof(struct nvmf_rpc_create_transport_ctx, opts.dif_insert_or_strip), 2503a54a6a26SSeth Howell spdk_json_decode_bool, true 2504a54a6a26SSeth Howell }, 2505a54a6a26SSeth Howell { 250626e0ef9aSShuhei Matsumoto "abort_timeout_sec", offsetof(struct nvmf_rpc_create_transport_ctx, opts.abort_timeout_sec), 250726e0ef9aSShuhei Matsumoto spdk_json_decode_uint32, true 250826e0ef9aSShuhei Matsumoto }, 250926e0ef9aSShuhei Matsumoto { 2510aa1d0398SKonrad Sztyber "zcopy", offsetof(struct nvmf_rpc_create_transport_ctx, opts.zcopy), 2511aa1d0398SKonrad Sztyber spdk_json_decode_bool, true 2512aa1d0398SKonrad Sztyber }, 2513aa1d0398SKonrad Sztyber { 2514f8433aadSSeth Howell "tgt_name", offsetof(struct nvmf_rpc_create_transport_ctx, tgt_name), 2515f8433aadSSeth Howell spdk_json_decode_string, true 2516f8433aadSSeth Howell }, 251743022da3SJacek Kalwas { 251843022da3SJacek Kalwas "acceptor_poll_rate", offsetof(struct nvmf_rpc_create_transport_ctx, opts.acceptor_poll_rate), 251943022da3SJacek Kalwas spdk_json_decode_uint32, true 252043022da3SJacek Kalwas }, 252179606beeSKonrad Sztyber { 252279606beeSKonrad Sztyber "ack_timeout", offsetof(struct nvmf_rpc_create_transport_ctx, opts.ack_timeout), 252379606beeSKonrad Sztyber spdk_json_decode_uint32, true 25247dab13c0SAlexey Marchuk }, 25257dab13c0SAlexey Marchuk { 25267dab13c0SAlexey Marchuk "data_wr_pool_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.data_wr_pool_size), 25277dab13c0SAlexey Marchuk spdk_json_decode_uint32, true 252865335336SKonrad Sztyber }, 252965335336SKonrad Sztyber { 253065335336SKonrad Sztyber "disable_command_passthru", offsetof(struct nvmf_rpc_create_transport_ctx, opts.disable_command_passthru), 253165335336SKonrad Sztyber spdk_json_decode_bool, true 253279606beeSKonrad Sztyber } 2533a54a6a26SSeth Howell }; 2534a54a6a26SSeth Howell 2535a54a6a26SSeth Howell static void 2536a54a6a26SSeth Howell nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx) 2537a54a6a26SSeth Howell { 2538a54a6a26SSeth Howell free(ctx->trtype); 2539f8433aadSSeth Howell free(ctx->tgt_name); 2540a54a6a26SSeth Howell free(ctx); 2541a54a6a26SSeth Howell } 2542a54a6a26SSeth Howell 2543a54a6a26SSeth Howell static void 2544fb4398efSAlexey Marchuk nvmf_rpc_transport_destroy_done_cb(void *cb_arg) 2545fb4398efSAlexey Marchuk { 2546fb4398efSAlexey Marchuk struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2547fb4398efSAlexey Marchuk 2548fb4398efSAlexey Marchuk spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2549fb4398efSAlexey Marchuk "Failed to add transport to tgt.(%d)", ctx->status); 2550fb4398efSAlexey Marchuk nvmf_rpc_create_transport_ctx_free(ctx); 2551fb4398efSAlexey Marchuk } 2552fb4398efSAlexey Marchuk 2553fb4398efSAlexey Marchuk static void 2554a54a6a26SSeth Howell nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status) 2555a54a6a26SSeth Howell { 2556a54a6a26SSeth Howell struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 2557a54a6a26SSeth Howell 2558a54a6a26SSeth Howell if (status) { 2559a54a6a26SSeth Howell SPDK_ERRLOG("Failed to add transport to tgt.(%d)\n", status); 2560fb4398efSAlexey Marchuk ctx->status = status; 2561fb4398efSAlexey Marchuk spdk_nvmf_transport_destroy(ctx->transport, nvmf_rpc_transport_destroy_done_cb, ctx); 2562a54a6a26SSeth Howell return; 2563a54a6a26SSeth Howell } 2564a54a6a26SSeth Howell 2565fb4398efSAlexey Marchuk spdk_jsonrpc_send_bool_response(ctx->request, true); 2566fb4398efSAlexey Marchuk nvmf_rpc_create_transport_ctx_free(ctx); 2567a54a6a26SSeth Howell } 2568a54a6a26SSeth Howell 2569a54a6a26SSeth Howell static void 257096073478SJacek Kalwas nvmf_rpc_create_transport_done(void *cb_arg, struct spdk_nvmf_transport *transport) 257196073478SJacek Kalwas { 257296073478SJacek Kalwas struct nvmf_rpc_create_transport_ctx *ctx = cb_arg; 257396073478SJacek Kalwas 257496073478SJacek Kalwas if (!transport) { 257596073478SJacek Kalwas SPDK_ERRLOG("Failed to create transport.\n"); 257696073478SJacek Kalwas spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 257796073478SJacek Kalwas "Failed to create transport."); 257896073478SJacek Kalwas nvmf_rpc_create_transport_ctx_free(ctx); 257996073478SJacek Kalwas return; 258096073478SJacek Kalwas } 258196073478SJacek Kalwas 258296073478SJacek Kalwas ctx->transport = transport; 258396073478SJacek Kalwas 258496073478SJacek Kalwas spdk_nvmf_tgt_add_transport(spdk_nvmf_get_tgt(ctx->tgt_name), transport, 258596073478SJacek Kalwas nvmf_rpc_tgt_add_transport_done, ctx); 258696073478SJacek Kalwas } 258796073478SJacek Kalwas 258896073478SJacek Kalwas static void 2589e569a578SSeth Howell rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request, 2590a54a6a26SSeth Howell const struct spdk_json_val *params) 2591a54a6a26SSeth Howell { 2592a54a6a26SSeth Howell struct nvmf_rpc_create_transport_ctx *ctx; 2593a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 259496073478SJacek Kalwas int rc; 2595a54a6a26SSeth Howell 2596a54a6a26SSeth Howell ctx = calloc(1, sizeof(*ctx)); 2597a54a6a26SSeth Howell if (!ctx) { 2598a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 2599a54a6a26SSeth Howell return; 2600a54a6a26SSeth Howell } 2601a54a6a26SSeth Howell 2602a54a6a26SSeth Howell /* Decode parameters the first time to get the transport type */ 2603f766d1e4SDarek Stojaczyk if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder, 2604a54a6a26SSeth Howell SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 2605a54a6a26SSeth Howell ctx)) { 2606f766d1e4SDarek Stojaczyk SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 2607a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2608a54a6a26SSeth Howell nvmf_rpc_create_transport_ctx_free(ctx); 2609a54a6a26SSeth Howell return; 2610a54a6a26SSeth Howell } 2611a54a6a26SSeth Howell 2612f8433aadSSeth Howell tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2613a54a6a26SSeth Howell if (!tgt) { 2614a54a6a26SSeth Howell SPDK_ERRLOG("Unable to find a target object.\n"); 2615a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2616a54a6a26SSeth Howell "Unable to find a target."); 2617a54a6a26SSeth Howell nvmf_rpc_create_transport_ctx_free(ctx); 2618a54a6a26SSeth Howell return; 2619a54a6a26SSeth Howell } 2620a54a6a26SSeth Howell 2621a54a6a26SSeth Howell /* Initialize all the transport options (based on transport type) and decode the 2622a54a6a26SSeth Howell * parameters again to update any options passed in rpc create transport call. 2623a54a6a26SSeth Howell */ 26243b16c6ddSZiye Yang if (!spdk_nvmf_transport_opts_init(ctx->trtype, &ctx->opts, sizeof(ctx->opts))) { 2625a54a6a26SSeth Howell /* This can happen if user specifies PCIE transport type which isn't valid for 2626a54a6a26SSeth Howell * NVMe-oF. 2627a54a6a26SSeth Howell */ 2628a54a6a26SSeth Howell SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype); 2629a54a6a26SSeth Howell spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 263010f712bcSwanghailiangx "Invalid transport type '%s'", ctx->trtype); 2631a54a6a26SSeth Howell nvmf_rpc_create_transport_ctx_free(ctx); 2632a54a6a26SSeth Howell return; 2633a54a6a26SSeth Howell } 2634a54a6a26SSeth Howell 2635f766d1e4SDarek Stojaczyk if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder, 2636a54a6a26SSeth Howell SPDK_COUNTOF(nvmf_rpc_create_transport_decoder), 2637a54a6a26SSeth Howell ctx)) { 2638f766d1e4SDarek Stojaczyk SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n"); 2639a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2640a54a6a26SSeth Howell nvmf_rpc_create_transport_ctx_free(ctx); 2641a54a6a26SSeth Howell return; 2642a54a6a26SSeth Howell } 2643a54a6a26SSeth Howell 2644b397546eSSeth Howell if (spdk_nvmf_tgt_get_transport(tgt, ctx->trtype)) { 2645a54a6a26SSeth Howell SPDK_ERRLOG("Transport type '%s' already exists\n", ctx->trtype); 2646a54a6a26SSeth Howell spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 264710f712bcSwanghailiangx "Transport type '%s' already exists", ctx->trtype); 2648a54a6a26SSeth Howell nvmf_rpc_create_transport_ctx_free(ctx); 2649a54a6a26SSeth Howell return; 2650a54a6a26SSeth Howell } 2651a54a6a26SSeth Howell 2652f766d1e4SDarek Stojaczyk /* Transport can parse additional params themselves */ 2653f766d1e4SDarek Stojaczyk ctx->opts.transport_specific = params; 265496073478SJacek Kalwas ctx->request = request; 2655f766d1e4SDarek Stojaczyk 265696073478SJacek Kalwas rc = spdk_nvmf_transport_create_async(ctx->trtype, &ctx->opts, nvmf_rpc_create_transport_done, ctx); 265796073478SJacek Kalwas if (rc) { 2658a54a6a26SSeth Howell SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype); 2659a54a6a26SSeth Howell spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 266010f712bcSwanghailiangx "Transport type '%s' create failed", ctx->trtype); 2661a54a6a26SSeth Howell nvmf_rpc_create_transport_ctx_free(ctx); 2662a54a6a26SSeth Howell } 2663a54a6a26SSeth Howell } 2664e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_create_transport", rpc_nvmf_create_transport, SPDK_RPC_RUNTIME) 2665a54a6a26SSeth Howell 2666f8433aadSSeth Howell struct rpc_get_transport { 2667fb335cb2SJacek Kalwas char *trtype; 2668f8433aadSSeth Howell char *tgt_name; 2669f8433aadSSeth Howell }; 2670f8433aadSSeth Howell 2671f8433aadSSeth Howell static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = { 2672fb335cb2SJacek Kalwas {"trtype", offsetof(struct rpc_get_transport, trtype), spdk_json_decode_string, true}, 2673f8433aadSSeth Howell {"tgt_name", offsetof(struct rpc_get_transport, tgt_name), spdk_json_decode_string, true}, 2674f8433aadSSeth Howell }; 2675f8433aadSSeth Howell 2676a54a6a26SSeth Howell static void 2677e569a578SSeth Howell rpc_nvmf_get_transports(struct spdk_jsonrpc_request *request, 2678a54a6a26SSeth Howell const struct spdk_json_val *params) 2679a54a6a26SSeth Howell { 2680f8433aadSSeth Howell struct rpc_get_transport req = { 0 }; 2681a54a6a26SSeth Howell struct spdk_json_write_ctx *w; 2682fb335cb2SJacek Kalwas struct spdk_nvmf_transport *transport = NULL; 2683a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 2684a54a6a26SSeth Howell 2685f8433aadSSeth Howell if (params) { 2686f8433aadSSeth Howell if (spdk_json_decode_object(params, rpc_get_transport_decoders, 2687f8433aadSSeth Howell SPDK_COUNTOF(rpc_get_transport_decoders), 2688f8433aadSSeth Howell &req)) { 2689f8433aadSSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2690f8433aadSSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2691a54a6a26SSeth Howell return; 2692a54a6a26SSeth Howell } 2693f8433aadSSeth Howell } 2694a54a6a26SSeth Howell 2695f8433aadSSeth Howell tgt = spdk_nvmf_get_tgt(req.tgt_name); 2696a54a6a26SSeth Howell if (!tgt) { 2697a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2698a54a6a26SSeth Howell "Unable to find a target."); 2699fb335cb2SJacek Kalwas free(req.trtype); 2700f8433aadSSeth Howell free(req.tgt_name); 2701a54a6a26SSeth Howell return; 2702a54a6a26SSeth Howell } 2703a54a6a26SSeth Howell 2704fb335cb2SJacek Kalwas if (req.trtype) { 2705fb335cb2SJacek Kalwas transport = spdk_nvmf_tgt_get_transport(tgt, req.trtype); 2706fb335cb2SJacek Kalwas if (transport == NULL) { 2707fb335cb2SJacek Kalwas SPDK_ERRLOG("transport '%s' does not exist\n", req.trtype); 2708fb335cb2SJacek Kalwas spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 2709fb335cb2SJacek Kalwas free(req.trtype); 2710fb335cb2SJacek Kalwas free(req.tgt_name); 2711fb335cb2SJacek Kalwas return; 2712fb335cb2SJacek Kalwas } 2713fb335cb2SJacek Kalwas } 2714fb335cb2SJacek Kalwas 2715a54a6a26SSeth Howell w = spdk_jsonrpc_begin_result(request); 2716a54a6a26SSeth Howell spdk_json_write_array_begin(w); 2717fb335cb2SJacek Kalwas 2718fb335cb2SJacek Kalwas if (transport) { 2719220bcf7dSJacek Kalwas nvmf_transport_dump_opts(transport, w, false); 2720fb335cb2SJacek Kalwas } else { 2721fb335cb2SJacek Kalwas for (transport = spdk_nvmf_transport_get_first(tgt); transport != NULL; 2722fb335cb2SJacek Kalwas transport = spdk_nvmf_transport_get_next(transport)) { 2723fb335cb2SJacek Kalwas nvmf_transport_dump_opts(transport, w, false); 2724a54a6a26SSeth Howell } 2725fb335cb2SJacek Kalwas } 2726fb335cb2SJacek Kalwas 2727a54a6a26SSeth Howell spdk_json_write_array_end(w); 2728a54a6a26SSeth Howell spdk_jsonrpc_end_result(request, w); 2729fb335cb2SJacek Kalwas free(req.trtype); 2730f8433aadSSeth Howell free(req.tgt_name); 2731a54a6a26SSeth Howell } 2732e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_get_transports", rpc_nvmf_get_transports, SPDK_RPC_RUNTIME) 2733a54a6a26SSeth Howell 2734a54a6a26SSeth Howell struct rpc_nvmf_get_stats_ctx { 2735f8433aadSSeth Howell char *tgt_name; 2736a54a6a26SSeth Howell struct spdk_nvmf_tgt *tgt; 2737a54a6a26SSeth Howell struct spdk_jsonrpc_request *request; 2738a54a6a26SSeth Howell struct spdk_json_write_ctx *w; 2739a54a6a26SSeth Howell }; 2740a54a6a26SSeth Howell 2741f8433aadSSeth Howell static const struct spdk_json_object_decoder rpc_get_stats_decoders[] = { 2742f8433aadSSeth Howell {"tgt_name", offsetof(struct rpc_nvmf_get_stats_ctx, tgt_name), spdk_json_decode_string, true}, 2743f8433aadSSeth Howell }; 2744f8433aadSSeth Howell 2745f8433aadSSeth Howell static void 2746f8433aadSSeth Howell free_get_stats_ctx(struct rpc_nvmf_get_stats_ctx *ctx) 2747f8433aadSSeth Howell { 2748f8433aadSSeth Howell free(ctx->tgt_name); 2749f8433aadSSeth Howell free(ctx); 2750f8433aadSSeth Howell } 2751f8433aadSSeth Howell 2752a54a6a26SSeth Howell static void 2753a54a6a26SSeth Howell rpc_nvmf_get_stats_done(struct spdk_io_channel_iter *i, int status) 2754a54a6a26SSeth Howell { 2755a54a6a26SSeth Howell struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 2756a54a6a26SSeth Howell 2757a54a6a26SSeth Howell spdk_json_write_array_end(ctx->w); 2758a54a6a26SSeth Howell spdk_json_write_object_end(ctx->w); 2759a54a6a26SSeth Howell spdk_jsonrpc_end_result(ctx->request, ctx->w); 2760f8433aadSSeth Howell free_get_stats_ctx(ctx); 2761a54a6a26SSeth Howell } 2762a54a6a26SSeth Howell 2763a54a6a26SSeth Howell static void 2764e569a578SSeth Howell _rpc_nvmf_get_stats(struct spdk_io_channel_iter *i) 2765a54a6a26SSeth Howell { 2766a54a6a26SSeth Howell struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 27678dfa1067SMaciej Szulik struct spdk_io_channel *ch; 27688dfa1067SMaciej Szulik struct spdk_nvmf_poll_group *group; 2769a54a6a26SSeth Howell 27708dfa1067SMaciej Szulik ch = spdk_get_io_channel(ctx->tgt); 27718dfa1067SMaciej Szulik group = spdk_io_channel_get_ctx(ch); 2772a54a6a26SSeth Howell 27738dfa1067SMaciej Szulik spdk_nvmf_poll_group_dump_stat(group, ctx->w); 2774a54a6a26SSeth Howell 27758dfa1067SMaciej Szulik spdk_put_io_channel(ch); 2776a54a6a26SSeth Howell spdk_for_each_channel_continue(i, 0); 2777a54a6a26SSeth Howell } 2778a54a6a26SSeth Howell 2779a54a6a26SSeth Howell 2780a54a6a26SSeth Howell static void 2781e569a578SSeth Howell rpc_nvmf_get_stats(struct spdk_jsonrpc_request *request, 2782a54a6a26SSeth Howell const struct spdk_json_val *params) 2783a54a6a26SSeth Howell { 2784a54a6a26SSeth Howell struct rpc_nvmf_get_stats_ctx *ctx; 2785a54a6a26SSeth Howell 2786a54a6a26SSeth Howell ctx = calloc(1, sizeof(*ctx)); 2787a54a6a26SSeth Howell if (!ctx) { 2788a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2789a54a6a26SSeth Howell "Memory allocation error"); 2790a54a6a26SSeth Howell return; 2791a54a6a26SSeth Howell } 2792a54a6a26SSeth Howell ctx->request = request; 2793a54a6a26SSeth Howell 2794f8433aadSSeth Howell if (params) { 2795f8433aadSSeth Howell if (spdk_json_decode_object(params, rpc_get_stats_decoders, 2796f8433aadSSeth Howell SPDK_COUNTOF(rpc_get_stats_decoders), 2797f8433aadSSeth Howell ctx)) { 2798f8433aadSSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 2799f8433aadSSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 2800f8433aadSSeth Howell free_get_stats_ctx(ctx); 2801f8433aadSSeth Howell return; 2802f8433aadSSeth Howell } 2803f8433aadSSeth Howell } 2804f8433aadSSeth Howell 2805f8433aadSSeth Howell ctx->tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 2806a54a6a26SSeth Howell if (!ctx->tgt) { 2807a54a6a26SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 2808a54a6a26SSeth Howell "Unable to find a target."); 2809f8433aadSSeth Howell free_get_stats_ctx(ctx); 2810a54a6a26SSeth Howell return; 2811a54a6a26SSeth Howell } 2812a54a6a26SSeth Howell 2813a54a6a26SSeth Howell ctx->w = spdk_jsonrpc_begin_result(ctx->request); 2814a54a6a26SSeth Howell spdk_json_write_object_begin(ctx->w); 2815a54a6a26SSeth Howell spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz()); 2816a54a6a26SSeth Howell spdk_json_write_named_array_begin(ctx->w, "poll_groups"); 2817a54a6a26SSeth Howell 2818a54a6a26SSeth Howell spdk_for_each_channel(ctx->tgt, 2819e569a578SSeth Howell _rpc_nvmf_get_stats, 2820a54a6a26SSeth Howell ctx, 2821a54a6a26SSeth Howell rpc_nvmf_get_stats_done); 2822a54a6a26SSeth Howell } 2823a54a6a26SSeth Howell 2824e569a578SSeth Howell SPDK_RPC_REGISTER("nvmf_get_stats", rpc_nvmf_get_stats, SPDK_RPC_RUNTIME) 28254cc04a12SShuhei Matsumoto 28264cc04a12SShuhei Matsumoto static void 28274cc04a12SShuhei Matsumoto dump_nvmf_ctrlr(struct spdk_json_write_ctx *w, struct spdk_nvmf_ctrlr *ctrlr) 28284cc04a12SShuhei Matsumoto { 28294cc04a12SShuhei Matsumoto uint32_t count; 28304cc04a12SShuhei Matsumoto 28314cc04a12SShuhei Matsumoto spdk_json_write_object_begin(w); 28324cc04a12SShuhei Matsumoto 28334cc04a12SShuhei Matsumoto spdk_json_write_named_uint32(w, "cntlid", ctrlr->cntlid); 28344cc04a12SShuhei Matsumoto spdk_json_write_named_string(w, "hostnqn", ctrlr->hostnqn); 28358cffbe01SKonrad Sztyber spdk_json_write_named_uuid(w, "hostid", &ctrlr->hostid); 28364cc04a12SShuhei Matsumoto 28374cc04a12SShuhei Matsumoto count = spdk_bit_array_count_set(ctrlr->qpair_mask); 28384cc04a12SShuhei Matsumoto spdk_json_write_named_uint32(w, "num_io_qpairs", count); 28394cc04a12SShuhei Matsumoto 28404cc04a12SShuhei Matsumoto spdk_json_write_object_end(w); 28414cc04a12SShuhei Matsumoto } 28424cc04a12SShuhei Matsumoto 284383eb352bSShuhei Matsumoto static const char * 284483eb352bSShuhei Matsumoto nvmf_qpair_state_str(enum spdk_nvmf_qpair_state state) 284583eb352bSShuhei Matsumoto { 284683eb352bSShuhei Matsumoto switch (state) { 284783eb352bSShuhei Matsumoto case SPDK_NVMF_QPAIR_UNINITIALIZED: 284883eb352bSShuhei Matsumoto return "uninitialized"; 2849db221b40SKonrad Sztyber case SPDK_NVMF_QPAIR_CONNECTING: 2850db221b40SKonrad Sztyber return "connecting"; 2851781d42adSKonrad Sztyber case SPDK_NVMF_QPAIR_ENABLED: 2852781d42adSKonrad Sztyber return "enabled"; 285383eb352bSShuhei Matsumoto case SPDK_NVMF_QPAIR_DEACTIVATING: 285483eb352bSShuhei Matsumoto return "deactivating"; 285583eb352bSShuhei Matsumoto case SPDK_NVMF_QPAIR_ERROR: 285683eb352bSShuhei Matsumoto return "error"; 285783eb352bSShuhei Matsumoto default: 285883eb352bSShuhei Matsumoto return NULL; 285983eb352bSShuhei Matsumoto } 286083eb352bSShuhei Matsumoto } 286183eb352bSShuhei Matsumoto 286283eb352bSShuhei Matsumoto static void 286383eb352bSShuhei Matsumoto dump_nvmf_qpair(struct spdk_json_write_ctx *w, struct spdk_nvmf_qpair *qpair) 286483eb352bSShuhei Matsumoto { 286566ec2569SKonrad Sztyber struct spdk_nvme_transport_id trid = {}; 286683eb352bSShuhei Matsumoto 286783eb352bSShuhei Matsumoto spdk_json_write_object_begin(w); 286883eb352bSShuhei Matsumoto 286983eb352bSShuhei Matsumoto spdk_json_write_named_uint32(w, "cntlid", qpair->ctrlr->cntlid); 287083eb352bSShuhei Matsumoto spdk_json_write_named_uint32(w, "qid", qpair->qid); 287183eb352bSShuhei Matsumoto spdk_json_write_named_string(w, "state", nvmf_qpair_state_str(qpair->state)); 28729e6e8d1dSKonrad Sztyber spdk_json_write_named_string(w, "thread", spdk_thread_get_name(spdk_get_thread())); 28738a4b7226SKonrad Sztyber spdk_json_write_named_string(w, "hostnqn", qpair->ctrlr->hostnqn); 287483eb352bSShuhei Matsumoto 287566ec2569SKonrad Sztyber if (spdk_nvmf_qpair_get_listen_trid(qpair, &trid) == 0) { 2876f5260201SWojciech Panfil spdk_json_write_named_object_begin(w, "listen_address"); 287766ec2569SKonrad Sztyber nvmf_transport_listen_dump_trid(&trid, w); 2878f5260201SWojciech Panfil spdk_json_write_object_end(w); 2879f5260201SWojciech Panfil if (qpair->transport->ops->listen_dump_opts) { 288066ec2569SKonrad Sztyber qpair->transport->ops->listen_dump_opts(qpair->transport, &trid, w); 2881f5260201SWojciech Panfil } 28825c9a8a3cSShuhei Matsumoto } 288383eb352bSShuhei Matsumoto 288466ec2569SKonrad Sztyber memset(&trid, 0, sizeof(trid)); 288566ec2569SKonrad Sztyber if (spdk_nvmf_qpair_get_peer_trid(qpair, &trid) == 0) { 288666ec2569SKonrad Sztyber spdk_json_write_named_object_begin(w, "peer_address"); 288766ec2569SKonrad Sztyber nvmf_transport_listen_dump_trid(&trid, w); 288866ec2569SKonrad Sztyber spdk_json_write_object_end(w); 288966ec2569SKonrad Sztyber } 289066ec2569SKonrad Sztyber 28918e817b0cSKonrad Sztyber nvmf_qpair_auth_dump(qpair, w); 289283eb352bSShuhei Matsumoto spdk_json_write_object_end(w); 289383eb352bSShuhei Matsumoto } 289483eb352bSShuhei Matsumoto 28959c1d6483SShuhei Matsumoto static const char * 28969c1d6483SShuhei Matsumoto nvme_ana_state_str(enum spdk_nvme_ana_state ana_state) 28979c1d6483SShuhei Matsumoto { 28989c1d6483SShuhei Matsumoto switch (ana_state) { 28999c1d6483SShuhei Matsumoto case SPDK_NVME_ANA_OPTIMIZED_STATE: 29009c1d6483SShuhei Matsumoto return "optimized"; 29019c1d6483SShuhei Matsumoto case SPDK_NVME_ANA_NON_OPTIMIZED_STATE: 29029c1d6483SShuhei Matsumoto return "non_optimized"; 29039c1d6483SShuhei Matsumoto case SPDK_NVME_ANA_INACCESSIBLE_STATE: 29049c1d6483SShuhei Matsumoto return "inaccessible"; 29059c1d6483SShuhei Matsumoto case SPDK_NVME_ANA_PERSISTENT_LOSS_STATE: 29069c1d6483SShuhei Matsumoto return "persistent_loss"; 29079c1d6483SShuhei Matsumoto case SPDK_NVME_ANA_CHANGE_STATE: 29089c1d6483SShuhei Matsumoto return "change"; 29099c1d6483SShuhei Matsumoto default: 29109c1d6483SShuhei Matsumoto return NULL; 29119c1d6483SShuhei Matsumoto } 29129c1d6483SShuhei Matsumoto } 29139c1d6483SShuhei Matsumoto 29149c1d6483SShuhei Matsumoto static void 29159c1d6483SShuhei Matsumoto dump_nvmf_subsystem_listener(struct spdk_json_write_ctx *w, 29169c1d6483SShuhei Matsumoto struct spdk_nvmf_subsystem_listener *listener) 29179c1d6483SShuhei Matsumoto { 29189c1d6483SShuhei Matsumoto const struct spdk_nvme_transport_id *trid = listener->trid; 2919785d10b5SShuhei Matsumoto uint32_t i; 29209c1d6483SShuhei Matsumoto 29219c1d6483SShuhei Matsumoto spdk_json_write_object_begin(w); 29229c1d6483SShuhei Matsumoto 29239c1d6483SShuhei Matsumoto spdk_json_write_named_object_begin(w, "address"); 2924f5260201SWojciech Panfil nvmf_transport_listen_dump_trid(trid, w); 29259c1d6483SShuhei Matsumoto spdk_json_write_object_end(w); 29269c1d6483SShuhei Matsumoto 2927fb5650ceSAbhineet Pandey if (spdk_nvmf_subsystem_get_ana_reporting(listener->subsystem)) { 2928785d10b5SShuhei Matsumoto spdk_json_write_named_array_begin(w, "ana_states"); 2929785d10b5SShuhei Matsumoto for (i = 0; i < listener->subsystem->max_nsid; i++) { 2930785d10b5SShuhei Matsumoto spdk_json_write_object_begin(w); 2931785d10b5SShuhei Matsumoto spdk_json_write_named_uint32(w, "ana_group", i + 1); 29329c1d6483SShuhei Matsumoto spdk_json_write_named_string(w, "ana_state", 2933785d10b5SShuhei Matsumoto nvme_ana_state_str(listener->ana_state[i])); 2934785d10b5SShuhei Matsumoto spdk_json_write_object_end(w); 2935785d10b5SShuhei Matsumoto } 2936785d10b5SShuhei Matsumoto spdk_json_write_array_end(w); 29372a67deefSShuhei Matsumoto } 29389c1d6483SShuhei Matsumoto 29399c1d6483SShuhei Matsumoto spdk_json_write_object_end(w); 29409c1d6483SShuhei Matsumoto } 29419c1d6483SShuhei Matsumoto 2942f1c42383SShuhei Matsumoto struct rpc_subsystem_query_ctx { 29434cc04a12SShuhei Matsumoto char *nqn; 29444cc04a12SShuhei Matsumoto char *tgt_name; 29454cc04a12SShuhei Matsumoto struct spdk_nvmf_subsystem *subsystem; 29464cc04a12SShuhei Matsumoto struct spdk_jsonrpc_request *request; 29474cc04a12SShuhei Matsumoto struct spdk_json_write_ctx *w; 29484cc04a12SShuhei Matsumoto }; 29494cc04a12SShuhei Matsumoto 2950f1c42383SShuhei Matsumoto static const struct spdk_json_object_decoder rpc_subsystem_query_decoders[] = { 2951f1c42383SShuhei Matsumoto {"nqn", offsetof(struct rpc_subsystem_query_ctx, nqn), spdk_json_decode_string}, 2952f1c42383SShuhei Matsumoto {"tgt_name", offsetof(struct rpc_subsystem_query_ctx, tgt_name), spdk_json_decode_string, true}, 29534cc04a12SShuhei Matsumoto }; 29544cc04a12SShuhei Matsumoto 29554cc04a12SShuhei Matsumoto static void 2956f1c42383SShuhei Matsumoto free_rpc_subsystem_query_ctx(struct rpc_subsystem_query_ctx *ctx) 29574cc04a12SShuhei Matsumoto { 29584cc04a12SShuhei Matsumoto free(ctx->nqn); 29594cc04a12SShuhei Matsumoto free(ctx->tgt_name); 29604cc04a12SShuhei Matsumoto free(ctx); 29614cc04a12SShuhei Matsumoto } 29624cc04a12SShuhei Matsumoto 29634cc04a12SShuhei Matsumoto static void 29644cc04a12SShuhei Matsumoto rpc_nvmf_get_controllers_paused(struct spdk_nvmf_subsystem *subsystem, 29654cc04a12SShuhei Matsumoto void *cb_arg, int status) 29664cc04a12SShuhei Matsumoto { 2967f1c42383SShuhei Matsumoto struct rpc_subsystem_query_ctx *ctx = cb_arg; 29684cc04a12SShuhei Matsumoto struct spdk_json_write_ctx *w; 29694cc04a12SShuhei Matsumoto struct spdk_nvmf_ctrlr *ctrlr; 29704cc04a12SShuhei Matsumoto 29714cc04a12SShuhei Matsumoto w = spdk_jsonrpc_begin_result(ctx->request); 29724cc04a12SShuhei Matsumoto 29734cc04a12SShuhei Matsumoto spdk_json_write_array_begin(w); 29744cc04a12SShuhei Matsumoto TAILQ_FOREACH(ctrlr, &ctx->subsystem->ctrlrs, link) { 29754cc04a12SShuhei Matsumoto dump_nvmf_ctrlr(w, ctrlr); 29764cc04a12SShuhei Matsumoto } 29774cc04a12SShuhei Matsumoto spdk_json_write_array_end(w); 29784cc04a12SShuhei Matsumoto 29794cc04a12SShuhei Matsumoto spdk_jsonrpc_end_result(ctx->request, w); 29804cc04a12SShuhei Matsumoto 29814cc04a12SShuhei Matsumoto if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 29824cc04a12SShuhei Matsumoto SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 29834cc04a12SShuhei Matsumoto /* FIXME: RPC should fail if resuming the subsystem failed. */ 29844cc04a12SShuhei Matsumoto } 29854cc04a12SShuhei Matsumoto 2986f1c42383SShuhei Matsumoto free_rpc_subsystem_query_ctx(ctx); 29874cc04a12SShuhei Matsumoto } 29884cc04a12SShuhei Matsumoto 29894cc04a12SShuhei Matsumoto static void 299083eb352bSShuhei Matsumoto rpc_nvmf_get_qpairs_done(struct spdk_io_channel_iter *i, int status) 299183eb352bSShuhei Matsumoto { 299283eb352bSShuhei Matsumoto struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 299383eb352bSShuhei Matsumoto 299483eb352bSShuhei Matsumoto spdk_json_write_array_end(ctx->w); 299583eb352bSShuhei Matsumoto spdk_jsonrpc_end_result(ctx->request, ctx->w); 299683eb352bSShuhei Matsumoto 299783eb352bSShuhei Matsumoto if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 299883eb352bSShuhei Matsumoto SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 299983eb352bSShuhei Matsumoto /* FIXME: RPC should fail if resuming the subsystem failed. */ 300083eb352bSShuhei Matsumoto } 300183eb352bSShuhei Matsumoto 300283eb352bSShuhei Matsumoto free_rpc_subsystem_query_ctx(ctx); 300383eb352bSShuhei Matsumoto } 300483eb352bSShuhei Matsumoto 300583eb352bSShuhei Matsumoto static void 300683eb352bSShuhei Matsumoto rpc_nvmf_get_qpairs(struct spdk_io_channel_iter *i) 300783eb352bSShuhei Matsumoto { 300883eb352bSShuhei Matsumoto struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 300983eb352bSShuhei Matsumoto struct spdk_io_channel *ch; 301083eb352bSShuhei Matsumoto struct spdk_nvmf_poll_group *group; 301183eb352bSShuhei Matsumoto struct spdk_nvmf_qpair *qpair; 301283eb352bSShuhei Matsumoto 30136000920eSzhaoshushu.zss ch = spdk_io_channel_iter_get_channel(i); 301483eb352bSShuhei Matsumoto group = spdk_io_channel_get_ctx(ch); 301583eb352bSShuhei Matsumoto 301683eb352bSShuhei Matsumoto TAILQ_FOREACH(qpair, &group->qpairs, link) { 301783eb352bSShuhei Matsumoto if (qpair->ctrlr->subsys == ctx->subsystem) { 301883eb352bSShuhei Matsumoto dump_nvmf_qpair(ctx->w, qpair); 301983eb352bSShuhei Matsumoto } 302083eb352bSShuhei Matsumoto } 302183eb352bSShuhei Matsumoto 302283eb352bSShuhei Matsumoto spdk_for_each_channel_continue(i, 0); 302383eb352bSShuhei Matsumoto } 302483eb352bSShuhei Matsumoto 302583eb352bSShuhei Matsumoto static void 302683eb352bSShuhei Matsumoto rpc_nvmf_get_qpairs_paused(struct spdk_nvmf_subsystem *subsystem, 302783eb352bSShuhei Matsumoto void *cb_arg, int status) 302883eb352bSShuhei Matsumoto { 302983eb352bSShuhei Matsumoto struct rpc_subsystem_query_ctx *ctx = cb_arg; 303083eb352bSShuhei Matsumoto 303183eb352bSShuhei Matsumoto ctx->w = spdk_jsonrpc_begin_result(ctx->request); 303283eb352bSShuhei Matsumoto 303383eb352bSShuhei Matsumoto spdk_json_write_array_begin(ctx->w); 303483eb352bSShuhei Matsumoto 303583eb352bSShuhei Matsumoto spdk_for_each_channel(ctx->subsystem->tgt, 303683eb352bSShuhei Matsumoto rpc_nvmf_get_qpairs, 303783eb352bSShuhei Matsumoto ctx, 303883eb352bSShuhei Matsumoto rpc_nvmf_get_qpairs_done); 303983eb352bSShuhei Matsumoto } 304083eb352bSShuhei Matsumoto 304183eb352bSShuhei Matsumoto static void 30429c1d6483SShuhei Matsumoto rpc_nvmf_get_listeners_paused(struct spdk_nvmf_subsystem *subsystem, 30439c1d6483SShuhei Matsumoto void *cb_arg, int status) 30449c1d6483SShuhei Matsumoto { 30459c1d6483SShuhei Matsumoto struct rpc_subsystem_query_ctx *ctx = cb_arg; 30469c1d6483SShuhei Matsumoto struct spdk_json_write_ctx *w; 30479c1d6483SShuhei Matsumoto struct spdk_nvmf_subsystem_listener *listener; 30489c1d6483SShuhei Matsumoto 30499c1d6483SShuhei Matsumoto w = spdk_jsonrpc_begin_result(ctx->request); 30509c1d6483SShuhei Matsumoto 30519c1d6483SShuhei Matsumoto spdk_json_write_array_begin(w); 30529c1d6483SShuhei Matsumoto 30539c1d6483SShuhei Matsumoto for (listener = spdk_nvmf_subsystem_get_first_listener(ctx->subsystem); 30549c1d6483SShuhei Matsumoto listener != NULL; 30559c1d6483SShuhei Matsumoto listener = spdk_nvmf_subsystem_get_next_listener(ctx->subsystem, listener)) { 30569c1d6483SShuhei Matsumoto dump_nvmf_subsystem_listener(w, listener); 30579c1d6483SShuhei Matsumoto } 30589c1d6483SShuhei Matsumoto spdk_json_write_array_end(w); 30599c1d6483SShuhei Matsumoto 30609c1d6483SShuhei Matsumoto spdk_jsonrpc_end_result(ctx->request, w); 30619c1d6483SShuhei Matsumoto 30629c1d6483SShuhei Matsumoto if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) { 30639c1d6483SShuhei Matsumoto SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn); 30649c1d6483SShuhei Matsumoto /* FIXME: RPC should fail if resuming the subsystem failed. */ 30659c1d6483SShuhei Matsumoto } 30669c1d6483SShuhei Matsumoto 30679c1d6483SShuhei Matsumoto free_rpc_subsystem_query_ctx(ctx); 30689c1d6483SShuhei Matsumoto } 30699c1d6483SShuhei Matsumoto 30709c1d6483SShuhei Matsumoto static void 3071f1c42383SShuhei Matsumoto _rpc_nvmf_subsystem_query(struct spdk_jsonrpc_request *request, 3072f1c42383SShuhei Matsumoto const struct spdk_json_val *params, 3073f1c42383SShuhei Matsumoto spdk_nvmf_subsystem_state_change_done cb_fn) 30744cc04a12SShuhei Matsumoto { 3075f1c42383SShuhei Matsumoto struct rpc_subsystem_query_ctx *ctx; 30764cc04a12SShuhei Matsumoto struct spdk_nvmf_subsystem *subsystem; 30774cc04a12SShuhei Matsumoto struct spdk_nvmf_tgt *tgt; 30784cc04a12SShuhei Matsumoto 30794cc04a12SShuhei Matsumoto ctx = calloc(1, sizeof(*ctx)); 30804cc04a12SShuhei Matsumoto if (!ctx) { 30814cc04a12SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 30824cc04a12SShuhei Matsumoto "Out of memory"); 30834cc04a12SShuhei Matsumoto return; 30844cc04a12SShuhei Matsumoto } 30854cc04a12SShuhei Matsumoto 30864cc04a12SShuhei Matsumoto ctx->request = request; 30874cc04a12SShuhei Matsumoto 3088f1c42383SShuhei Matsumoto if (spdk_json_decode_object(params, rpc_subsystem_query_decoders, 3089f1c42383SShuhei Matsumoto SPDK_COUNTOF(rpc_subsystem_query_decoders), 30904cc04a12SShuhei Matsumoto ctx)) { 30914cc04a12SShuhei Matsumoto SPDK_ERRLOG("spdk_json_decode_object failed\n"); 30924cc04a12SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 30934cc04a12SShuhei Matsumoto "Invalid parameters"); 3094f1c42383SShuhei Matsumoto free_rpc_subsystem_query_ctx(ctx); 30954cc04a12SShuhei Matsumoto return; 30964cc04a12SShuhei Matsumoto } 30974cc04a12SShuhei Matsumoto 30984cc04a12SShuhei Matsumoto tgt = spdk_nvmf_get_tgt(ctx->tgt_name); 30994cc04a12SShuhei Matsumoto if (!tgt) { 31004cc04a12SShuhei Matsumoto SPDK_ERRLOG("Unable to find a target object.\n"); 31014cc04a12SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 31024cc04a12SShuhei Matsumoto "Unable to find a target"); 3103f1c42383SShuhei Matsumoto free_rpc_subsystem_query_ctx(ctx); 31044cc04a12SShuhei Matsumoto return; 31054cc04a12SShuhei Matsumoto } 31064cc04a12SShuhei Matsumoto 31074cc04a12SShuhei Matsumoto subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn); 31084cc04a12SShuhei Matsumoto if (!subsystem) { 31094cc04a12SShuhei Matsumoto SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn); 31104cc04a12SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 31114cc04a12SShuhei Matsumoto "Invalid parameters"); 3112f1c42383SShuhei Matsumoto free_rpc_subsystem_query_ctx(ctx); 31134cc04a12SShuhei Matsumoto return; 31144cc04a12SShuhei Matsumoto } 31154cc04a12SShuhei Matsumoto 31164cc04a12SShuhei Matsumoto ctx->subsystem = subsystem; 31174cc04a12SShuhei Matsumoto 3118312a9d60SBen Walker if (spdk_nvmf_subsystem_pause(subsystem, 0, cb_fn, ctx)) { 31194cc04a12SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 31204cc04a12SShuhei Matsumoto "Internal error"); 3121f1c42383SShuhei Matsumoto free_rpc_subsystem_query_ctx(ctx); 31224cc04a12SShuhei Matsumoto return; 31234cc04a12SShuhei Matsumoto } 31244cc04a12SShuhei Matsumoto } 3125f1c42383SShuhei Matsumoto 3126f1c42383SShuhei Matsumoto static void 3127f1c42383SShuhei Matsumoto rpc_nvmf_subsystem_get_controllers(struct spdk_jsonrpc_request *request, 3128f1c42383SShuhei Matsumoto const struct spdk_json_val *params) 3129f1c42383SShuhei Matsumoto { 3130f1c42383SShuhei Matsumoto _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_controllers_paused); 3131f1c42383SShuhei Matsumoto } 31324cc04a12SShuhei Matsumoto SPDK_RPC_REGISTER("nvmf_subsystem_get_controllers", rpc_nvmf_subsystem_get_controllers, 31334cc04a12SShuhei Matsumoto SPDK_RPC_RUNTIME); 313483eb352bSShuhei Matsumoto 313583eb352bSShuhei Matsumoto static void 313683eb352bSShuhei Matsumoto rpc_nvmf_subsystem_get_qpairs(struct spdk_jsonrpc_request *request, 313783eb352bSShuhei Matsumoto const struct spdk_json_val *params) 313883eb352bSShuhei Matsumoto { 313983eb352bSShuhei Matsumoto _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_qpairs_paused); 314083eb352bSShuhei Matsumoto } 314183eb352bSShuhei Matsumoto SPDK_RPC_REGISTER("nvmf_subsystem_get_qpairs", rpc_nvmf_subsystem_get_qpairs, SPDK_RPC_RUNTIME); 31429c1d6483SShuhei Matsumoto 31439c1d6483SShuhei Matsumoto static void 31449c1d6483SShuhei Matsumoto rpc_nvmf_subsystem_get_listeners(struct spdk_jsonrpc_request *request, 31459c1d6483SShuhei Matsumoto const struct spdk_json_val *params) 31469c1d6483SShuhei Matsumoto { 31479c1d6483SShuhei Matsumoto _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_listeners_paused); 31489c1d6483SShuhei Matsumoto } 31499c1d6483SShuhei Matsumoto SPDK_RPC_REGISTER("nvmf_subsystem_get_listeners", rpc_nvmf_subsystem_get_listeners, 31509c1d6483SShuhei Matsumoto SPDK_RPC_RUNTIME); 3151e2d54380Skyuho.son 3152e2d54380Skyuho.son struct rpc_mdns_prr { 3153e2d54380Skyuho.son char *tgt_name; 3154e2d54380Skyuho.son }; 3155e2d54380Skyuho.son 3156e2d54380Skyuho.son static const struct spdk_json_object_decoder rpc_mdns_prr_decoders[] = { 3157e2d54380Skyuho.son {"tgt_name", offsetof(struct rpc_mdns_prr, tgt_name), spdk_json_decode_string, true}, 3158e2d54380Skyuho.son }; 3159e2d54380Skyuho.son 3160e2d54380Skyuho.son static void 3161e2d54380Skyuho.son rpc_nvmf_publish_mdns_prr(struct spdk_jsonrpc_request *request, 3162e2d54380Skyuho.son const struct spdk_json_val *params) 3163e2d54380Skyuho.son { 3164e2d54380Skyuho.son int rc; 3165e2d54380Skyuho.son struct rpc_mdns_prr req = { 0 }; 3166e2d54380Skyuho.son struct spdk_nvmf_tgt *tgt; 3167e2d54380Skyuho.son 3168e2d54380Skyuho.son if (params) { 3169e2d54380Skyuho.son if (spdk_json_decode_object(params, rpc_mdns_prr_decoders, 3170e2d54380Skyuho.son SPDK_COUNTOF(rpc_mdns_prr_decoders), 3171e2d54380Skyuho.son &req)) { 3172e2d54380Skyuho.son SPDK_ERRLOG("spdk_json_decode_object failed\n"); 3173e2d54380Skyuho.son spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 3174e2d54380Skyuho.son return; 3175e2d54380Skyuho.son } 3176e2d54380Skyuho.son } 3177e2d54380Skyuho.son 3178e2d54380Skyuho.son tgt = spdk_nvmf_get_tgt(req.tgt_name); 3179e2d54380Skyuho.son if (!tgt) { 3180e2d54380Skyuho.son spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 3181e2d54380Skyuho.son "Unable to find a target."); 3182e2d54380Skyuho.son free(req.tgt_name); 3183e2d54380Skyuho.son return; 3184e2d54380Skyuho.son } 3185e2d54380Skyuho.son 3186e2d54380Skyuho.son rc = nvmf_publish_mdns_prr(tgt); 3187e2d54380Skyuho.son if (rc) { 3188e2d54380Skyuho.son spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 3189e2d54380Skyuho.son free(req.tgt_name); 3190e2d54380Skyuho.son return; 3191e2d54380Skyuho.son } 3192e2d54380Skyuho.son 3193e2d54380Skyuho.son spdk_jsonrpc_send_bool_response(request, true); 3194e2d54380Skyuho.son free(req.tgt_name); 3195e2d54380Skyuho.son } 3196e2d54380Skyuho.son SPDK_RPC_REGISTER("nvmf_publish_mdns_prr", rpc_nvmf_publish_mdns_prr, SPDK_RPC_RUNTIME); 319748352fbbSkyuho.son 319848352fbbSkyuho.son static void 319948352fbbSkyuho.son rpc_nvmf_stop_mdns_prr(struct spdk_jsonrpc_request *request, 320048352fbbSkyuho.son const struct spdk_json_val *params) 320148352fbbSkyuho.son { 320248352fbbSkyuho.son struct rpc_mdns_prr req = { 0 }; 320348352fbbSkyuho.son struct spdk_nvmf_tgt *tgt; 320448352fbbSkyuho.son 320548352fbbSkyuho.son if (params) { 320648352fbbSkyuho.son if (spdk_json_decode_object(params, rpc_mdns_prr_decoders, 320748352fbbSkyuho.son SPDK_COUNTOF(rpc_mdns_prr_decoders), 320848352fbbSkyuho.son &req)) { 320948352fbbSkyuho.son SPDK_ERRLOG("spdk_json_decode_object failed\n"); 321048352fbbSkyuho.son spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 321148352fbbSkyuho.son return; 321248352fbbSkyuho.son } 321348352fbbSkyuho.son } 321448352fbbSkyuho.son 321548352fbbSkyuho.son tgt = spdk_nvmf_get_tgt(req.tgt_name); 321648352fbbSkyuho.son if (!tgt) { 321748352fbbSkyuho.son spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 321848352fbbSkyuho.son "Unable to find a target."); 321948352fbbSkyuho.son free(req.tgt_name); 322048352fbbSkyuho.son return; 322148352fbbSkyuho.son } 322248352fbbSkyuho.son 322348352fbbSkyuho.son nvmf_tgt_stop_mdns_prr(tgt); 322448352fbbSkyuho.son 322548352fbbSkyuho.son spdk_jsonrpc_send_bool_response(request, true); 322648352fbbSkyuho.son free(req.tgt_name); 322748352fbbSkyuho.son } 322848352fbbSkyuho.son SPDK_RPC_REGISTER("nvmf_stop_mdns_prr", rpc_nvmf_stop_mdns_prr, SPDK_RPC_RUNTIME); 3229