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