xref: /spdk/lib/nvmf/nvmf_rpc.c (revision 2b36fae2f324aa7e853d51da4e51e7416689fce6)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2016 Intel Corporation. All rights reserved.
3  *   Copyright (c) 2018-2021 Mellanox Technologies LTD. All rights reserved.
4  *   Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5  */
6 
7 #include "spdk/bdev.h"
8 #include "spdk/log.h"
9 #include "spdk/rpc.h"
10 #include "spdk/env.h"
11 #include "spdk/nvme.h"
12 #include "spdk/nvmf.h"
13 #include "spdk/string.h"
14 #include "spdk/util.h"
15 #include "spdk/bit_array.h"
16 
17 #include "spdk_internal/assert.h"
18 
19 #include "nvmf_internal.h"
20 
21 static bool g_logged_deprecated_nvmf_get_subsystems = false;
22 
23 static int
24 json_write_hex_str(struct spdk_json_write_ctx *w, const void *data, size_t size)
25 {
26 	static const char hex_char[16] = "0123456789ABCDEF";
27 	const uint8_t *buf = data;
28 	char *str, *out;
29 	int rc;
30 
31 	str = malloc(size * 2 + 1);
32 	if (str == NULL) {
33 		return -1;
34 	}
35 
36 	out = str;
37 	while (size--) {
38 		unsigned byte = *buf++;
39 
40 		out[0] = hex_char[(byte >> 4) & 0xF];
41 		out[1] = hex_char[byte & 0xF];
42 
43 		out += 2;
44 	}
45 	*out = '\0';
46 
47 	rc = spdk_json_write_string(w, str);
48 	free(str);
49 
50 	return rc;
51 }
52 
53 static int
54 hex_nybble_to_num(char c)
55 {
56 	if (c >= '0' && c <= '9') {
57 		return c - '0';
58 	}
59 
60 	if (c >= 'a' && c <= 'f') {
61 		return c - 'a' + 0xA;
62 	}
63 
64 	if (c >= 'A' && c <= 'F') {
65 		return c - 'A' + 0xA;
66 	}
67 
68 	return -1;
69 }
70 
71 static int
72 hex_byte_to_num(const char *str)
73 {
74 	int hi, lo;
75 
76 	hi = hex_nybble_to_num(str[0]);
77 	if (hi < 0) {
78 		return hi;
79 	}
80 
81 	lo = hex_nybble_to_num(str[1]);
82 	if (lo < 0) {
83 		return lo;
84 	}
85 
86 	return hi * 16 + lo;
87 }
88 
89 static int
90 decode_hex_string_be(const char *str, uint8_t *out, size_t size)
91 {
92 	size_t i;
93 
94 	/* Decode a string in "ABCDEF012345" format to its binary representation */
95 	for (i = 0; i < size; i++) {
96 		int num = hex_byte_to_num(str);
97 
98 		if (num < 0) {
99 			/* Invalid hex byte or end of string */
100 			return -1;
101 		}
102 
103 		out[i] = (uint8_t)num;
104 		str += 2;
105 	}
106 
107 	if (i != size || *str != '\0') {
108 		/* Length mismatch */
109 		return -1;
110 	}
111 
112 	return 0;
113 }
114 
115 static int
116 decode_ns_nguid(const struct spdk_json_val *val, void *out)
117 {
118 	char *str = NULL;
119 	int rc;
120 
121 	rc = spdk_json_decode_string(val, &str);
122 	if (rc == 0) {
123 		/* 16-byte NGUID */
124 		rc = decode_hex_string_be(str, out, 16);
125 	}
126 
127 	free(str);
128 	return rc;
129 }
130 
131 static int
132 decode_ns_eui64(const struct spdk_json_val *val, void *out)
133 {
134 	char *str = NULL;
135 	int rc;
136 
137 	rc = spdk_json_decode_string(val, &str);
138 	if (rc == 0) {
139 		/* 8-byte EUI-64 */
140 		rc = decode_hex_string_be(str, out, 8);
141 	}
142 
143 	free(str);
144 	return rc;
145 }
146 
147 static int
148 decode_ns_uuid(const struct spdk_json_val *val, void *out)
149 {
150 	char *str = NULL;
151 	int rc;
152 
153 	rc = spdk_json_decode_string(val, &str);
154 	if (rc == 0) {
155 		rc = spdk_uuid_parse(out, str);
156 	}
157 
158 	free(str);
159 	return rc;
160 }
161 
162 struct rpc_get_subsystem {
163 	char *nqn;
164 	char *tgt_name;
165 };
166 
167 static const struct spdk_json_object_decoder rpc_get_subsystem_decoders[] = {
168 	{"nqn", offsetof(struct rpc_get_subsystem, nqn), spdk_json_decode_string, true},
169 	{"tgt_name", offsetof(struct rpc_get_subsystem, tgt_name), spdk_json_decode_string, true},
170 };
171 
172 static void
173 dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct spdk_nvmf_subsystem *subsystem)
174 {
175 	struct spdk_nvmf_host			*host;
176 	struct spdk_nvmf_subsystem_listener	*listener;
177 
178 	spdk_json_write_object_begin(w);
179 
180 	spdk_json_write_named_string(w, "nqn", spdk_nvmf_subsystem_get_nqn(subsystem));
181 	spdk_json_write_name(w, "subtype");
182 	if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) {
183 		spdk_json_write_string(w, "NVMe");
184 	} else {
185 		spdk_json_write_string(w, "Discovery");
186 	}
187 
188 	spdk_json_write_named_array_begin(w, "listen_addresses");
189 
190 	for (listener = spdk_nvmf_subsystem_get_first_listener(subsystem); listener != NULL;
191 	     listener = spdk_nvmf_subsystem_get_next_listener(subsystem, listener)) {
192 		const struct spdk_nvme_transport_id *trid;
193 
194 		trid = spdk_nvmf_subsystem_listener_get_trid(listener);
195 
196 		spdk_json_write_object_begin(w);
197 
198 		/* NOTE: "transport" is kept for compatibility; new code should use "trtype". */
199 		/* TODO: Remove after SPDK v23.09 release. */
200 		spdk_json_write_named_string(w, "transport", trid->trstring);
201 		nvmf_transport_listen_dump_trid(trid, w);
202 		spdk_json_write_object_end(w);
203 	}
204 	spdk_json_write_array_end(w);
205 
206 	spdk_json_write_named_bool(w, "allow_any_host",
207 				   spdk_nvmf_subsystem_get_allow_any_host(subsystem));
208 
209 	spdk_json_write_named_array_begin(w, "hosts");
210 
211 	for (host = spdk_nvmf_subsystem_get_first_host(subsystem); host != NULL;
212 	     host = spdk_nvmf_subsystem_get_next_host(subsystem, host)) {
213 		spdk_json_write_object_begin(w);
214 		spdk_json_write_named_string(w, "nqn", spdk_nvmf_host_get_nqn(host));
215 		spdk_json_write_object_end(w);
216 	}
217 	spdk_json_write_array_end(w);
218 
219 	if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) {
220 		struct spdk_nvmf_ns *ns;
221 		struct spdk_nvmf_ns_opts ns_opts;
222 		uint32_t max_namespaces;
223 
224 		spdk_json_write_named_string(w, "serial_number", spdk_nvmf_subsystem_get_sn(subsystem));
225 
226 		spdk_json_write_named_string(w, "model_number", spdk_nvmf_subsystem_get_mn(subsystem));
227 
228 		max_namespaces = spdk_nvmf_subsystem_get_max_namespaces(subsystem);
229 		if (max_namespaces != 0) {
230 			spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces);
231 		}
232 
233 		spdk_json_write_named_uint32(w, "min_cntlid", spdk_nvmf_subsystem_get_min_cntlid(subsystem));
234 		spdk_json_write_named_uint32(w, "max_cntlid", spdk_nvmf_subsystem_get_max_cntlid(subsystem));
235 
236 		spdk_json_write_named_array_begin(w, "namespaces");
237 		for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
238 		     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
239 			spdk_nvmf_ns_get_opts(ns, &ns_opts, sizeof(ns_opts));
240 			spdk_json_write_object_begin(w);
241 			spdk_json_write_named_int32(w, "nsid", spdk_nvmf_ns_get_id(ns));
242 			spdk_json_write_named_string(w, "bdev_name",
243 						     spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns)));
244 			/* NOTE: "name" is kept for compatibility only - new code should use bdev_name. */
245 			spdk_json_write_named_string(w, "name",
246 						     spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns)));
247 
248 			if (!spdk_mem_all_zero(ns_opts.nguid, sizeof(ns_opts.nguid))) {
249 				spdk_json_write_name(w, "nguid");
250 				json_write_hex_str(w, ns_opts.nguid, sizeof(ns_opts.nguid));
251 			}
252 
253 			if (!spdk_mem_all_zero(ns_opts.eui64, sizeof(ns_opts.eui64))) {
254 				spdk_json_write_name(w, "eui64");
255 				json_write_hex_str(w, ns_opts.eui64, sizeof(ns_opts.eui64));
256 			}
257 
258 			if (!spdk_uuid_is_null(&ns_opts.uuid)) {
259 				char uuid_str[SPDK_UUID_STRING_LEN];
260 
261 				spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ns_opts.uuid);
262 				spdk_json_write_named_string(w, "uuid", uuid_str);
263 			}
264 
265 			if (nvmf_subsystem_get_ana_reporting(subsystem)) {
266 				spdk_json_write_named_uint32(w, "anagrpid", ns_opts.anagrpid);
267 			}
268 
269 			spdk_json_write_object_end(w);
270 		}
271 		spdk_json_write_array_end(w);
272 	}
273 	spdk_json_write_object_end(w);
274 }
275 
276 SPDK_LOG_DEPRECATION_REGISTER(rpc_nvmf_get_subsystems,
277 			      "listener.transport is deprecated in favor of trtype",
278 			      "v24.01", 0);
279 
280 static void
281 rpc_nvmf_get_subsystems(struct spdk_jsonrpc_request *request,
282 			const struct spdk_json_val *params)
283 {
284 	struct rpc_get_subsystem req = { 0 };
285 	struct spdk_json_write_ctx *w;
286 	struct spdk_nvmf_subsystem *subsystem = NULL;
287 	struct spdk_nvmf_tgt *tgt;
288 
289 	/* Log only once */
290 	if (!g_logged_deprecated_nvmf_get_subsystems) {
291 		SPDK_LOG_DEPRECATED(rpc_nvmf_get_subsystems);
292 		g_logged_deprecated_nvmf_get_subsystems = true;
293 	}
294 
295 	if (params) {
296 		if (spdk_json_decode_object(params, rpc_get_subsystem_decoders,
297 					    SPDK_COUNTOF(rpc_get_subsystem_decoders),
298 					    &req)) {
299 			SPDK_ERRLOG("spdk_json_decode_object failed\n");
300 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
301 			return;
302 		}
303 	}
304 
305 	tgt = spdk_nvmf_get_tgt(req.tgt_name);
306 	if (!tgt) {
307 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
308 						 "Unable to find a target.");
309 		free(req.tgt_name);
310 		free(req.nqn);
311 		return;
312 	}
313 
314 	if (req.nqn) {
315 		subsystem = spdk_nvmf_tgt_find_subsystem(tgt, req.nqn);
316 		if (!subsystem) {
317 			SPDK_ERRLOG("subsystem '%s' does not exist\n", req.nqn);
318 			spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
319 			free(req.tgt_name);
320 			free(req.nqn);
321 			return;
322 		}
323 	}
324 
325 	w = spdk_jsonrpc_begin_result(request);
326 	spdk_json_write_array_begin(w);
327 
328 	if (subsystem) {
329 		dump_nvmf_subsystem(w, subsystem);
330 	} else {
331 		for (subsystem = spdk_nvmf_subsystem_get_first(tgt); subsystem != NULL;
332 		     subsystem = spdk_nvmf_subsystem_get_next(subsystem)) {
333 			dump_nvmf_subsystem(w, subsystem);
334 		}
335 	}
336 
337 	spdk_json_write_array_end(w);
338 	spdk_jsonrpc_end_result(request, w);
339 	free(req.tgt_name);
340 	free(req.nqn);
341 }
342 SPDK_RPC_REGISTER("nvmf_get_subsystems", rpc_nvmf_get_subsystems, SPDK_RPC_RUNTIME)
343 
344 struct rpc_subsystem_create {
345 	char *nqn;
346 	char *serial_number;
347 	char *model_number;
348 	char *tgt_name;
349 	uint32_t max_namespaces;
350 	bool allow_any_host;
351 	bool ana_reporting;
352 	uint16_t min_cntlid;
353 	uint16_t max_cntlid;
354 };
355 
356 static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = {
357 	{"nqn", offsetof(struct rpc_subsystem_create, nqn), spdk_json_decode_string},
358 	{"serial_number", offsetof(struct rpc_subsystem_create, serial_number), spdk_json_decode_string, true},
359 	{"model_number", offsetof(struct rpc_subsystem_create, model_number), spdk_json_decode_string, true},
360 	{"tgt_name", offsetof(struct rpc_subsystem_create, tgt_name), spdk_json_decode_string, true},
361 	{"max_namespaces", offsetof(struct rpc_subsystem_create, max_namespaces), spdk_json_decode_uint32, true},
362 	{"allow_any_host", offsetof(struct rpc_subsystem_create, allow_any_host), spdk_json_decode_bool, true},
363 	{"ana_reporting", offsetof(struct rpc_subsystem_create, ana_reporting), spdk_json_decode_bool, true},
364 	{"min_cntlid", offsetof(struct rpc_subsystem_create, min_cntlid), spdk_json_decode_uint16, true},
365 	{"max_cntlid", offsetof(struct rpc_subsystem_create, max_cntlid), spdk_json_decode_uint16, true},
366 };
367 
368 static void
369 rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem,
370 			   void *cb_arg, int status)
371 {
372 	struct spdk_jsonrpc_request *request = cb_arg;
373 
374 	if (!status) {
375 		spdk_jsonrpc_send_bool_response(request, true);
376 	} else {
377 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
378 						     "Subsystem %s start failed",
379 						     subsystem->subnqn);
380 		spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
381 	}
382 }
383 
384 static void
385 rpc_nvmf_create_subsystem(struct spdk_jsonrpc_request *request,
386 			  const struct spdk_json_val *params)
387 {
388 	struct rpc_subsystem_create *req;
389 	struct spdk_nvmf_subsystem *subsystem = NULL;
390 	struct spdk_nvmf_tgt *tgt;
391 	int rc = -1;
392 
393 	req = calloc(1, sizeof(*req));
394 	if (!req) {
395 		SPDK_ERRLOG("Memory allocation failed\n");
396 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
397 						 "Memory allocation failed");
398 		return;
399 	}
400 	req->min_cntlid = NVMF_MIN_CNTLID;
401 	req->max_cntlid = NVMF_MAX_CNTLID;
402 
403 	if (spdk_json_decode_object(params, rpc_subsystem_create_decoders,
404 				    SPDK_COUNTOF(rpc_subsystem_create_decoders),
405 				    req)) {
406 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
407 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
408 		goto cleanup;
409 	}
410 
411 	tgt = spdk_nvmf_get_tgt(req->tgt_name);
412 	if (!tgt) {
413 		SPDK_ERRLOG("Unable to find target %s\n", req->tgt_name);
414 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
415 						     "Unable to find target %s", req->tgt_name);
416 		goto cleanup;
417 	}
418 
419 	subsystem = spdk_nvmf_subsystem_create(tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME,
420 					       req->max_namespaces);
421 	if (!subsystem) {
422 		SPDK_ERRLOG("Unable to create subsystem %s\n", req->nqn);
423 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
424 						     "Unable to create subsystem %s", req->nqn);
425 		goto cleanup;
426 	}
427 
428 	if (req->serial_number) {
429 		if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) {
430 			SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number);
431 			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
432 							     "Invalid SN %s", req->serial_number);
433 			goto cleanup;
434 		}
435 	}
436 
437 	if (req->model_number) {
438 		if (spdk_nvmf_subsystem_set_mn(subsystem, req->model_number)) {
439 			SPDK_ERRLOG("Subsystem %s: invalid model number '%s'\n", req->nqn, req->model_number);
440 			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
441 							     "Invalid MN %s", req->model_number);
442 			goto cleanup;
443 		}
444 	}
445 
446 	spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host);
447 
448 	spdk_nvmf_subsystem_set_ana_reporting(subsystem, req->ana_reporting);
449 
450 	if (nvmf_subsystem_set_cntlid_range(subsystem, req->min_cntlid, req->max_cntlid)) {
451 		SPDK_ERRLOG("Subsystem %s: invalid cntlid range [%u-%u]\n", req->nqn, req->min_cntlid,
452 			    req->max_cntlid);
453 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
454 						     "Invalid cntlid range [%u-%u]", req->min_cntlid, req->max_cntlid);
455 		goto cleanup;
456 	}
457 
458 	rc = spdk_nvmf_subsystem_start(subsystem,
459 				       rpc_nvmf_subsystem_started,
460 				       request);
461 	if (rc) {
462 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
463 						 "Failed to start subsystem");
464 	}
465 
466 cleanup:
467 	free(req->nqn);
468 	free(req->tgt_name);
469 	free(req->serial_number);
470 	free(req->model_number);
471 	free(req);
472 
473 	if (rc && subsystem) {
474 		spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
475 	}
476 }
477 SPDK_RPC_REGISTER("nvmf_create_subsystem", rpc_nvmf_create_subsystem, SPDK_RPC_RUNTIME)
478 
479 struct rpc_delete_subsystem {
480 	char *nqn;
481 	char *tgt_name;
482 };
483 
484 static void
485 free_rpc_delete_subsystem(struct rpc_delete_subsystem *r)
486 {
487 	free(r->nqn);
488 	free(r->tgt_name);
489 }
490 
491 static void
492 rpc_nvmf_subsystem_destroy_complete_cb(void *cb_arg)
493 {
494 	struct spdk_jsonrpc_request *request = cb_arg;
495 
496 	spdk_jsonrpc_send_bool_response(request, true);
497 }
498 
499 static void
500 rpc_nvmf_subsystem_stopped(struct spdk_nvmf_subsystem *subsystem,
501 			   void *cb_arg, int status)
502 {
503 	struct spdk_jsonrpc_request *request = cb_arg;
504 	int rc;
505 
506 	nvmf_subsystem_remove_all_listeners(subsystem, true);
507 	rc = spdk_nvmf_subsystem_destroy(subsystem, rpc_nvmf_subsystem_destroy_complete_cb, request);
508 	if (rc) {
509 		if (rc == -EINPROGRESS) {
510 			/* response will be sent in completion callback */
511 			return;
512 		} else {
513 			SPDK_ERRLOG("Subsystem destruction failed, rc %d\n", rc);
514 			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
515 							     "Subsystem destruction failed, rc %d", rc);
516 			return;
517 		}
518 	}
519 	spdk_jsonrpc_send_bool_response(request, true);
520 }
521 
522 static const struct spdk_json_object_decoder rpc_delete_subsystem_decoders[] = {
523 	{"nqn", offsetof(struct rpc_delete_subsystem, nqn), spdk_json_decode_string},
524 	{"tgt_name", offsetof(struct rpc_delete_subsystem, tgt_name), spdk_json_decode_string, true},
525 };
526 
527 static void
528 rpc_nvmf_delete_subsystem(struct spdk_jsonrpc_request *request,
529 			  const struct spdk_json_val *params)
530 {
531 	struct rpc_delete_subsystem req = { 0 };
532 	struct spdk_nvmf_subsystem *subsystem;
533 	struct spdk_nvmf_tgt *tgt;
534 	int rc;
535 
536 	if (spdk_json_decode_object(params, rpc_delete_subsystem_decoders,
537 				    SPDK_COUNTOF(rpc_delete_subsystem_decoders),
538 				    &req)) {
539 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
540 		goto invalid;
541 	}
542 
543 	if (req.nqn == NULL) {
544 		SPDK_ERRLOG("missing name param\n");
545 		goto invalid;
546 	}
547 
548 	tgt = spdk_nvmf_get_tgt(req.tgt_name);
549 	if (!tgt) {
550 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
551 						 "Unable to find a target.");
552 		goto invalid_custom_response;
553 	}
554 
555 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, req.nqn);
556 	if (!subsystem) {
557 		goto invalid;
558 	}
559 
560 	free_rpc_delete_subsystem(&req);
561 
562 	rc = spdk_nvmf_subsystem_stop(subsystem,
563 				      rpc_nvmf_subsystem_stopped,
564 				      request);
565 	if (rc == -EBUSY) {
566 		SPDK_ERRLOG("Subsystem currently in another state change try again later.\n");
567 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
568 						 "Subsystem currently in another state change try again later.");
569 	} else if (rc != 0) {
570 		SPDK_ERRLOG("Unable to change state on subsystem. rc=%d\n", rc);
571 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
572 						     "Unable to change state on subsystem. rc=%d", rc);
573 	}
574 
575 	return;
576 
577 invalid:
578 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
579 invalid_custom_response:
580 	free_rpc_delete_subsystem(&req);
581 }
582 SPDK_RPC_REGISTER("nvmf_delete_subsystem", rpc_nvmf_delete_subsystem, SPDK_RPC_RUNTIME)
583 
584 struct rpc_listen_address {
585 	char *transport;
586 	char *adrfam;
587 	char *traddr;
588 	char *trsvcid;
589 };
590 
591 static const struct spdk_json_object_decoder rpc_listen_address_decoders[] = {
592 	/* NOTE: "transport" is kept for compatibility; new code should use "trtype" */
593 	{"transport", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
594 	{"trtype", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
595 	{"adrfam", offsetof(struct rpc_listen_address, adrfam), spdk_json_decode_string, true},
596 	{"traddr", offsetof(struct rpc_listen_address, traddr), spdk_json_decode_string},
597 	{"trsvcid", offsetof(struct rpc_listen_address, trsvcid), spdk_json_decode_string, true},
598 };
599 
600 static int
601 decode_rpc_listen_address(const struct spdk_json_val *val, void *out)
602 {
603 	struct rpc_listen_address *req = (struct rpc_listen_address *)out;
604 	if (spdk_json_decode_object(val, rpc_listen_address_decoders,
605 				    SPDK_COUNTOF(rpc_listen_address_decoders),
606 				    req)) {
607 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
608 		return -1;
609 	}
610 	return 0;
611 }
612 
613 static void
614 free_rpc_listen_address(struct rpc_listen_address *r)
615 {
616 	free(r->transport);
617 	free(r->adrfam);
618 	free(r->traddr);
619 	free(r->trsvcid);
620 }
621 
622 enum nvmf_rpc_listen_op {
623 	NVMF_RPC_LISTEN_ADD,
624 	NVMF_RPC_LISTEN_REMOVE,
625 	NVMF_RPC_LISTEN_SET_ANA_STATE,
626 };
627 
628 struct nvmf_rpc_listener_ctx {
629 	char				*nqn;
630 	char				*tgt_name;
631 	struct spdk_nvmf_tgt		*tgt;
632 	struct spdk_nvmf_transport	*transport;
633 	struct spdk_nvmf_subsystem	*subsystem;
634 	struct rpc_listen_address	address;
635 	char				*ana_state_str;
636 	enum spdk_nvme_ana_state	ana_state;
637 	uint32_t			anagrpid;
638 
639 	struct spdk_jsonrpc_request	*request;
640 	struct spdk_nvme_transport_id	trid;
641 	enum nvmf_rpc_listen_op		op;
642 	bool				response_sent;
643 	struct spdk_nvmf_listen_opts	opts;
644 
645 	/* Additional options for listener creation. */
646 	struct spdk_nvmf_listener_opts	listener_opts;
647 };
648 
649 static const struct spdk_json_object_decoder nvmf_rpc_listener_decoder[] = {
650 	{"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string},
651 	{"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address},
652 	{"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true},
653 	{"secure_channel", offsetof(struct nvmf_rpc_listener_ctx, listener_opts.secure_channel), spdk_json_decode_bool, true},
654 };
655 
656 static void
657 nvmf_rpc_listener_ctx_free(struct nvmf_rpc_listener_ctx *ctx)
658 {
659 	free(ctx->nqn);
660 	free(ctx->tgt_name);
661 	free_rpc_listen_address(&ctx->address);
662 	free(ctx->ana_state_str);
663 	free(ctx);
664 }
665 
666 static void
667 nvmf_rpc_listen_resumed(struct spdk_nvmf_subsystem *subsystem,
668 			void *cb_arg, int status)
669 {
670 	struct nvmf_rpc_listener_ctx *ctx = cb_arg;
671 	struct spdk_jsonrpc_request *request;
672 
673 	request = ctx->request;
674 	if (ctx->response_sent) {
675 		/* If an error occurred, the response has already been sent. */
676 		nvmf_rpc_listener_ctx_free(ctx);
677 		return;
678 	}
679 
680 	nvmf_rpc_listener_ctx_free(ctx);
681 
682 	spdk_jsonrpc_send_bool_response(request, true);
683 }
684 
685 static void
686 nvmf_rpc_subsystem_listen(void *cb_arg, int status)
687 {
688 	struct nvmf_rpc_listener_ctx *ctx = cb_arg;
689 
690 	if (status) {
691 		/* Destroy the listener that we just created. Ignore the error code because
692 		 * the RPC is failing already anyway. */
693 		spdk_nvmf_tgt_stop_listen(ctx->tgt, &ctx->trid);
694 
695 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
696 						 "Invalid parameters");
697 		ctx->response_sent = true;
698 	}
699 
700 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
701 		if (!ctx->response_sent) {
702 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
703 							 "Internal error");
704 		}
705 		nvmf_rpc_listener_ctx_free(ctx);
706 		/* Can't really do anything to recover here - subsystem will remain paused. */
707 	}
708 }
709 static void
710 nvmf_rpc_stop_listen_async_done(void *cb_arg, int status)
711 {
712 	struct nvmf_rpc_listener_ctx *ctx = cb_arg;
713 
714 	if (status) {
715 		SPDK_ERRLOG("Unable to stop listener.\n");
716 		spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
717 						     "error stopping listener: %d", status);
718 		ctx->response_sent = true;
719 	}
720 
721 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
722 		if (!ctx->response_sent) {
723 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
724 							 "Internal error");
725 		}
726 		nvmf_rpc_listener_ctx_free(ctx);
727 		/* Can't really do anything to recover here - subsystem will remain paused. */
728 	}
729 }
730 
731 static void
732 nvmf_rpc_set_ana_state_done(void *cb_arg, int status)
733 {
734 	struct nvmf_rpc_listener_ctx *ctx = cb_arg;
735 
736 	if (status) {
737 		SPDK_ERRLOG("Unable to set ANA state.\n");
738 		spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
739 						     "error setting ANA state: %d", status);
740 		ctx->response_sent = true;
741 	}
742 
743 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
744 		if (!ctx->response_sent) {
745 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
746 							 "Internal error");
747 		}
748 		nvmf_rpc_listener_ctx_free(ctx);
749 		/* Can't really do anything to recover here - subsystem will remain paused. */
750 	}
751 }
752 
753 static void
754 nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem,
755 		       void *cb_arg, int status)
756 {
757 	struct nvmf_rpc_listener_ctx *ctx = cb_arg;
758 	int rc;
759 
760 	if (ctx->op == NVMF_RPC_LISTEN_ADD) {
761 		if (!nvmf_subsystem_find_listener(subsystem, &ctx->trid)) {
762 			rc = spdk_nvmf_tgt_listen_ext(ctx->tgt, &ctx->trid, &ctx->opts);
763 			if (rc == 0) {
764 				spdk_nvmf_subsystem_add_listener_ext(ctx->subsystem, &ctx->trid, nvmf_rpc_subsystem_listen, ctx,
765 								     &ctx->listener_opts);
766 				return;
767 			}
768 
769 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
770 							 "Invalid parameters");
771 			ctx->response_sent = true;
772 		}
773 	} else if (ctx->op == NVMF_RPC_LISTEN_REMOVE) {
774 		rc = spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid);
775 		if (rc == 0) {
776 			spdk_nvmf_transport_stop_listen_async(ctx->transport, &ctx->trid, subsystem,
777 							      nvmf_rpc_stop_listen_async_done, ctx);
778 			return;
779 		}
780 		SPDK_ERRLOG("Unable to remove listener, rc %d\n", rc);
781 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
782 						 "Invalid parameters");
783 		ctx->response_sent = true;
784 	} else if (ctx->op == NVMF_RPC_LISTEN_SET_ANA_STATE) {
785 		nvmf_subsystem_set_ana_state(subsystem, &ctx->trid, ctx->ana_state, ctx->anagrpid,
786 					     nvmf_rpc_set_ana_state_done, ctx);
787 		return;
788 	} else {
789 		SPDK_UNREACHABLE();
790 	}
791 
792 	if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) {
793 		if (!ctx->response_sent) {
794 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
795 							 "Internal error");
796 		}
797 		nvmf_rpc_listener_ctx_free(ctx);
798 		/* Can't really do anything to recover here - subsystem will remain paused. */
799 	}
800 }
801 
802 static int
803 rpc_listen_address_to_trid(const struct rpc_listen_address *address,
804 			   struct spdk_nvme_transport_id *trid)
805 {
806 	size_t len;
807 
808 	memset(trid, 0, sizeof(*trid));
809 
810 	if (spdk_nvme_transport_id_populate_trstring(trid, address->transport)) {
811 		SPDK_ERRLOG("Invalid transport string: %s\n", address->transport);
812 		return -EINVAL;
813 	}
814 
815 	if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->transport)) {
816 		SPDK_ERRLOG("Invalid transport type: %s\n", address->transport);
817 		return -EINVAL;
818 	}
819 
820 	if (address->adrfam) {
821 		if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) {
822 			SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam);
823 			return -EINVAL;
824 		}
825 	} else {
826 		trid->adrfam = SPDK_NVMF_ADRFAM_IPV4;
827 	}
828 
829 	len = strlen(address->traddr);
830 	if (len > sizeof(trid->traddr) - 1) {
831 		SPDK_ERRLOG("Transport address longer than %zu characters: %s\n",
832 			    sizeof(trid->traddr) - 1, address->traddr);
833 		return -EINVAL;
834 	}
835 	memcpy(trid->traddr, address->traddr, len + 1);
836 
837 	trid->trsvcid[0] = '\0';
838 	if (address->trsvcid) {
839 		len = strlen(address->trsvcid);
840 		if (len > sizeof(trid->trsvcid) - 1) {
841 			SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n",
842 				    sizeof(trid->trsvcid) - 1, address->trsvcid);
843 			return -EINVAL;
844 		}
845 		memcpy(trid->trsvcid, address->trsvcid, len + 1);
846 	}
847 
848 	return 0;
849 }
850 
851 static void
852 rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request,
853 				const struct spdk_json_val *params)
854 {
855 	struct nvmf_rpc_listener_ctx *ctx;
856 	struct spdk_nvmf_subsystem *subsystem;
857 	struct spdk_nvmf_tgt *tgt;
858 	int rc;
859 
860 	ctx = calloc(1, sizeof(*ctx));
861 	if (!ctx) {
862 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
863 		return;
864 	}
865 
866 	ctx->request = request;
867 
868 	spdk_nvmf_subsystem_listener_opts_init(&ctx->listener_opts, sizeof(ctx->listener_opts));
869 
870 	if (spdk_json_decode_object_relaxed(params, nvmf_rpc_listener_decoder,
871 					    SPDK_COUNTOF(nvmf_rpc_listener_decoder),
872 					    ctx)) {
873 		SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n");
874 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
875 		nvmf_rpc_listener_ctx_free(ctx);
876 		return;
877 	}
878 
879 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
880 	if (!tgt) {
881 		SPDK_ERRLOG("Unable to find a target object.\n");
882 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
883 						 "Unable to find a target.");
884 		nvmf_rpc_listener_ctx_free(ctx);
885 		return;
886 	}
887 	ctx->tgt = tgt;
888 
889 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
890 	if (!subsystem) {
891 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
892 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
893 		nvmf_rpc_listener_ctx_free(ctx);
894 		return;
895 	}
896 
897 	ctx->subsystem = subsystem;
898 
899 	if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
900 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
901 						 "Invalid parameters");
902 		nvmf_rpc_listener_ctx_free(ctx);
903 		return;
904 	}
905 
906 	ctx->op = NVMF_RPC_LISTEN_ADD;
907 	spdk_nvmf_listen_opts_init(&ctx->opts, sizeof(ctx->opts));
908 	ctx->opts.transport_specific = params;
909 	if (subsystem->flags.allow_any_host == 1 && ctx->listener_opts.secure_channel == true) {
910 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
911 						 "Cannot establish secure channel, when 'allow_any_host' is set");
912 		nvmf_rpc_listener_ctx_free(ctx);
913 		return;
914 	}
915 	ctx->opts.secure_channel = ctx->listener_opts.secure_channel;
916 
917 	rc = spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx);
918 	if (rc != 0) {
919 		if (rc == -EBUSY) {
920 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
921 							 "subsystem busy, retry later.\n");
922 		} else {
923 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
924 		}
925 		nvmf_rpc_listener_ctx_free(ctx);
926 	}
927 }
928 SPDK_RPC_REGISTER("nvmf_subsystem_add_listener", rpc_nvmf_subsystem_add_listener,
929 		  SPDK_RPC_RUNTIME);
930 
931 static void
932 rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request,
933 				   const struct spdk_json_val *params)
934 {
935 	struct nvmf_rpc_listener_ctx *ctx;
936 	struct spdk_nvmf_subsystem *subsystem;
937 	struct spdk_nvmf_tgt *tgt;
938 	int rc;
939 
940 	ctx = calloc(1, sizeof(*ctx));
941 	if (!ctx) {
942 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
943 		return;
944 	}
945 
946 	ctx->request = request;
947 
948 	if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder,
949 				    SPDK_COUNTOF(nvmf_rpc_listener_decoder),
950 				    ctx)) {
951 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
952 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
953 		nvmf_rpc_listener_ctx_free(ctx);
954 		return;
955 	}
956 
957 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
958 	if (!tgt) {
959 		SPDK_ERRLOG("Unable to find a target object.\n");
960 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
961 						 "Unable to find a target.");
962 		nvmf_rpc_listener_ctx_free(ctx);
963 		return;
964 	}
965 	ctx->tgt = tgt;
966 
967 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
968 	if (!subsystem) {
969 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
970 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
971 		nvmf_rpc_listener_ctx_free(ctx);
972 		return;
973 	}
974 
975 	ctx->subsystem = subsystem;
976 
977 	if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
978 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
979 						 "Invalid parameters");
980 		nvmf_rpc_listener_ctx_free(ctx);
981 		return;
982 	}
983 
984 	ctx->transport = spdk_nvmf_tgt_get_transport(tgt, ctx->trid.trstring);
985 	if (!ctx->transport) {
986 		SPDK_ERRLOG("Unable to find %s transport. The transport must be created first also make sure it is properly registered.\n",
987 			    ctx->trid.trstring);
988 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
989 						 "Invalid parameters");
990 		nvmf_rpc_listener_ctx_free(ctx);
991 		return;
992 	}
993 
994 	ctx->op = NVMF_RPC_LISTEN_REMOVE;
995 
996 	rc = spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx);
997 	if (rc != 0) {
998 		if (rc == -EBUSY) {
999 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1000 							 "subsystem busy, retry later.\n");
1001 		} else {
1002 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1003 		}
1004 		nvmf_rpc_listener_ctx_free(ctx);
1005 	}
1006 }
1007 SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", rpc_nvmf_subsystem_remove_listener,
1008 		  SPDK_RPC_RUNTIME);
1009 
1010 struct nvmf_rpc_referral_ctx {
1011 	char				*tgt_name;
1012 	struct spdk_nvmf_tgt		*tgt;
1013 	struct spdk_nvmf_transport	*transport;
1014 	struct spdk_nvmf_subsystem	*subsystem;
1015 	struct rpc_listen_address	address;
1016 	struct spdk_jsonrpc_request	*request;
1017 	struct spdk_nvme_transport_id	trid;
1018 	bool				response_sent;
1019 	bool				secure_channel;
1020 };
1021 
1022 static const struct spdk_json_object_decoder nvmf_rpc_referral_decoder[] = {
1023 	{"address", offsetof(struct nvmf_rpc_referral_ctx, address), decode_rpc_listen_address},
1024 	{"tgt_name", offsetof(struct nvmf_rpc_referral_ctx, tgt_name), spdk_json_decode_string, true},
1025 	{"secure_channel", offsetof(struct nvmf_rpc_referral_ctx, secure_channel), spdk_json_decode_bool, true},
1026 };
1027 
1028 static void
1029 nvmf_rpc_referral_ctx_free(struct nvmf_rpc_referral_ctx *ctx)
1030 {
1031 	free(ctx->tgt_name);
1032 	free_rpc_listen_address(&ctx->address);
1033 	free(ctx);
1034 }
1035 
1036 static void
1037 rpc_nvmf_add_referral(struct spdk_jsonrpc_request *request,
1038 		      const struct spdk_json_val *params)
1039 {
1040 	struct nvmf_rpc_referral_ctx *ctx;
1041 	struct spdk_nvmf_tgt *tgt;
1042 	int rc;
1043 
1044 	ctx = calloc(1, sizeof(*ctx));
1045 	if (!ctx) {
1046 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1047 		return;
1048 	}
1049 
1050 	ctx->request = request;
1051 
1052 	if (spdk_json_decode_object_relaxed(params, nvmf_rpc_referral_decoder,
1053 					    SPDK_COUNTOF(nvmf_rpc_referral_decoder),
1054 					    ctx)) {
1055 		SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n");
1056 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1057 		nvmf_rpc_referral_ctx_free(ctx);
1058 		return;
1059 	}
1060 
1061 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1062 	if (!tgt) {
1063 		SPDK_ERRLOG("Unable to find a target object.\n");
1064 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1065 						 "Unable to find a target.");
1066 		nvmf_rpc_referral_ctx_free(ctx);
1067 		return;
1068 	}
1069 	ctx->tgt = tgt;
1070 
1071 	if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
1072 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1073 						 "Invalid parameters");
1074 		nvmf_rpc_referral_ctx_free(ctx);
1075 		return;
1076 	}
1077 
1078 	if ((ctx->trid.trtype == SPDK_NVME_TRANSPORT_TCP ||
1079 	     ctx->trid.trtype == SPDK_NVME_TRANSPORT_RDMA) &&
1080 	    !strlen(ctx->trid.trsvcid)) {
1081 		SPDK_ERRLOG("Service ID is required.\n");
1082 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1083 						 "Service ID is required.");
1084 		nvmf_rpc_referral_ctx_free(ctx);
1085 		return;
1086 	}
1087 
1088 	rc = spdk_nvmf_tgt_add_referral(tgt, &ctx->trid, ctx->secure_channel);
1089 	if (rc != 0) {
1090 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1091 						 "Internal error");
1092 		nvmf_rpc_referral_ctx_free(ctx);
1093 		return;
1094 	}
1095 
1096 	nvmf_rpc_referral_ctx_free(ctx);
1097 
1098 	spdk_jsonrpc_send_bool_response(request, true);
1099 }
1100 
1101 SPDK_RPC_REGISTER("nvmf_discovery_add_referral", rpc_nvmf_add_referral,
1102 		  SPDK_RPC_RUNTIME);
1103 
1104 static void
1105 rpc_nvmf_remove_referral(struct spdk_jsonrpc_request *request,
1106 			 const struct spdk_json_val *params)
1107 {
1108 	struct nvmf_rpc_referral_ctx *ctx;
1109 	struct spdk_nvmf_tgt *tgt;
1110 
1111 	ctx = calloc(1, sizeof(*ctx));
1112 	if (!ctx) {
1113 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1114 		return;
1115 	}
1116 
1117 	ctx->request = request;
1118 
1119 	if (spdk_json_decode_object(params, nvmf_rpc_referral_decoder,
1120 				    SPDK_COUNTOF(nvmf_rpc_referral_decoder),
1121 				    ctx)) {
1122 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1123 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1124 		nvmf_rpc_referral_ctx_free(ctx);
1125 		return;
1126 	}
1127 
1128 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1129 	if (!tgt) {
1130 		SPDK_ERRLOG("Unable to find a target object.\n");
1131 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1132 						 "Unable to find a target.");
1133 		nvmf_rpc_referral_ctx_free(ctx);
1134 		return;
1135 	}
1136 	ctx->tgt = tgt;
1137 
1138 	if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
1139 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1140 						 "Invalid parameters");
1141 		nvmf_rpc_referral_ctx_free(ctx);
1142 		return;
1143 	}
1144 
1145 	if (spdk_nvmf_tgt_remove_referral(tgt, &ctx->trid)) {
1146 		SPDK_ERRLOG("Failed to remove referral.\n");
1147 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1148 						 "Unable to remove a referral.");
1149 		nvmf_rpc_referral_ctx_free(ctx);
1150 		return;
1151 	}
1152 
1153 	nvmf_rpc_referral_ctx_free(ctx);
1154 
1155 	spdk_jsonrpc_send_bool_response(request, true);
1156 }
1157 
1158 SPDK_RPC_REGISTER("nvmf_discovery_remove_referral", rpc_nvmf_remove_referral,
1159 		  SPDK_RPC_RUNTIME);
1160 
1161 static void
1162 dump_nvmf_referral(struct spdk_json_write_ctx *w,
1163 		   struct spdk_nvmf_referral *referral)
1164 {
1165 	spdk_json_write_object_begin(w);
1166 
1167 	spdk_json_write_named_object_begin(w, "address");
1168 	nvmf_transport_listen_dump_trid(&referral->trid, w);
1169 	spdk_json_write_object_end(w);
1170 	spdk_json_write_named_bool(w, "secure_channel",
1171 				   referral->entry.treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_REQUIRED);
1172 
1173 	spdk_json_write_object_end(w);
1174 }
1175 
1176 struct rpc_get_referrals_ctx {
1177 	char *tgt_name;
1178 };
1179 
1180 static const struct spdk_json_object_decoder rpc_get_referrals_decoders[] = {
1181 	{"tgt_name", offsetof(struct rpc_get_referrals_ctx, tgt_name), spdk_json_decode_string, true},
1182 };
1183 
1184 static void
1185 free_rpc_get_referrals_ctx(struct rpc_get_referrals_ctx *ctx)
1186 {
1187 	free(ctx->tgt_name);
1188 	free(ctx);
1189 }
1190 
1191 static void
1192 rpc_nvmf_get_referrals(struct spdk_jsonrpc_request *request,
1193 		       const struct spdk_json_val *params)
1194 {
1195 	struct rpc_get_referrals_ctx *ctx;
1196 	struct spdk_nvmf_tgt *tgt;
1197 	struct spdk_json_write_ctx *w;
1198 	struct spdk_nvmf_referral *referral;
1199 
1200 	ctx = calloc(1, sizeof(*ctx));
1201 	if (!ctx) {
1202 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1203 						 "Out of memory");
1204 		return;
1205 	}
1206 
1207 	if (params) {
1208 		if (spdk_json_decode_object(params, rpc_get_referrals_decoders,
1209 					    SPDK_COUNTOF(rpc_get_referrals_decoders),
1210 					    ctx)) {
1211 			SPDK_ERRLOG("spdk_json_decode_object failed\n");
1212 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1213 							 "Invalid parameters");
1214 			free_rpc_get_referrals_ctx(ctx);
1215 			return;
1216 		}
1217 	}
1218 
1219 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1220 	if (!tgt) {
1221 		SPDK_ERRLOG("Unable to find a target object.\n");
1222 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1223 						 "Unable to find a target");
1224 		free_rpc_get_referrals_ctx(ctx);
1225 		return;
1226 	}
1227 
1228 	w = spdk_jsonrpc_begin_result(request);
1229 
1230 	spdk_json_write_array_begin(w);
1231 
1232 	TAILQ_FOREACH(referral, &tgt->referrals, link) {
1233 		dump_nvmf_referral(w, referral);
1234 	}
1235 
1236 	spdk_json_write_array_end(w);
1237 
1238 	spdk_jsonrpc_end_result(request, w);
1239 
1240 	free_rpc_get_referrals_ctx(ctx);
1241 }
1242 SPDK_RPC_REGISTER("nvmf_discovery_get_referrals", rpc_nvmf_get_referrals,
1243 		  SPDK_RPC_RUNTIME);
1244 
1245 static const struct spdk_json_object_decoder nvmf_rpc_set_ana_state_decoder[] = {
1246 	{"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string},
1247 	{"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address},
1248 	{"ana_state", offsetof(struct nvmf_rpc_listener_ctx, ana_state_str), spdk_json_decode_string},
1249 	{"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true},
1250 	{"anagrpid", offsetof(struct nvmf_rpc_listener_ctx, anagrpid), spdk_json_decode_uint32, true},
1251 };
1252 
1253 static int
1254 rpc_ana_state_parse(const char *str, enum spdk_nvme_ana_state *ana_state)
1255 {
1256 	if (ana_state == NULL || str == NULL) {
1257 		return -EINVAL;
1258 	}
1259 
1260 	if (strcasecmp(str, "optimized") == 0) {
1261 		*ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
1262 	} else if (strcasecmp(str, "non_optimized") == 0) {
1263 		*ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
1264 	} else if (strcasecmp(str, "inaccessible") == 0) {
1265 		*ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
1266 	} else {
1267 		return -ENOENT;
1268 	}
1269 
1270 	return 0;
1271 }
1272 
1273 static void
1274 rpc_nvmf_subsystem_listener_set_ana_state(struct spdk_jsonrpc_request *request,
1275 		const struct spdk_json_val *params)
1276 {
1277 	struct nvmf_rpc_listener_ctx *ctx;
1278 	struct spdk_nvmf_subsystem *subsystem;
1279 	struct spdk_nvmf_tgt *tgt;
1280 
1281 	ctx = calloc(1, sizeof(*ctx));
1282 	if (!ctx) {
1283 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1284 						 "Out of memory");
1285 		return;
1286 	}
1287 
1288 	ctx->request = request;
1289 
1290 	if (spdk_json_decode_object(params, nvmf_rpc_set_ana_state_decoder,
1291 				    SPDK_COUNTOF(nvmf_rpc_set_ana_state_decoder),
1292 				    ctx)) {
1293 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1294 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1295 						 "Invalid parameters");
1296 		nvmf_rpc_listener_ctx_free(ctx);
1297 		return;
1298 	}
1299 
1300 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1301 	if (!tgt) {
1302 		SPDK_ERRLOG("Unable to find a target object.\n");
1303 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1304 						 "Unable to find a target.\n");
1305 		nvmf_rpc_listener_ctx_free(ctx);
1306 		return;
1307 	}
1308 
1309 	ctx->tgt = tgt;
1310 
1311 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
1312 	if (!subsystem) {
1313 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1314 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1315 						     "Unable to find subsystem with NQN %s",
1316 						     ctx->nqn);
1317 		nvmf_rpc_listener_ctx_free(ctx);
1318 		return;
1319 	}
1320 
1321 	ctx->subsystem = subsystem;
1322 
1323 	if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
1324 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1325 						 "Invalid parameters");
1326 		nvmf_rpc_listener_ctx_free(ctx);
1327 		return;
1328 	}
1329 
1330 	if (rpc_ana_state_parse(ctx->ana_state_str, &ctx->ana_state)) {
1331 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1332 						 "Invalid parameters");
1333 		nvmf_rpc_listener_ctx_free(ctx);
1334 		return;
1335 	}
1336 
1337 	ctx->op = NVMF_RPC_LISTEN_SET_ANA_STATE;
1338 
1339 	if (spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx)) {
1340 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1341 						 "Internal error");
1342 		nvmf_rpc_listener_ctx_free(ctx);
1343 	}
1344 }
1345 SPDK_RPC_REGISTER("nvmf_subsystem_listener_set_ana_state",
1346 		  rpc_nvmf_subsystem_listener_set_ana_state, SPDK_RPC_RUNTIME);
1347 
1348 struct spdk_nvmf_ns_params {
1349 	char *bdev_name;
1350 	char *ptpl_file;
1351 	uint32_t nsid;
1352 	char nguid[16];
1353 	char eui64[8];
1354 	struct spdk_uuid uuid;
1355 	uint32_t anagrpid;
1356 };
1357 
1358 static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = {
1359 	{"nsid", offsetof(struct spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true},
1360 	{"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string},
1361 	{"ptpl_file", offsetof(struct spdk_nvmf_ns_params, ptpl_file), spdk_json_decode_string, true},
1362 	{"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true},
1363 	{"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true},
1364 	{"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), decode_ns_uuid, true},
1365 	{"anagrpid", offsetof(struct spdk_nvmf_ns_params, anagrpid), spdk_json_decode_uint32, true},
1366 };
1367 
1368 static int
1369 decode_rpc_ns_params(const struct spdk_json_val *val, void *out)
1370 {
1371 	struct spdk_nvmf_ns_params *ns_params = out;
1372 
1373 	return spdk_json_decode_object(val, rpc_ns_params_decoders,
1374 				       SPDK_COUNTOF(rpc_ns_params_decoders),
1375 				       ns_params);
1376 }
1377 
1378 struct nvmf_rpc_ns_ctx {
1379 	char *nqn;
1380 	char *tgt_name;
1381 	struct spdk_nvmf_ns_params ns_params;
1382 
1383 	struct spdk_jsonrpc_request *request;
1384 	bool response_sent;
1385 };
1386 
1387 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = {
1388 	{"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string},
1389 	{"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params},
1390 	{"tgt_name", offsetof(struct nvmf_rpc_ns_ctx, tgt_name), spdk_json_decode_string, true},
1391 };
1392 
1393 static void
1394 nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx)
1395 {
1396 	free(ctx->nqn);
1397 	free(ctx->tgt_name);
1398 	free(ctx->ns_params.bdev_name);
1399 	free(ctx->ns_params.ptpl_file);
1400 	free(ctx);
1401 }
1402 
1403 static void
1404 nvmf_rpc_ns_failback_resumed(struct spdk_nvmf_subsystem *subsystem,
1405 			     void *cb_arg, int status)
1406 {
1407 	struct nvmf_rpc_ns_ctx *ctx = cb_arg;
1408 	struct spdk_jsonrpc_request *request = ctx->request;
1409 
1410 	if (status) {
1411 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1412 						 "Unable to add ns, subsystem in invalid state");
1413 	} else {
1414 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1415 						 "Unable to add ns, subsystem in active state");
1416 	}
1417 
1418 	nvmf_rpc_ns_ctx_free(ctx);
1419 }
1420 
1421 static void
1422 nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem,
1423 		    void *cb_arg, int status)
1424 {
1425 	struct nvmf_rpc_ns_ctx *ctx = cb_arg;
1426 	struct spdk_jsonrpc_request *request = ctx->request;
1427 	uint32_t nsid = ctx->ns_params.nsid;
1428 	bool response_sent = ctx->response_sent;
1429 	struct spdk_json_write_ctx *w;
1430 	int rc;
1431 
1432 	/* The case where the call to add the namespace was successful, but the subsystem couldn't be resumed. */
1433 	if (status && !ctx->response_sent) {
1434 		rc = spdk_nvmf_subsystem_remove_ns(subsystem, nsid);
1435 		if (rc != 0) {
1436 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1437 							 "Unable to add ns, subsystem in invalid state");
1438 			nvmf_rpc_ns_ctx_free(ctx);
1439 			return;
1440 		}
1441 
1442 		rc = spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_failback_resumed, ctx);
1443 		if (rc != 0) {
1444 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1445 			nvmf_rpc_ns_ctx_free(ctx);
1446 			return;
1447 		}
1448 
1449 		return;
1450 	}
1451 
1452 	nvmf_rpc_ns_ctx_free(ctx);
1453 
1454 	if (response_sent) {
1455 		return;
1456 	}
1457 
1458 	w = spdk_jsonrpc_begin_result(request);
1459 	spdk_json_write_uint32(w, nsid);
1460 	spdk_jsonrpc_end_result(request, w);
1461 }
1462 
1463 static void
1464 nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem,
1465 		   void *cb_arg, int status)
1466 {
1467 	struct nvmf_rpc_ns_ctx *ctx = cb_arg;
1468 	struct spdk_nvmf_ns_opts ns_opts;
1469 
1470 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
1471 	ns_opts.nsid = ctx->ns_params.nsid;
1472 
1473 	SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ctx->ns_params.nguid), "size mismatch");
1474 	memcpy(ns_opts.nguid, ctx->ns_params.nguid, sizeof(ns_opts.nguid));
1475 
1476 	SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch");
1477 	memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64));
1478 
1479 	if (!spdk_uuid_is_null(&ctx->ns_params.uuid)) {
1480 		ns_opts.uuid = ctx->ns_params.uuid;
1481 	}
1482 
1483 	ns_opts.anagrpid = ctx->ns_params.anagrpid;
1484 
1485 	ctx->ns_params.nsid = spdk_nvmf_subsystem_add_ns_ext(subsystem, ctx->ns_params.bdev_name,
1486 			      &ns_opts, sizeof(ns_opts),
1487 			      ctx->ns_params.ptpl_file);
1488 	if (ctx->ns_params.nsid == 0) {
1489 		SPDK_ERRLOG("Unable to add namespace\n");
1490 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1491 						 "Invalid parameters");
1492 		ctx->response_sent = true;
1493 		goto resume;
1494 	}
1495 
1496 resume:
1497 	if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_resumed, ctx)) {
1498 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1499 		nvmf_rpc_ns_ctx_free(ctx);
1500 	}
1501 }
1502 
1503 static void
1504 rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request,
1505 			  const struct spdk_json_val *params)
1506 {
1507 	struct nvmf_rpc_ns_ctx *ctx;
1508 	struct spdk_nvmf_subsystem *subsystem;
1509 	struct spdk_nvmf_tgt *tgt;
1510 	int rc;
1511 
1512 	ctx = calloc(1, sizeof(*ctx));
1513 	if (!ctx) {
1514 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1515 		return;
1516 	}
1517 
1518 	if (spdk_json_decode_object(params, nvmf_rpc_subsystem_ns_decoder,
1519 				    SPDK_COUNTOF(nvmf_rpc_subsystem_ns_decoder),
1520 				    ctx)) {
1521 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1522 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1523 		nvmf_rpc_ns_ctx_free(ctx);
1524 		return;
1525 	}
1526 
1527 	ctx->request = request;
1528 	ctx->response_sent = false;
1529 
1530 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1531 	if (!tgt) {
1532 		SPDK_ERRLOG("Unable to find a target object.\n");
1533 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1534 						 "Unable to find a target.");
1535 		nvmf_rpc_ns_ctx_free(ctx);
1536 		return;
1537 	}
1538 
1539 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
1540 	if (!subsystem) {
1541 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1542 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1543 		nvmf_rpc_ns_ctx_free(ctx);
1544 		return;
1545 	}
1546 
1547 	rc = spdk_nvmf_subsystem_pause(subsystem, ctx->ns_params.nsid, nvmf_rpc_ns_paused, ctx);
1548 	if (rc != 0) {
1549 		if (rc == -EBUSY) {
1550 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1551 							 "subsystem busy, retry later.\n");
1552 		} else {
1553 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1554 		}
1555 		nvmf_rpc_ns_ctx_free(ctx);
1556 	}
1557 }
1558 SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", rpc_nvmf_subsystem_add_ns, SPDK_RPC_RUNTIME)
1559 
1560 struct nvmf_rpc_remove_ns_ctx {
1561 	char *nqn;
1562 	char *tgt_name;
1563 	uint32_t nsid;
1564 
1565 	struct spdk_jsonrpc_request *request;
1566 	bool response_sent;
1567 };
1568 
1569 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = {
1570 	{"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string},
1571 	{"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32},
1572 	{"tgt_name", offsetof(struct nvmf_rpc_remove_ns_ctx, tgt_name), spdk_json_decode_string, true},
1573 };
1574 
1575 static void
1576 nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx)
1577 {
1578 	free(ctx->nqn);
1579 	free(ctx->tgt_name);
1580 	free(ctx);
1581 }
1582 
1583 static void
1584 nvmf_rpc_remove_ns_resumed(struct spdk_nvmf_subsystem *subsystem,
1585 			   void *cb_arg, int status)
1586 {
1587 	struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg;
1588 	struct spdk_jsonrpc_request *request = ctx->request;
1589 	bool response_sent = ctx->response_sent;
1590 
1591 	nvmf_rpc_remove_ns_ctx_free(ctx);
1592 
1593 	if (response_sent) {
1594 		return;
1595 	}
1596 
1597 	spdk_jsonrpc_send_bool_response(request, true);
1598 }
1599 
1600 static void
1601 nvmf_rpc_remove_ns_paused(struct spdk_nvmf_subsystem *subsystem,
1602 			  void *cb_arg, int status)
1603 {
1604 	struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg;
1605 	int ret;
1606 
1607 	ret = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid);
1608 	if (ret < 0) {
1609 		SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid);
1610 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1611 						 "Invalid parameters");
1612 		ctx->response_sent = true;
1613 	}
1614 
1615 	if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx)) {
1616 		if (!ctx->response_sent) {
1617 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1618 		}
1619 		nvmf_rpc_remove_ns_ctx_free(ctx);
1620 	}
1621 }
1622 
1623 static void
1624 rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request,
1625 			     const struct spdk_json_val *params)
1626 {
1627 	struct nvmf_rpc_remove_ns_ctx *ctx;
1628 	struct spdk_nvmf_subsystem *subsystem;
1629 	struct spdk_nvmf_tgt *tgt;
1630 	int rc;
1631 
1632 	ctx = calloc(1, sizeof(*ctx));
1633 	if (!ctx) {
1634 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1635 		return;
1636 	}
1637 
1638 	if (spdk_json_decode_object(params, nvmf_rpc_subsystem_remove_ns_decoder,
1639 				    SPDK_COUNTOF(nvmf_rpc_subsystem_remove_ns_decoder),
1640 				    ctx)) {
1641 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1642 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1643 		nvmf_rpc_remove_ns_ctx_free(ctx);
1644 		return;
1645 	}
1646 
1647 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1648 	if (!tgt) {
1649 		SPDK_ERRLOG("Unable to find a target object.\n");
1650 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1651 						 "Unable to find a target.");
1652 		nvmf_rpc_remove_ns_ctx_free(ctx);
1653 		return;
1654 	}
1655 
1656 	ctx->request = request;
1657 	ctx->response_sent = false;
1658 
1659 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
1660 	if (!subsystem) {
1661 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1662 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1663 		nvmf_rpc_remove_ns_ctx_free(ctx);
1664 		return;
1665 	}
1666 
1667 	rc = spdk_nvmf_subsystem_pause(subsystem, ctx->nsid, nvmf_rpc_remove_ns_paused, ctx);
1668 	if (rc != 0) {
1669 		if (rc == -EBUSY) {
1670 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1671 							 "subsystem busy, retry later.\n");
1672 		} else {
1673 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1674 		}
1675 		nvmf_rpc_remove_ns_ctx_free(ctx);
1676 	}
1677 }
1678 SPDK_RPC_REGISTER("nvmf_subsystem_remove_ns", rpc_nvmf_subsystem_remove_ns, SPDK_RPC_RUNTIME)
1679 
1680 struct nvmf_rpc_host_ctx {
1681 	struct spdk_jsonrpc_request *request;
1682 	char *nqn;
1683 	char *host;
1684 	char *tgt_name;
1685 	bool allow_any_host;
1686 };
1687 
1688 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = {
1689 	{"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string},
1690 	{"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string},
1691 	{"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true},
1692 };
1693 
1694 static void
1695 nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx)
1696 {
1697 	free(ctx->nqn);
1698 	free(ctx->host);
1699 	free(ctx->tgt_name);
1700 }
1701 
1702 static void
1703 rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request,
1704 			    const struct spdk_json_val *params)
1705 {
1706 	struct nvmf_rpc_host_ctx ctx = {};
1707 	struct spdk_nvmf_subsystem *subsystem;
1708 	struct spdk_nvmf_tgt *tgt;
1709 	int rc;
1710 
1711 	if (spdk_json_decode_object_relaxed(params, nvmf_rpc_subsystem_host_decoder,
1712 					    SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder),
1713 					    &ctx)) {
1714 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1715 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1716 		nvmf_rpc_host_ctx_free(&ctx);
1717 		return;
1718 	}
1719 
1720 	tgt = spdk_nvmf_get_tgt(ctx.tgt_name);
1721 	if (!tgt) {
1722 		SPDK_ERRLOG("Unable to find a target object.\n");
1723 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1724 						 "Unable to find a target.");
1725 		nvmf_rpc_host_ctx_free(&ctx);
1726 		return;
1727 	}
1728 
1729 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn);
1730 	if (!subsystem) {
1731 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn);
1732 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1733 		nvmf_rpc_host_ctx_free(&ctx);
1734 		return;
1735 	}
1736 
1737 	rc = spdk_nvmf_subsystem_add_host(subsystem, ctx.host, params);
1738 	if (rc != 0) {
1739 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1740 		nvmf_rpc_host_ctx_free(&ctx);
1741 		return;
1742 	}
1743 
1744 	spdk_jsonrpc_send_bool_response(request, true);
1745 	nvmf_rpc_host_ctx_free(&ctx);
1746 }
1747 SPDK_RPC_REGISTER("nvmf_subsystem_add_host", rpc_nvmf_subsystem_add_host, SPDK_RPC_RUNTIME)
1748 
1749 static void
1750 rpc_nvmf_subsystem_remove_host_done(void *_ctx, int status)
1751 {
1752 	struct nvmf_rpc_host_ctx *ctx = _ctx;
1753 
1754 	spdk_jsonrpc_send_bool_response(ctx->request, true);
1755 	nvmf_rpc_host_ctx_free(ctx);
1756 	free(ctx);
1757 }
1758 
1759 static void
1760 rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request,
1761 			       const struct spdk_json_val *params)
1762 {
1763 	struct nvmf_rpc_host_ctx *ctx;
1764 	struct spdk_nvmf_subsystem *subsystem;
1765 	struct spdk_nvmf_tgt *tgt;
1766 	int rc;
1767 
1768 	ctx = calloc(1, sizeof(*ctx));
1769 	if (ctx == NULL) {
1770 		SPDK_ERRLOG("Unable to allocate context to perform RPC\n");
1771 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1772 		return;
1773 	}
1774 
1775 	ctx->request = request;
1776 
1777 	if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder,
1778 				    SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder),
1779 				    ctx)) {
1780 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1781 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1782 		nvmf_rpc_host_ctx_free(ctx);
1783 		free(ctx);
1784 		return;
1785 	}
1786 
1787 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1788 	if (!tgt) {
1789 		SPDK_ERRLOG("Unable to find a target object.\n");
1790 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1791 						 "Unable to find a target.");
1792 		nvmf_rpc_host_ctx_free(ctx);
1793 		free(ctx);
1794 		return;
1795 	}
1796 
1797 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
1798 	if (!subsystem) {
1799 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1800 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1801 		nvmf_rpc_host_ctx_free(ctx);
1802 		free(ctx);
1803 		return;
1804 	}
1805 
1806 	rc = spdk_nvmf_subsystem_remove_host(subsystem, ctx->host);
1807 	if (rc != 0) {
1808 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1809 		nvmf_rpc_host_ctx_free(ctx);
1810 		free(ctx);
1811 		return;
1812 	}
1813 
1814 	rc = spdk_nvmf_subsystem_disconnect_host(subsystem, ctx->host,
1815 			rpc_nvmf_subsystem_remove_host_done,
1816 			ctx);
1817 	if (rc != 0) {
1818 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1819 		nvmf_rpc_host_ctx_free(ctx);
1820 		free(ctx);
1821 		return;
1822 	}
1823 }
1824 SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", rpc_nvmf_subsystem_remove_host,
1825 		  SPDK_RPC_RUNTIME)
1826 
1827 
1828 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = {
1829 	{"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string},
1830 	{"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool},
1831 	{"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true},
1832 };
1833 
1834 static void
1835 rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request,
1836 				  const struct spdk_json_val *params)
1837 {
1838 	struct nvmf_rpc_host_ctx ctx = {};
1839 	struct spdk_nvmf_subsystem *subsystem;
1840 	struct spdk_nvmf_tgt *tgt;
1841 	int rc;
1842 
1843 	if (spdk_json_decode_object(params, nvmf_rpc_subsystem_any_host_decoder,
1844 				    SPDK_COUNTOF(nvmf_rpc_subsystem_any_host_decoder),
1845 				    &ctx)) {
1846 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1847 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1848 		nvmf_rpc_host_ctx_free(&ctx);
1849 		return;
1850 	}
1851 
1852 	tgt = spdk_nvmf_get_tgt(ctx.tgt_name);
1853 	if (!tgt) {
1854 		SPDK_ERRLOG("Unable to find a target object.\n");
1855 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1856 						 "Unable to find a target.");
1857 		nvmf_rpc_host_ctx_free(&ctx);
1858 		return;
1859 	}
1860 
1861 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn);
1862 	if (!subsystem) {
1863 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn);
1864 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1865 		nvmf_rpc_host_ctx_free(&ctx);
1866 		return;
1867 	}
1868 
1869 	rc = spdk_nvmf_subsystem_set_allow_any_host(subsystem, ctx.allow_any_host);
1870 	if (rc != 0) {
1871 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1872 		nvmf_rpc_host_ctx_free(&ctx);
1873 		return;
1874 	}
1875 
1876 	spdk_jsonrpc_send_bool_response(request, true);
1877 	nvmf_rpc_host_ctx_free(&ctx);
1878 }
1879 SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", rpc_nvmf_subsystem_allow_any_host,
1880 		  SPDK_RPC_RUNTIME)
1881 
1882 struct nvmf_rpc_target_ctx {
1883 	char *name;
1884 	uint32_t max_subsystems;
1885 	char *discovery_filter;
1886 };
1887 
1888 static int
1889 decode_discovery_filter(const struct spdk_json_val *val, void *out)
1890 {
1891 	enum spdk_nvmf_tgt_discovery_filter *_filter = (enum spdk_nvmf_tgt_discovery_filter *)out;
1892 	enum spdk_nvmf_tgt_discovery_filter filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
1893 	char *tokens = spdk_json_strdup(val);
1894 	char *tok;
1895 	int rc = -EINVAL;
1896 	bool all_specified = false;
1897 
1898 	if (!tokens) {
1899 		return -ENOMEM;
1900 	}
1901 
1902 	tok = strtok(tokens, ",");
1903 	while (tok) {
1904 		if (strncmp(tok, "match_any", 9) == 0) {
1905 			if (filter != SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY) {
1906 				goto out;
1907 			}
1908 			filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
1909 			all_specified = true;
1910 		} else {
1911 			if (all_specified) {
1912 				goto out;
1913 			}
1914 			if (strncmp(tok, "transport", 9) == 0) {
1915 				filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE;
1916 			} else if (strncmp(tok, "address", 7) == 0) {
1917 				filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
1918 			} else if (strncmp(tok, "svcid", 5) == 0) {
1919 				filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
1920 			} else {
1921 				SPDK_ERRLOG("Invalid value %s\n", tok);
1922 				goto out;
1923 			}
1924 		}
1925 
1926 		tok = strtok(NULL, ",");
1927 	}
1928 
1929 	rc = 0;
1930 	*_filter = filter;
1931 
1932 out:
1933 	free(tokens);
1934 
1935 	return rc;
1936 }
1937 
1938 static const struct spdk_json_object_decoder nvmf_rpc_create_target_decoder[] = {
1939 	{"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string},
1940 	{"max_subsystems", offsetof(struct nvmf_rpc_target_ctx, max_subsystems), spdk_json_decode_uint32, true},
1941 	{"discovery_filter", offsetof(struct nvmf_rpc_target_ctx, discovery_filter), decode_discovery_filter, true}
1942 };
1943 
1944 static void
1945 rpc_nvmf_create_target(struct spdk_jsonrpc_request *request,
1946 		       const struct spdk_json_val *params)
1947 {
1948 	struct spdk_nvmf_target_opts	opts;
1949 	struct nvmf_rpc_target_ctx	ctx = {0};
1950 	struct spdk_nvmf_tgt		*tgt;
1951 	struct spdk_json_write_ctx	*w;
1952 
1953 	/* Decode parameters the first time to get the transport type */
1954 	if (spdk_json_decode_object(params, nvmf_rpc_create_target_decoder,
1955 				    SPDK_COUNTOF(nvmf_rpc_create_target_decoder),
1956 				    &ctx)) {
1957 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1958 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1959 		goto out;
1960 	}
1961 
1962 	snprintf(opts.name, NVMF_TGT_NAME_MAX_LENGTH, "%s", ctx.name);
1963 	opts.max_subsystems = ctx.max_subsystems;
1964 
1965 	if (spdk_nvmf_get_tgt(opts.name) != NULL) {
1966 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1967 						 "Target already exists.");
1968 		goto out;
1969 	}
1970 
1971 	tgt = spdk_nvmf_tgt_create(&opts);
1972 
1973 	if (tgt == NULL) {
1974 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1975 						 "Unable to create the requested target.");
1976 		goto out;
1977 	}
1978 
1979 	w = spdk_jsonrpc_begin_result(request);
1980 	spdk_json_write_string(w, spdk_nvmf_tgt_get_name(tgt));
1981 	spdk_jsonrpc_end_result(request, w);
1982 out:
1983 	free(ctx.name);
1984 	free(ctx.discovery_filter);
1985 }
1986 /* private */ SPDK_RPC_REGISTER("nvmf_create_target", rpc_nvmf_create_target, SPDK_RPC_RUNTIME);
1987 
1988 static const struct spdk_json_object_decoder nvmf_rpc_destroy_target_decoder[] = {
1989 	{"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string},
1990 };
1991 
1992 static void
1993 nvmf_rpc_destroy_target_done(void *ctx, int status)
1994 {
1995 	struct spdk_jsonrpc_request	*request = ctx;
1996 
1997 	spdk_jsonrpc_send_bool_response(request, true);
1998 }
1999 
2000 static void
2001 rpc_nvmf_delete_target(struct spdk_jsonrpc_request *request,
2002 		       const struct spdk_json_val *params)
2003 {
2004 	struct nvmf_rpc_target_ctx	ctx = {0};
2005 	struct spdk_nvmf_tgt		*tgt;
2006 
2007 	/* Decode parameters the first time to get the transport type */
2008 	if (spdk_json_decode_object(params, nvmf_rpc_destroy_target_decoder,
2009 				    SPDK_COUNTOF(nvmf_rpc_destroy_target_decoder),
2010 				    &ctx)) {
2011 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
2012 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
2013 		free(ctx.name);
2014 		return;
2015 	}
2016 
2017 	tgt = spdk_nvmf_get_tgt(ctx.name);
2018 
2019 	if (tgt == NULL) {
2020 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
2021 						 "The specified target doesn't exist, cannot delete it.");
2022 		free(ctx.name);
2023 		return;
2024 	}
2025 
2026 	spdk_nvmf_tgt_destroy(tgt, nvmf_rpc_destroy_target_done, request);
2027 	free(ctx.name);
2028 }
2029 /* private */ SPDK_RPC_REGISTER("nvmf_delete_target", rpc_nvmf_delete_target, SPDK_RPC_RUNTIME);
2030 
2031 static void
2032 rpc_nvmf_get_targets(struct spdk_jsonrpc_request *request,
2033 		     const struct spdk_json_val *params)
2034 {
2035 	struct spdk_json_write_ctx	*w;
2036 	struct spdk_nvmf_tgt		*tgt;
2037 	const char			*name;
2038 
2039 	if (params != NULL) {
2040 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
2041 						 "nvmf_get_targets has no parameters.");
2042 		return;
2043 	}
2044 
2045 	w = spdk_jsonrpc_begin_result(request);
2046 	spdk_json_write_array_begin(w);
2047 
2048 	tgt = spdk_nvmf_get_first_tgt();
2049 
2050 	while (tgt != NULL) {
2051 		name = spdk_nvmf_tgt_get_name(tgt);
2052 		spdk_json_write_string(w, name);
2053 		tgt = spdk_nvmf_get_next_tgt(tgt);
2054 	}
2055 
2056 	spdk_json_write_array_end(w);
2057 	spdk_jsonrpc_end_result(request, w);
2058 }
2059 /* private */ SPDK_RPC_REGISTER("nvmf_get_targets", rpc_nvmf_get_targets, SPDK_RPC_RUNTIME);
2060 
2061 struct nvmf_rpc_create_transport_ctx {
2062 	char				*trtype;
2063 	char				*tgt_name;
2064 	struct spdk_nvmf_transport_opts	opts;
2065 	struct spdk_jsonrpc_request	*request;
2066 	struct spdk_nvmf_transport	*transport;
2067 	int				status;
2068 };
2069 
2070 /**
2071  * `max_qpairs_per_ctrlr` represents both admin and IO qpairs, that confuses
2072  * users when they configure a transport using RPC. So it was decided to
2073  * deprecate `max_qpairs_per_ctrlr` RPC parameter and use `max_io_qpairs_per_ctrlr`
2074  * But internal logic remains unchanged and SPDK expects that
2075  * spdk_nvmf_transport_opts::max_qpairs_per_ctrlr includes an admin qpair.
2076  * This function parses the number of IO qpairs and adds +1 for admin qpair.
2077  */
2078 static int
2079 nvmf_rpc_decode_max_io_qpairs(const struct spdk_json_val *val, void *out)
2080 {
2081 	uint16_t *i = out;
2082 	int rc;
2083 
2084 	rc = spdk_json_number_to_uint16(val, i);
2085 	if (rc == 0) {
2086 		(*i)++;
2087 	}
2088 
2089 	return rc;
2090 }
2091 
2092 static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[] = {
2093 	{	"trtype", offsetof(struct nvmf_rpc_create_transport_ctx, trtype), spdk_json_decode_string},
2094 	{
2095 		"max_queue_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_queue_depth),
2096 		spdk_json_decode_uint16, true
2097 	},
2098 	{
2099 		"max_io_qpairs_per_ctrlr", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_qpairs_per_ctrlr),
2100 		nvmf_rpc_decode_max_io_qpairs, true
2101 	},
2102 	{
2103 		"in_capsule_data_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.in_capsule_data_size),
2104 		spdk_json_decode_uint32, true
2105 	},
2106 	{
2107 		"max_io_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_io_size),
2108 		spdk_json_decode_uint32, true
2109 	},
2110 	{
2111 		"io_unit_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.io_unit_size),
2112 		spdk_json_decode_uint32, true
2113 	},
2114 	{
2115 		"max_aq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_aq_depth),
2116 		spdk_json_decode_uint32, true
2117 	},
2118 	{
2119 		"num_shared_buffers", offsetof(struct nvmf_rpc_create_transport_ctx, opts.num_shared_buffers),
2120 		spdk_json_decode_uint32, true
2121 	},
2122 	{
2123 		"buf_cache_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.buf_cache_size),
2124 		spdk_json_decode_uint32, true
2125 	},
2126 	{
2127 		"dif_insert_or_strip", offsetof(struct nvmf_rpc_create_transport_ctx, opts.dif_insert_or_strip),
2128 		spdk_json_decode_bool, true
2129 	},
2130 	{
2131 		"abort_timeout_sec", offsetof(struct nvmf_rpc_create_transport_ctx, opts.abort_timeout_sec),
2132 		spdk_json_decode_uint32, true
2133 	},
2134 	{
2135 		"zcopy", offsetof(struct nvmf_rpc_create_transport_ctx, opts.zcopy),
2136 		spdk_json_decode_bool, true
2137 	},
2138 	{
2139 		"tgt_name", offsetof(struct nvmf_rpc_create_transport_ctx, tgt_name),
2140 		spdk_json_decode_string, true
2141 	},
2142 	{
2143 		"acceptor_poll_rate", offsetof(struct nvmf_rpc_create_transport_ctx, opts.acceptor_poll_rate),
2144 		spdk_json_decode_uint32, true
2145 	},
2146 };
2147 
2148 static void
2149 nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx)
2150 {
2151 	free(ctx->trtype);
2152 	free(ctx->tgt_name);
2153 	free(ctx);
2154 }
2155 
2156 static void
2157 nvmf_rpc_transport_destroy_done_cb(void *cb_arg)
2158 {
2159 	struct nvmf_rpc_create_transport_ctx *ctx = cb_arg;
2160 
2161 	spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2162 					     "Failed to add transport to tgt.(%d)", ctx->status);
2163 	nvmf_rpc_create_transport_ctx_free(ctx);
2164 }
2165 
2166 static void
2167 nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status)
2168 {
2169 	struct nvmf_rpc_create_transport_ctx *ctx = cb_arg;
2170 
2171 	if (status) {
2172 		SPDK_ERRLOG("Failed to add transport to tgt.(%d)\n", status);
2173 		ctx->status = status;
2174 		spdk_nvmf_transport_destroy(ctx->transport, nvmf_rpc_transport_destroy_done_cb, ctx);
2175 		return;
2176 	}
2177 
2178 	spdk_jsonrpc_send_bool_response(ctx->request, true);
2179 	nvmf_rpc_create_transport_ctx_free(ctx);
2180 }
2181 
2182 static void
2183 nvmf_rpc_create_transport_done(void *cb_arg, struct spdk_nvmf_transport *transport)
2184 {
2185 	struct nvmf_rpc_create_transport_ctx *ctx = cb_arg;
2186 
2187 	if (!transport) {
2188 		SPDK_ERRLOG("Failed to create transport.\n");
2189 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2190 						 "Failed to create transport.");
2191 		nvmf_rpc_create_transport_ctx_free(ctx);
2192 		return;
2193 	}
2194 
2195 	ctx->transport = transport;
2196 
2197 	spdk_nvmf_tgt_add_transport(spdk_nvmf_get_tgt(ctx->tgt_name), transport,
2198 				    nvmf_rpc_tgt_add_transport_done, ctx);
2199 }
2200 
2201 static void
2202 rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request,
2203 			  const struct spdk_json_val *params)
2204 {
2205 	struct nvmf_rpc_create_transport_ctx *ctx;
2206 	struct spdk_nvmf_tgt *tgt;
2207 	int rc;
2208 
2209 	ctx = calloc(1, sizeof(*ctx));
2210 	if (!ctx) {
2211 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
2212 		return;
2213 	}
2214 
2215 	/* Decode parameters the first time to get the transport type */
2216 	if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder,
2217 					    SPDK_COUNTOF(nvmf_rpc_create_transport_decoder),
2218 					    ctx)) {
2219 		SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n");
2220 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
2221 		nvmf_rpc_create_transport_ctx_free(ctx);
2222 		return;
2223 	}
2224 
2225 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
2226 	if (!tgt) {
2227 		SPDK_ERRLOG("Unable to find a target object.\n");
2228 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2229 						 "Unable to find a target.");
2230 		nvmf_rpc_create_transport_ctx_free(ctx);
2231 		return;
2232 	}
2233 
2234 	/* Initialize all the transport options (based on transport type) and decode the
2235 	 * parameters again to update any options passed in rpc create transport call.
2236 	 */
2237 	if (!spdk_nvmf_transport_opts_init(ctx->trtype, &ctx->opts, sizeof(ctx->opts))) {
2238 		/* This can happen if user specifies PCIE transport type which isn't valid for
2239 		 * NVMe-oF.
2240 		 */
2241 		SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype);
2242 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
2243 						     "Invalid transport type '%s'", ctx->trtype);
2244 		nvmf_rpc_create_transport_ctx_free(ctx);
2245 		return;
2246 	}
2247 
2248 	if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder,
2249 					    SPDK_COUNTOF(nvmf_rpc_create_transport_decoder),
2250 					    ctx)) {
2251 		SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n");
2252 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
2253 		nvmf_rpc_create_transport_ctx_free(ctx);
2254 		return;
2255 	}
2256 
2257 	if (spdk_nvmf_tgt_get_transport(tgt, ctx->trtype)) {
2258 		SPDK_ERRLOG("Transport type '%s' already exists\n", ctx->trtype);
2259 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2260 						     "Transport type '%s' already exists", ctx->trtype);
2261 		nvmf_rpc_create_transport_ctx_free(ctx);
2262 		return;
2263 	}
2264 
2265 	/* Transport can parse additional params themselves */
2266 	ctx->opts.transport_specific = params;
2267 	ctx->request = request;
2268 
2269 	rc = spdk_nvmf_transport_create_async(ctx->trtype, &ctx->opts, nvmf_rpc_create_transport_done, ctx);
2270 	if (rc) {
2271 		SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype);
2272 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2273 						     "Transport type '%s' create failed", ctx->trtype);
2274 		nvmf_rpc_create_transport_ctx_free(ctx);
2275 	}
2276 }
2277 SPDK_RPC_REGISTER("nvmf_create_transport", rpc_nvmf_create_transport, SPDK_RPC_RUNTIME)
2278 
2279 struct rpc_get_transport {
2280 	char *trtype;
2281 	char *tgt_name;
2282 };
2283 
2284 static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = {
2285 	{"trtype", offsetof(struct rpc_get_transport, trtype), spdk_json_decode_string, true},
2286 	{"tgt_name", offsetof(struct rpc_get_transport, tgt_name), spdk_json_decode_string, true},
2287 };
2288 
2289 static void
2290 rpc_nvmf_get_transports(struct spdk_jsonrpc_request *request,
2291 			const struct spdk_json_val *params)
2292 {
2293 	struct rpc_get_transport req = { 0 };
2294 	struct spdk_json_write_ctx *w;
2295 	struct spdk_nvmf_transport *transport = NULL;
2296 	struct spdk_nvmf_tgt *tgt;
2297 
2298 	if (params) {
2299 		if (spdk_json_decode_object(params, rpc_get_transport_decoders,
2300 					    SPDK_COUNTOF(rpc_get_transport_decoders),
2301 					    &req)) {
2302 			SPDK_ERRLOG("spdk_json_decode_object failed\n");
2303 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
2304 			return;
2305 		}
2306 	}
2307 
2308 	tgt = spdk_nvmf_get_tgt(req.tgt_name);
2309 	if (!tgt) {
2310 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2311 						 "Unable to find a target.");
2312 		free(req.trtype);
2313 		free(req.tgt_name);
2314 		return;
2315 	}
2316 
2317 	if (req.trtype) {
2318 		transport = spdk_nvmf_tgt_get_transport(tgt, req.trtype);
2319 		if (transport == NULL) {
2320 			SPDK_ERRLOG("transport '%s' does not exist\n", req.trtype);
2321 			spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
2322 			free(req.trtype);
2323 			free(req.tgt_name);
2324 			return;
2325 		}
2326 	}
2327 
2328 	w = spdk_jsonrpc_begin_result(request);
2329 	spdk_json_write_array_begin(w);
2330 
2331 	if (transport) {
2332 		nvmf_transport_dump_opts(transport, w, false);
2333 	} else {
2334 		for (transport = spdk_nvmf_transport_get_first(tgt); transport != NULL;
2335 		     transport = spdk_nvmf_transport_get_next(transport)) {
2336 			nvmf_transport_dump_opts(transport, w, false);
2337 		}
2338 	}
2339 
2340 	spdk_json_write_array_end(w);
2341 	spdk_jsonrpc_end_result(request, w);
2342 	free(req.trtype);
2343 	free(req.tgt_name);
2344 }
2345 SPDK_RPC_REGISTER("nvmf_get_transports", rpc_nvmf_get_transports, SPDK_RPC_RUNTIME)
2346 
2347 struct rpc_nvmf_get_stats_ctx {
2348 	char *tgt_name;
2349 	struct spdk_nvmf_tgt *tgt;
2350 	struct spdk_jsonrpc_request *request;
2351 	struct spdk_json_write_ctx *w;
2352 };
2353 
2354 static const struct spdk_json_object_decoder rpc_get_stats_decoders[] = {
2355 	{"tgt_name", offsetof(struct rpc_nvmf_get_stats_ctx, tgt_name), spdk_json_decode_string, true},
2356 };
2357 
2358 static void
2359 free_get_stats_ctx(struct rpc_nvmf_get_stats_ctx *ctx)
2360 {
2361 	free(ctx->tgt_name);
2362 	free(ctx);
2363 }
2364 
2365 static void
2366 rpc_nvmf_get_stats_done(struct spdk_io_channel_iter *i, int status)
2367 {
2368 	struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2369 
2370 	spdk_json_write_array_end(ctx->w);
2371 	spdk_json_write_object_end(ctx->w);
2372 	spdk_jsonrpc_end_result(ctx->request, ctx->w);
2373 	free_get_stats_ctx(ctx);
2374 }
2375 
2376 static void
2377 _rpc_nvmf_get_stats(struct spdk_io_channel_iter *i)
2378 {
2379 	struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2380 	struct spdk_io_channel *ch;
2381 	struct spdk_nvmf_poll_group *group;
2382 
2383 	ch = spdk_get_io_channel(ctx->tgt);
2384 	group = spdk_io_channel_get_ctx(ch);
2385 
2386 	spdk_nvmf_poll_group_dump_stat(group, ctx->w);
2387 
2388 	spdk_put_io_channel(ch);
2389 	spdk_for_each_channel_continue(i, 0);
2390 }
2391 
2392 
2393 static void
2394 rpc_nvmf_get_stats(struct spdk_jsonrpc_request *request,
2395 		   const struct spdk_json_val *params)
2396 {
2397 	struct rpc_nvmf_get_stats_ctx *ctx;
2398 
2399 	ctx = calloc(1, sizeof(*ctx));
2400 	if (!ctx) {
2401 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2402 						 "Memory allocation error");
2403 		return;
2404 	}
2405 	ctx->request = request;
2406 
2407 	if (params) {
2408 		if (spdk_json_decode_object(params, rpc_get_stats_decoders,
2409 					    SPDK_COUNTOF(rpc_get_stats_decoders),
2410 					    ctx)) {
2411 			SPDK_ERRLOG("spdk_json_decode_object failed\n");
2412 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
2413 			free_get_stats_ctx(ctx);
2414 			return;
2415 		}
2416 	}
2417 
2418 	ctx->tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
2419 	if (!ctx->tgt) {
2420 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2421 						 "Unable to find a target.");
2422 		free_get_stats_ctx(ctx);
2423 		return;
2424 	}
2425 
2426 	ctx->w = spdk_jsonrpc_begin_result(ctx->request);
2427 	spdk_json_write_object_begin(ctx->w);
2428 	spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
2429 	spdk_json_write_named_array_begin(ctx->w, "poll_groups");
2430 
2431 	spdk_for_each_channel(ctx->tgt,
2432 			      _rpc_nvmf_get_stats,
2433 			      ctx,
2434 			      rpc_nvmf_get_stats_done);
2435 }
2436 
2437 SPDK_RPC_REGISTER("nvmf_get_stats", rpc_nvmf_get_stats, SPDK_RPC_RUNTIME)
2438 
2439 static void
2440 dump_nvmf_ctrlr(struct spdk_json_write_ctx *w, struct spdk_nvmf_ctrlr *ctrlr)
2441 {
2442 	char uuid_str[SPDK_UUID_STRING_LEN] = {};
2443 	uint32_t count;
2444 
2445 	spdk_json_write_object_begin(w);
2446 
2447 	spdk_json_write_named_uint32(w, "cntlid", ctrlr->cntlid);
2448 
2449 	spdk_json_write_named_string(w, "hostnqn", ctrlr->hostnqn);
2450 
2451 	spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ctrlr->hostid);
2452 	spdk_json_write_named_string(w, "hostid", uuid_str);
2453 
2454 	count = spdk_bit_array_count_set(ctrlr->qpair_mask);
2455 	spdk_json_write_named_uint32(w, "num_io_qpairs", count);
2456 
2457 	spdk_json_write_object_end(w);
2458 }
2459 
2460 static const char *
2461 nvmf_qpair_state_str(enum spdk_nvmf_qpair_state state)
2462 {
2463 	switch (state) {
2464 	case SPDK_NVMF_QPAIR_UNINITIALIZED:
2465 		return "uninitialized";
2466 	case SPDK_NVMF_QPAIR_ACTIVE:
2467 		return "active";
2468 	case SPDK_NVMF_QPAIR_DEACTIVATING:
2469 		return "deactivating";
2470 	case SPDK_NVMF_QPAIR_ERROR:
2471 		return "error";
2472 	default:
2473 		return NULL;
2474 	}
2475 }
2476 
2477 static void
2478 dump_nvmf_qpair(struct spdk_json_write_ctx *w, struct spdk_nvmf_qpair *qpair)
2479 {
2480 	struct spdk_nvme_transport_id listen_trid = {};
2481 
2482 	spdk_json_write_object_begin(w);
2483 
2484 	spdk_json_write_named_uint32(w, "cntlid", qpair->ctrlr->cntlid);
2485 	spdk_json_write_named_uint32(w, "qid", qpair->qid);
2486 	spdk_json_write_named_string(w, "state", nvmf_qpair_state_str(qpair->state));
2487 
2488 	if (spdk_nvmf_qpair_get_listen_trid(qpair, &listen_trid) == 0) {
2489 		spdk_json_write_named_object_begin(w, "listen_address");
2490 		nvmf_transport_listen_dump_trid(&listen_trid, w);
2491 		spdk_json_write_object_end(w);
2492 		if (qpair->transport->ops->listen_dump_opts) {
2493 			qpair->transport->ops->listen_dump_opts(qpair->transport, &listen_trid, w);
2494 		}
2495 	}
2496 
2497 	spdk_json_write_object_end(w);
2498 }
2499 
2500 static const char *
2501 nvme_ana_state_str(enum spdk_nvme_ana_state ana_state)
2502 {
2503 	switch (ana_state) {
2504 	case SPDK_NVME_ANA_OPTIMIZED_STATE:
2505 		return "optimized";
2506 	case SPDK_NVME_ANA_NON_OPTIMIZED_STATE:
2507 		return "non_optimized";
2508 	case SPDK_NVME_ANA_INACCESSIBLE_STATE:
2509 		return "inaccessible";
2510 	case SPDK_NVME_ANA_PERSISTENT_LOSS_STATE:
2511 		return "persistent_loss";
2512 	case SPDK_NVME_ANA_CHANGE_STATE:
2513 		return "change";
2514 	default:
2515 		return NULL;
2516 	}
2517 }
2518 
2519 static void
2520 dump_nvmf_subsystem_listener(struct spdk_json_write_ctx *w,
2521 			     struct spdk_nvmf_subsystem_listener *listener)
2522 {
2523 	const struct spdk_nvme_transport_id *trid = listener->trid;
2524 	uint32_t i;
2525 
2526 	spdk_json_write_object_begin(w);
2527 
2528 	spdk_json_write_named_object_begin(w, "address");
2529 	nvmf_transport_listen_dump_trid(trid, w);
2530 	spdk_json_write_object_end(w);
2531 
2532 	if (nvmf_subsystem_get_ana_reporting(listener->subsystem)) {
2533 		spdk_json_write_named_array_begin(w, "ana_states");
2534 		for (i = 0; i < listener->subsystem->max_nsid; i++) {
2535 			spdk_json_write_object_begin(w);
2536 			spdk_json_write_named_uint32(w, "ana_group", i + 1);
2537 			spdk_json_write_named_string(w, "ana_state",
2538 						     nvme_ana_state_str(listener->ana_state[i]));
2539 			spdk_json_write_object_end(w);
2540 		}
2541 		spdk_json_write_array_end(w);
2542 	}
2543 
2544 	spdk_json_write_object_end(w);
2545 }
2546 
2547 struct rpc_subsystem_query_ctx {
2548 	char *nqn;
2549 	char *tgt_name;
2550 	struct spdk_nvmf_subsystem *subsystem;
2551 	struct spdk_jsonrpc_request *request;
2552 	struct spdk_json_write_ctx *w;
2553 };
2554 
2555 static const struct spdk_json_object_decoder rpc_subsystem_query_decoders[] = {
2556 	{"nqn", offsetof(struct rpc_subsystem_query_ctx, nqn), spdk_json_decode_string},
2557 	{"tgt_name", offsetof(struct rpc_subsystem_query_ctx, tgt_name), spdk_json_decode_string, true},
2558 };
2559 
2560 static void
2561 free_rpc_subsystem_query_ctx(struct rpc_subsystem_query_ctx *ctx)
2562 {
2563 	free(ctx->nqn);
2564 	free(ctx->tgt_name);
2565 	free(ctx);
2566 }
2567 
2568 static void
2569 rpc_nvmf_get_controllers_paused(struct spdk_nvmf_subsystem *subsystem,
2570 				void *cb_arg, int status)
2571 {
2572 	struct rpc_subsystem_query_ctx *ctx = cb_arg;
2573 	struct spdk_json_write_ctx *w;
2574 	struct spdk_nvmf_ctrlr *ctrlr;
2575 
2576 	w = spdk_jsonrpc_begin_result(ctx->request);
2577 
2578 	spdk_json_write_array_begin(w);
2579 	TAILQ_FOREACH(ctrlr, &ctx->subsystem->ctrlrs, link) {
2580 		dump_nvmf_ctrlr(w, ctrlr);
2581 	}
2582 	spdk_json_write_array_end(w);
2583 
2584 	spdk_jsonrpc_end_result(ctx->request, w);
2585 
2586 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) {
2587 		SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn);
2588 		/* FIXME: RPC should fail if resuming the subsystem failed. */
2589 	}
2590 
2591 	free_rpc_subsystem_query_ctx(ctx);
2592 }
2593 
2594 static void
2595 rpc_nvmf_get_qpairs_done(struct spdk_io_channel_iter *i, int status)
2596 {
2597 	struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2598 
2599 	spdk_json_write_array_end(ctx->w);
2600 	spdk_jsonrpc_end_result(ctx->request, ctx->w);
2601 
2602 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) {
2603 		SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn);
2604 		/* FIXME: RPC should fail if resuming the subsystem failed. */
2605 	}
2606 
2607 	free_rpc_subsystem_query_ctx(ctx);
2608 }
2609 
2610 static void
2611 rpc_nvmf_get_qpairs(struct spdk_io_channel_iter *i)
2612 {
2613 	struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2614 	struct spdk_io_channel *ch;
2615 	struct spdk_nvmf_poll_group *group;
2616 	struct spdk_nvmf_qpair *qpair;
2617 
2618 	ch = spdk_io_channel_iter_get_channel(i);
2619 	group = spdk_io_channel_get_ctx(ch);
2620 
2621 	TAILQ_FOREACH(qpair, &group->qpairs, link) {
2622 		if (qpair->ctrlr->subsys == ctx->subsystem) {
2623 			dump_nvmf_qpair(ctx->w, qpair);
2624 		}
2625 	}
2626 
2627 	spdk_for_each_channel_continue(i, 0);
2628 }
2629 
2630 static void
2631 rpc_nvmf_get_qpairs_paused(struct spdk_nvmf_subsystem *subsystem,
2632 			   void *cb_arg, int status)
2633 {
2634 	struct rpc_subsystem_query_ctx *ctx = cb_arg;
2635 
2636 	ctx->w = spdk_jsonrpc_begin_result(ctx->request);
2637 
2638 	spdk_json_write_array_begin(ctx->w);
2639 
2640 	spdk_for_each_channel(ctx->subsystem->tgt,
2641 			      rpc_nvmf_get_qpairs,
2642 			      ctx,
2643 			      rpc_nvmf_get_qpairs_done);
2644 }
2645 
2646 static void
2647 rpc_nvmf_get_listeners_paused(struct spdk_nvmf_subsystem *subsystem,
2648 			      void *cb_arg, int status)
2649 {
2650 	struct rpc_subsystem_query_ctx *ctx = cb_arg;
2651 	struct spdk_json_write_ctx *w;
2652 	struct spdk_nvmf_subsystem_listener *listener;
2653 
2654 	w = spdk_jsonrpc_begin_result(ctx->request);
2655 
2656 	spdk_json_write_array_begin(w);
2657 
2658 	for (listener = spdk_nvmf_subsystem_get_first_listener(ctx->subsystem);
2659 	     listener != NULL;
2660 	     listener = spdk_nvmf_subsystem_get_next_listener(ctx->subsystem, listener)) {
2661 		dump_nvmf_subsystem_listener(w, listener);
2662 	}
2663 	spdk_json_write_array_end(w);
2664 
2665 	spdk_jsonrpc_end_result(ctx->request, w);
2666 
2667 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) {
2668 		SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn);
2669 		/* FIXME: RPC should fail if resuming the subsystem failed. */
2670 	}
2671 
2672 	free_rpc_subsystem_query_ctx(ctx);
2673 }
2674 
2675 static void
2676 _rpc_nvmf_subsystem_query(struct spdk_jsonrpc_request *request,
2677 			  const struct spdk_json_val *params,
2678 			  spdk_nvmf_subsystem_state_change_done cb_fn)
2679 {
2680 	struct rpc_subsystem_query_ctx *ctx;
2681 	struct spdk_nvmf_subsystem *subsystem;
2682 	struct spdk_nvmf_tgt *tgt;
2683 
2684 	ctx = calloc(1, sizeof(*ctx));
2685 	if (!ctx) {
2686 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2687 						 "Out of memory");
2688 		return;
2689 	}
2690 
2691 	ctx->request = request;
2692 
2693 	if (spdk_json_decode_object(params, rpc_subsystem_query_decoders,
2694 				    SPDK_COUNTOF(rpc_subsystem_query_decoders),
2695 				    ctx)) {
2696 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
2697 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
2698 						 "Invalid parameters");
2699 		free_rpc_subsystem_query_ctx(ctx);
2700 		return;
2701 	}
2702 
2703 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
2704 	if (!tgt) {
2705 		SPDK_ERRLOG("Unable to find a target object.\n");
2706 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2707 						 "Unable to find a target");
2708 		free_rpc_subsystem_query_ctx(ctx);
2709 		return;
2710 	}
2711 
2712 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
2713 	if (!subsystem) {
2714 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
2715 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
2716 						 "Invalid parameters");
2717 		free_rpc_subsystem_query_ctx(ctx);
2718 		return;
2719 	}
2720 
2721 	ctx->subsystem = subsystem;
2722 
2723 	if (spdk_nvmf_subsystem_pause(subsystem, 0, cb_fn, ctx)) {
2724 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2725 						 "Internal error");
2726 		free_rpc_subsystem_query_ctx(ctx);
2727 		return;
2728 	}
2729 }
2730 
2731 static void
2732 rpc_nvmf_subsystem_get_controllers(struct spdk_jsonrpc_request *request,
2733 				   const struct spdk_json_val *params)
2734 {
2735 	_rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_controllers_paused);
2736 }
2737 SPDK_RPC_REGISTER("nvmf_subsystem_get_controllers", rpc_nvmf_subsystem_get_controllers,
2738 		  SPDK_RPC_RUNTIME);
2739 
2740 static void
2741 rpc_nvmf_subsystem_get_qpairs(struct spdk_jsonrpc_request *request,
2742 			      const struct spdk_json_val *params)
2743 {
2744 	_rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_qpairs_paused);
2745 }
2746 SPDK_RPC_REGISTER("nvmf_subsystem_get_qpairs", rpc_nvmf_subsystem_get_qpairs, SPDK_RPC_RUNTIME);
2747 
2748 static void
2749 rpc_nvmf_subsystem_get_listeners(struct spdk_jsonrpc_request *request,
2750 				 const struct spdk_json_val *params)
2751 {
2752 	_rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_listeners_paused);
2753 }
2754 SPDK_RPC_REGISTER("nvmf_subsystem_get_listeners", rpc_nvmf_subsystem_get_listeners,
2755 		  SPDK_RPC_RUNTIME);
2756