xref: /spdk/module/bdev/nvme/bdev_nvme_rpc.c (revision 8d3f8fb818735d717730489685debac3c814d0ac)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2016 Intel Corporation. All rights reserved.
3  *   Copyright (c) 2019-2021 Mellanox Technologies LTD. All rights reserved.
4  *   Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5  *   Copyright (c) 2022 Dell Inc, or its subsidiaries. All rights reserved.
6  */
7 
8 #include "spdk/stdinc.h"
9 
10 #include "bdev_nvme.h"
11 
12 #include "spdk/config.h"
13 
14 #include "spdk/string.h"
15 #include "spdk/rpc.h"
16 #include "spdk/util.h"
17 #include "spdk/env.h"
18 #include "spdk/nvme.h"
19 #include "spdk/nvme_spec.h"
20 
21 #include "spdk/log.h"
22 #include "spdk/bdev_module.h"
23 
24 static bool g_tls_log = false;
25 
26 static int
27 rpc_decode_action_on_timeout(const struct spdk_json_val *val, void *out)
28 {
29 	enum spdk_bdev_timeout_action *action = out;
30 
31 	if (spdk_json_strequal(val, "none") == true) {
32 		*action = SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE;
33 	} else if (spdk_json_strequal(val, "abort") == true) {
34 		*action = SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT;
35 	} else if (spdk_json_strequal(val, "reset") == true) {
36 		*action = SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET;
37 	} else {
38 		SPDK_NOTICELOG("Invalid parameter value: action_on_timeout\n");
39 		return -EINVAL;
40 	}
41 
42 	return 0;
43 }
44 
45 static int
46 rpc_decode_digest(const struct spdk_json_val *val, void *out)
47 {
48 	uint32_t *flags = out;
49 	char *digest = NULL;
50 	int rc;
51 
52 	rc = spdk_json_decode_string(val, &digest);
53 	if (rc != 0) {
54 		return rc;
55 	}
56 
57 	rc = spdk_nvme_dhchap_get_digest_id(digest);
58 	if (rc >= 0) {
59 		*flags |= SPDK_BIT(rc);
60 		rc = 0;
61 	}
62 	free(digest);
63 
64 	return rc;
65 }
66 
67 static int
68 rpc_decode_digest_array(const struct spdk_json_val *val, void *out)
69 {
70 	uint32_t *flags = out;
71 	size_t count;
72 
73 	*flags = 0;
74 
75 	return spdk_json_decode_array(val, rpc_decode_digest, out, 32, &count, 0);
76 }
77 
78 static int
79 rpc_decode_dhgroup(const struct spdk_json_val *val, void *out)
80 {
81 	uint32_t *flags = out;
82 	char *dhgroup = NULL;
83 	int rc;
84 
85 	rc = spdk_json_decode_string(val, &dhgroup);
86 	if (rc != 0) {
87 		return rc;
88 	}
89 
90 	rc = spdk_nvme_dhchap_get_dhgroup_id(dhgroup);
91 	if (rc >= 0) {
92 		*flags |= SPDK_BIT(rc);
93 		rc = 0;
94 	}
95 	free(dhgroup);
96 
97 	return rc;
98 }
99 
100 static int
101 rpc_decode_dhgroup_array(const struct spdk_json_val *val, void *out)
102 {
103 	uint32_t *flags = out;
104 	size_t count;
105 
106 	*flags = 0;
107 
108 	return spdk_json_decode_array(val, rpc_decode_dhgroup, out, 32, &count, 0);
109 }
110 
111 static const struct spdk_json_object_decoder rpc_bdev_nvme_options_decoders[] = {
112 	{"action_on_timeout", offsetof(struct spdk_bdev_nvme_opts, action_on_timeout), rpc_decode_action_on_timeout, true},
113 	{"timeout_us", offsetof(struct spdk_bdev_nvme_opts, timeout_us), spdk_json_decode_uint64, true},
114 	{"timeout_admin_us", offsetof(struct spdk_bdev_nvme_opts, timeout_admin_us), spdk_json_decode_uint64, true},
115 	{"keep_alive_timeout_ms", offsetof(struct spdk_bdev_nvme_opts, keep_alive_timeout_ms), spdk_json_decode_uint32, true},
116 	{"arbitration_burst", offsetof(struct spdk_bdev_nvme_opts, arbitration_burst), spdk_json_decode_uint32, true},
117 	{"low_priority_weight", offsetof(struct spdk_bdev_nvme_opts, low_priority_weight), spdk_json_decode_uint32, true},
118 	{"medium_priority_weight", offsetof(struct spdk_bdev_nvme_opts, medium_priority_weight), spdk_json_decode_uint32, true},
119 	{"high_priority_weight", offsetof(struct spdk_bdev_nvme_opts, high_priority_weight), spdk_json_decode_uint32, true},
120 	{"nvme_adminq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_adminq_poll_period_us), spdk_json_decode_uint64, true},
121 	{"nvme_ioq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_ioq_poll_period_us), spdk_json_decode_uint64, true},
122 	{"io_queue_requests", offsetof(struct spdk_bdev_nvme_opts, io_queue_requests), spdk_json_decode_uint32, true},
123 	{"delay_cmd_submit", offsetof(struct spdk_bdev_nvme_opts, delay_cmd_submit), spdk_json_decode_bool, true},
124 	{"transport_retry_count", offsetof(struct spdk_bdev_nvme_opts, transport_retry_count), spdk_json_decode_uint32, true},
125 	{"bdev_retry_count", offsetof(struct spdk_bdev_nvme_opts, bdev_retry_count), spdk_json_decode_int32, true},
126 	{"transport_ack_timeout", offsetof(struct spdk_bdev_nvme_opts, transport_ack_timeout), spdk_json_decode_uint8, true},
127 	{"ctrlr_loss_timeout_sec", offsetof(struct spdk_bdev_nvme_opts, ctrlr_loss_timeout_sec), spdk_json_decode_int32, true},
128 	{"reconnect_delay_sec", offsetof(struct spdk_bdev_nvme_opts, reconnect_delay_sec), spdk_json_decode_uint32, true},
129 	{"fast_io_fail_timeout_sec", offsetof(struct spdk_bdev_nvme_opts, fast_io_fail_timeout_sec), spdk_json_decode_uint32, true},
130 	{"disable_auto_failback", offsetof(struct spdk_bdev_nvme_opts, disable_auto_failback), spdk_json_decode_bool, true},
131 	{"generate_uuids", offsetof(struct spdk_bdev_nvme_opts, generate_uuids), spdk_json_decode_bool, true},
132 	{"transport_tos", offsetof(struct spdk_bdev_nvme_opts, transport_tos), spdk_json_decode_uint8, true},
133 	{"nvme_error_stat", offsetof(struct spdk_bdev_nvme_opts, nvme_error_stat), spdk_json_decode_bool, true},
134 	{"rdma_srq_size", offsetof(struct spdk_bdev_nvme_opts, rdma_srq_size), spdk_json_decode_uint32, true},
135 	{"io_path_stat", offsetof(struct spdk_bdev_nvme_opts, io_path_stat), spdk_json_decode_bool, true},
136 	{"allow_accel_sequence", offsetof(struct spdk_bdev_nvme_opts, allow_accel_sequence), spdk_json_decode_bool, true},
137 	{"rdma_max_cq_size", offsetof(struct spdk_bdev_nvme_opts, rdma_max_cq_size), spdk_json_decode_uint32, true},
138 	{"rdma_cm_event_timeout_ms", offsetof(struct spdk_bdev_nvme_opts, rdma_cm_event_timeout_ms), spdk_json_decode_uint16, true},
139 	{"dhchap_digests", offsetof(struct spdk_bdev_nvme_opts, dhchap_digests), rpc_decode_digest_array, true},
140 	{"dhchap_dhgroups", offsetof(struct spdk_bdev_nvme_opts, dhchap_dhgroups), rpc_decode_dhgroup_array, true},
141 };
142 
143 static void
144 rpc_bdev_nvme_set_options(struct spdk_jsonrpc_request *request,
145 			  const struct spdk_json_val *params)
146 {
147 	struct spdk_bdev_nvme_opts opts;
148 	int rc;
149 
150 	bdev_nvme_get_opts(&opts);
151 	if (params && spdk_json_decode_object(params, rpc_bdev_nvme_options_decoders,
152 					      SPDK_COUNTOF(rpc_bdev_nvme_options_decoders),
153 					      &opts)) {
154 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
155 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
156 						 "spdk_json_decode_object failed");
157 		return;
158 	}
159 
160 	rc = bdev_nvme_set_opts(&opts);
161 	if (rc == -EPERM) {
162 		spdk_jsonrpc_send_error_response(request, -EPERM,
163 						 "RPC not permitted with nvme controllers already attached");
164 	} else if (rc) {
165 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
166 	} else {
167 		spdk_jsonrpc_send_bool_response(request, true);
168 	}
169 
170 	return;
171 }
172 SPDK_RPC_REGISTER("bdev_nvme_set_options", rpc_bdev_nvme_set_options,
173 		  SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME)
174 
175 struct rpc_bdev_nvme_hotplug {
176 	bool enabled;
177 	uint64_t period_us;
178 };
179 
180 static const struct spdk_json_object_decoder rpc_bdev_nvme_hotplug_decoders[] = {
181 	{"enable", offsetof(struct rpc_bdev_nvme_hotplug, enabled), spdk_json_decode_bool, false},
182 	{"period_us", offsetof(struct rpc_bdev_nvme_hotplug, period_us), spdk_json_decode_uint64, true},
183 };
184 
185 static void
186 rpc_bdev_nvme_set_hotplug_done(void *ctx)
187 {
188 	struct spdk_jsonrpc_request *request = ctx;
189 
190 	spdk_jsonrpc_send_bool_response(request, true);
191 }
192 
193 static void
194 rpc_bdev_nvme_set_hotplug(struct spdk_jsonrpc_request *request,
195 			  const struct spdk_json_val *params)
196 {
197 	struct rpc_bdev_nvme_hotplug req = {false, 0};
198 	int rc;
199 
200 	if (spdk_json_decode_object(params, rpc_bdev_nvme_hotplug_decoders,
201 				    SPDK_COUNTOF(rpc_bdev_nvme_hotplug_decoders), &req)) {
202 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
203 		rc = -EINVAL;
204 		goto invalid;
205 	}
206 
207 	rc = bdev_nvme_set_hotplug(req.enabled, req.period_us, rpc_bdev_nvme_set_hotplug_done,
208 				   request);
209 	if (rc) {
210 		goto invalid;
211 	}
212 
213 	return;
214 invalid:
215 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc));
216 }
217 SPDK_RPC_REGISTER("bdev_nvme_set_hotplug", rpc_bdev_nvme_set_hotplug, SPDK_RPC_RUNTIME)
218 
219 enum bdev_nvme_multipath_mode {
220 	BDEV_NVME_MP_MODE_FAILOVER,
221 	BDEV_NVME_MP_MODE_MULTIPATH,
222 	BDEV_NVME_MP_MODE_DISABLE,
223 };
224 
225 struct rpc_bdev_nvme_attach_controller {
226 	char *name;
227 	char *trtype;
228 	char *adrfam;
229 	char *traddr;
230 	char *trsvcid;
231 	char *priority;
232 	char *subnqn;
233 	char *hostnqn;
234 	char *hostaddr;
235 	char *hostsvcid;
236 	char *psk;
237 	char *dhchap_key;
238 	char *dhchap_ctrlr_key;
239 	enum bdev_nvme_multipath_mode multipath;
240 	struct spdk_bdev_nvme_ctrlr_opts bdev_opts;
241 	struct spdk_nvme_ctrlr_opts drv_opts;
242 	uint32_t max_bdevs;
243 };
244 
245 static void
246 free_rpc_bdev_nvme_attach_controller(struct rpc_bdev_nvme_attach_controller *req)
247 {
248 	free(req->name);
249 	free(req->trtype);
250 	free(req->adrfam);
251 	free(req->traddr);
252 	free(req->trsvcid);
253 	free(req->priority);
254 	free(req->subnqn);
255 	free(req->hostnqn);
256 	free(req->hostaddr);
257 	free(req->hostsvcid);
258 	free(req->psk);
259 	free(req->dhchap_key);
260 	free(req->dhchap_ctrlr_key);
261 }
262 
263 static int
264 bdev_nvme_decode_reftag(const struct spdk_json_val *val, void *out)
265 {
266 	uint32_t *flag = out;
267 	bool reftag;
268 	int rc;
269 
270 	rc = spdk_json_decode_bool(val, &reftag);
271 	if (rc == 0 && reftag == true) {
272 		*flag |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG;
273 	}
274 
275 	return rc;
276 }
277 
278 static int
279 bdev_nvme_decode_guard(const struct spdk_json_val *val, void *out)
280 {
281 	uint32_t *flag = out;
282 	bool guard;
283 	int rc;
284 
285 	rc = spdk_json_decode_bool(val, &guard);
286 	if (rc == 0 && guard == true) {
287 		*flag |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD;
288 	}
289 
290 	return rc;
291 }
292 
293 static int
294 bdev_nvme_decode_multipath(const struct spdk_json_val *val, void *out)
295 {
296 	enum bdev_nvme_multipath_mode *multipath = out;
297 
298 	if (spdk_json_strequal(val, "failover") == true) {
299 		*multipath = BDEV_NVME_MP_MODE_FAILOVER;
300 	} else if (spdk_json_strequal(val, "multipath") == true) {
301 		*multipath = BDEV_NVME_MP_MODE_MULTIPATH;
302 	} else if (spdk_json_strequal(val, "disable") == true) {
303 		*multipath = BDEV_NVME_MP_MODE_DISABLE;
304 	} else {
305 		SPDK_NOTICELOG("Invalid parameter value: multipath\n");
306 		return -EINVAL;
307 	}
308 
309 	return 0;
310 }
311 
312 
313 static const struct spdk_json_object_decoder rpc_bdev_nvme_attach_controller_decoders[] = {
314 	{"name", offsetof(struct rpc_bdev_nvme_attach_controller, name), spdk_json_decode_string},
315 	{"trtype", offsetof(struct rpc_bdev_nvme_attach_controller, trtype), spdk_json_decode_string},
316 	{"traddr", offsetof(struct rpc_bdev_nvme_attach_controller, traddr), spdk_json_decode_string},
317 
318 	{"adrfam", offsetof(struct rpc_bdev_nvme_attach_controller, adrfam), spdk_json_decode_string, true},
319 	{"trsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, trsvcid), spdk_json_decode_string, true},
320 	{"priority", offsetof(struct rpc_bdev_nvme_attach_controller, priority), spdk_json_decode_string, true},
321 	{"subnqn", offsetof(struct rpc_bdev_nvme_attach_controller, subnqn), spdk_json_decode_string, true},
322 	{"hostnqn", offsetof(struct rpc_bdev_nvme_attach_controller, hostnqn), spdk_json_decode_string, true},
323 	{"hostaddr", offsetof(struct rpc_bdev_nvme_attach_controller, hostaddr), spdk_json_decode_string, true},
324 	{"hostsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, hostsvcid), spdk_json_decode_string, true},
325 
326 	{"prchk_reftag", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.prchk_flags), bdev_nvme_decode_reftag, true},
327 	{"prchk_guard", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.prchk_flags), bdev_nvme_decode_guard, true},
328 	{"hdgst", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.header_digest), spdk_json_decode_bool, true},
329 	{"ddgst", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.data_digest), spdk_json_decode_bool, true},
330 	{"fabrics_connect_timeout_us", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.fabrics_connect_timeout_us), spdk_json_decode_uint64, true},
331 	{"multipath", offsetof(struct rpc_bdev_nvme_attach_controller, multipath), bdev_nvme_decode_multipath, true},
332 	{"num_io_queues", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.num_io_queues), spdk_json_decode_uint32, true},
333 	{"ctrlr_loss_timeout_sec", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.ctrlr_loss_timeout_sec), spdk_json_decode_int32, true},
334 	{"reconnect_delay_sec", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.reconnect_delay_sec), spdk_json_decode_uint32, true},
335 	{"fast_io_fail_timeout_sec", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.fast_io_fail_timeout_sec), spdk_json_decode_uint32, true},
336 	{"psk", offsetof(struct rpc_bdev_nvme_attach_controller, psk), spdk_json_decode_string, true},
337 	{"max_bdevs", offsetof(struct rpc_bdev_nvme_attach_controller, max_bdevs), spdk_json_decode_uint32, true},
338 	{"dhchap_key", offsetof(struct rpc_bdev_nvme_attach_controller, dhchap_key), spdk_json_decode_string, true},
339 	{"dhchap_ctrlr_key", offsetof(struct rpc_bdev_nvme_attach_controller, dhchap_ctrlr_key), spdk_json_decode_string, true},
340 	{"allow_unrecognized_csi", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.allow_unrecognized_csi), spdk_json_decode_bool, true},
341 };
342 
343 #define DEFAULT_MAX_BDEVS_PER_RPC 128
344 
345 struct rpc_bdev_nvme_attach_controller_ctx {
346 	struct rpc_bdev_nvme_attach_controller req;
347 	size_t bdev_count;
348 	const char **names;
349 	struct spdk_jsonrpc_request *request;
350 };
351 
352 static void
353 free_rpc_bdev_nvme_attach_controller_ctx(struct rpc_bdev_nvme_attach_controller_ctx *ctx)
354 {
355 	free_rpc_bdev_nvme_attach_controller(&ctx->req);
356 	free(ctx->names);
357 	free(ctx);
358 }
359 
360 static void
361 rpc_bdev_nvme_attach_controller_examined(void *cb_ctx)
362 {
363 	struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx;
364 	struct spdk_jsonrpc_request *request = ctx->request;
365 	struct spdk_json_write_ctx *w;
366 	size_t i;
367 
368 	w = spdk_jsonrpc_begin_result(request);
369 	spdk_json_write_array_begin(w);
370 	for (i = 0; i < ctx->bdev_count; i++) {
371 		spdk_json_write_string(w, ctx->names[i]);
372 	}
373 	spdk_json_write_array_end(w);
374 	spdk_jsonrpc_end_result(request, w);
375 
376 	free_rpc_bdev_nvme_attach_controller_ctx(ctx);
377 }
378 
379 static void
380 rpc_bdev_nvme_attach_controller_done(void *cb_ctx, size_t bdev_count, int rc)
381 {
382 	struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx;
383 	struct spdk_jsonrpc_request *request = ctx->request;
384 
385 	if (rc < 0) {
386 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
387 		free_rpc_bdev_nvme_attach_controller_ctx(ctx);
388 		return;
389 	}
390 
391 	ctx->bdev_count = bdev_count;
392 	spdk_bdev_wait_for_examine(rpc_bdev_nvme_attach_controller_examined, ctx);
393 }
394 
395 static void
396 rpc_bdev_nvme_attach_controller(struct spdk_jsonrpc_request *request,
397 				const struct spdk_json_val *params)
398 {
399 	struct rpc_bdev_nvme_attach_controller_ctx *ctx;
400 	struct spdk_nvme_transport_id trid = {};
401 	const struct spdk_nvme_ctrlr_opts *drv_opts;
402 	const struct spdk_nvme_transport_id *ctrlr_trid;
403 	struct nvme_ctrlr *ctrlr = NULL;
404 	size_t len, maxlen;
405 	bool multipath = false;
406 	int rc;
407 
408 	ctx = calloc(1, sizeof(*ctx));
409 	if (!ctx) {
410 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
411 		return;
412 	}
413 
414 	spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->req.drv_opts, sizeof(ctx->req.drv_opts));
415 	spdk_bdev_nvme_get_default_ctrlr_opts(&ctx->req.bdev_opts);
416 	/* For now, initialize the multipath parameter to add a failover path. This maintains backward
417 	 * compatibility with past behavior. In the future, this behavior will change to "disable". */
418 	ctx->req.multipath = BDEV_NVME_MP_MODE_FAILOVER;
419 	ctx->req.max_bdevs = DEFAULT_MAX_BDEVS_PER_RPC;
420 
421 	if (spdk_json_decode_object(params, rpc_bdev_nvme_attach_controller_decoders,
422 				    SPDK_COUNTOF(rpc_bdev_nvme_attach_controller_decoders),
423 				    &ctx->req)) {
424 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
425 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
426 						 "spdk_json_decode_object failed");
427 		goto cleanup;
428 	}
429 
430 	if (ctx->req.max_bdevs == 0) {
431 		spdk_jsonrpc_send_error_response(request, -EINVAL, "max_bdevs cannot be zero");
432 		goto cleanup;
433 	}
434 
435 	ctx->names = calloc(ctx->req.max_bdevs, sizeof(char *));
436 	if (ctx->names == NULL) {
437 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
438 		goto cleanup;
439 	}
440 
441 	/* Parse trstring */
442 	rc = spdk_nvme_transport_id_populate_trstring(&trid, ctx->req.trtype);
443 	if (rc < 0) {
444 		SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype);
445 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s",
446 						     ctx->req.trtype);
447 		goto cleanup;
448 	}
449 
450 	/* Parse trtype */
451 	rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype);
452 	assert(rc == 0);
453 
454 	/* Parse traddr */
455 	maxlen = sizeof(trid.traddr);
456 	len = strnlen(ctx->req.traddr, maxlen);
457 	if (len == maxlen) {
458 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s",
459 						     ctx->req.traddr);
460 		goto cleanup;
461 	}
462 	memcpy(trid.traddr, ctx->req.traddr, len + 1);
463 
464 	/* Parse adrfam */
465 	if (ctx->req.adrfam) {
466 		rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam);
467 		if (rc < 0) {
468 			SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam);
469 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s",
470 							     ctx->req.adrfam);
471 			goto cleanup;
472 		}
473 	}
474 
475 	/* Parse trsvcid */
476 	if (ctx->req.trsvcid) {
477 		maxlen = sizeof(trid.trsvcid);
478 		len = strnlen(ctx->req.trsvcid, maxlen);
479 		if (len == maxlen) {
480 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s",
481 							     ctx->req.trsvcid);
482 			goto cleanup;
483 		}
484 		memcpy(trid.trsvcid, ctx->req.trsvcid, len + 1);
485 	}
486 
487 	/* Parse priority for the NVMe-oF transport connection */
488 	if (ctx->req.priority) {
489 		trid.priority = spdk_strtol(ctx->req.priority, 10);
490 	}
491 
492 	/* Parse subnqn */
493 	if (ctx->req.subnqn) {
494 		maxlen = sizeof(trid.subnqn);
495 		len = strnlen(ctx->req.subnqn, maxlen);
496 		if (len == maxlen) {
497 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s",
498 							     ctx->req.subnqn);
499 			goto cleanup;
500 		}
501 		memcpy(trid.subnqn, ctx->req.subnqn, len + 1);
502 	}
503 
504 	if (ctx->req.hostnqn) {
505 		maxlen = sizeof(ctx->req.drv_opts.hostnqn);
506 		len = strnlen(ctx->req.hostnqn, maxlen);
507 		if (len == maxlen) {
508 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostnqn too long: %s",
509 							     ctx->req.hostnqn);
510 			goto cleanup;
511 		}
512 		memcpy(ctx->req.drv_opts.hostnqn, ctx->req.hostnqn, len + 1);
513 	}
514 
515 	if (ctx->req.psk) {
516 		if (!g_tls_log) {
517 			SPDK_NOTICELOG("TLS support is considered experimental\n");
518 			g_tls_log = true;
519 		}
520 	}
521 
522 	if (ctx->req.hostaddr) {
523 		maxlen = sizeof(ctx->req.drv_opts.src_addr);
524 		len = strnlen(ctx->req.hostaddr, maxlen);
525 		if (len == maxlen) {
526 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostaddr too long: %s",
527 							     ctx->req.hostaddr);
528 			goto cleanup;
529 		}
530 		snprintf(ctx->req.drv_opts.src_addr, maxlen, "%s", ctx->req.hostaddr);
531 	}
532 
533 	if (ctx->req.hostsvcid) {
534 		maxlen = sizeof(ctx->req.drv_opts.src_svcid);
535 		len = strnlen(ctx->req.hostsvcid, maxlen);
536 		if (len == maxlen) {
537 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostsvcid too long: %s",
538 							     ctx->req.hostsvcid);
539 			goto cleanup;
540 		}
541 		snprintf(ctx->req.drv_opts.src_svcid, maxlen, "%s", ctx->req.hostsvcid);
542 	}
543 
544 	ctrlr = nvme_ctrlr_get_by_name(ctx->req.name);
545 
546 	if (ctrlr) {
547 		/* This controller already exists. Check what the user wants to do. */
548 		if (ctx->req.multipath == BDEV_NVME_MP_MODE_DISABLE) {
549 			/* The user does not want to do any form of multipathing. */
550 			spdk_jsonrpc_send_error_response_fmt(request, -EALREADY,
551 							     "A controller named %s already exists and multipath is disabled",
552 							     ctx->req.name);
553 			goto cleanup;
554 		}
555 
556 		assert(ctx->req.multipath == BDEV_NVME_MP_MODE_FAILOVER ||
557 		       ctx->req.multipath == BDEV_NVME_MP_MODE_MULTIPATH);
558 
559 		/* The user wants to add this as a failover path or add this to create multipath. */
560 		drv_opts = spdk_nvme_ctrlr_get_opts(ctrlr->ctrlr);
561 		ctrlr_trid = spdk_nvme_ctrlr_get_transport_id(ctrlr->ctrlr);
562 
563 		if (strncmp(trid.traddr, ctrlr_trid->traddr, sizeof(trid.traddr)) == 0 &&
564 		    strncmp(trid.trsvcid, ctrlr_trid->trsvcid, sizeof(trid.trsvcid)) == 0 &&
565 		    strncmp(ctx->req.drv_opts.src_addr, drv_opts->src_addr, sizeof(drv_opts->src_addr)) == 0 &&
566 		    strncmp(ctx->req.drv_opts.src_svcid, drv_opts->src_svcid, sizeof(drv_opts->src_svcid)) == 0) {
567 			/* Exactly same network path can't be added a second time */
568 			spdk_jsonrpc_send_error_response_fmt(request, -EALREADY,
569 							     "A controller named %s already exists with the specified network path",
570 							     ctx->req.name);
571 			goto cleanup;
572 		}
573 
574 		if (strncmp(trid.subnqn,
575 			    ctrlr_trid->subnqn,
576 			    SPDK_NVMF_NQN_MAX_LEN) != 0) {
577 			/* Different SUBNQN is not allowed when specifying the same controller name. */
578 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL,
579 							     "A controller named %s already exists, but uses a different subnqn (%s)",
580 							     ctx->req.name, ctrlr_trid->subnqn);
581 			goto cleanup;
582 		}
583 
584 		if (strncmp(ctx->req.drv_opts.hostnqn, drv_opts->hostnqn, SPDK_NVMF_NQN_MAX_LEN) != 0) {
585 			/* Different HOSTNQN is not allowed when specifying the same controller name. */
586 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL,
587 							     "A controller named %s already exists, but uses a different hostnqn (%s)",
588 							     ctx->req.name, drv_opts->hostnqn);
589 			goto cleanup;
590 		}
591 
592 		if (ctx->req.bdev_opts.prchk_flags) {
593 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL,
594 							     "A controller named %s already exists. To add a path, do not specify PI options.",
595 							     ctx->req.name);
596 			goto cleanup;
597 		}
598 
599 		ctx->req.bdev_opts.prchk_flags = ctrlr->opts.prchk_flags;
600 	}
601 
602 	if (ctx->req.multipath == BDEV_NVME_MP_MODE_MULTIPATH) {
603 		multipath = true;
604 	}
605 
606 	if (ctx->req.drv_opts.num_io_queues == 0 || ctx->req.drv_opts.num_io_queues > UINT16_MAX + 1) {
607 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL,
608 						     "num_io_queues out of bounds, min: %u max: %u",
609 						     1, UINT16_MAX + 1);
610 		goto cleanup;
611 	}
612 
613 	ctx->request = request;
614 	/* Should already be zero due to the calloc(), but set explicitly for clarity. */
615 	ctx->req.bdev_opts.from_discovery_service = false;
616 	ctx->req.bdev_opts.psk = ctx->req.psk;
617 	ctx->req.bdev_opts.dhchap_key = ctx->req.dhchap_key;
618 	ctx->req.bdev_opts.dhchap_ctrlr_key = ctx->req.dhchap_ctrlr_key;
619 	ctx->req.bdev_opts.multipath = multipath;
620 	rc = spdk_bdev_nvme_create(&trid, ctx->req.name, ctx->names, ctx->req.max_bdevs,
621 				   rpc_bdev_nvme_attach_controller_done, ctx, &ctx->req.drv_opts,
622 				   &ctx->req.bdev_opts, multipath);
623 	if (rc) {
624 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
625 		goto cleanup;
626 	}
627 
628 	return;
629 
630 cleanup:
631 	free_rpc_bdev_nvme_attach_controller_ctx(ctx);
632 }
633 SPDK_RPC_REGISTER("bdev_nvme_attach_controller", rpc_bdev_nvme_attach_controller,
634 		  SPDK_RPC_RUNTIME)
635 
636 static void
637 rpc_dump_nvme_bdev_controller_info(struct nvme_bdev_ctrlr *nbdev_ctrlr, void *ctx)
638 {
639 	struct spdk_json_write_ctx	*w = ctx;
640 	struct nvme_ctrlr		*nvme_ctrlr;
641 
642 	spdk_json_write_object_begin(w);
643 	spdk_json_write_named_string(w, "name", nbdev_ctrlr->name);
644 
645 	spdk_json_write_named_array_begin(w, "ctrlrs");
646 	TAILQ_FOREACH(nvme_ctrlr, &nbdev_ctrlr->ctrlrs, tailq) {
647 		nvme_ctrlr_info_json(w, nvme_ctrlr);
648 	}
649 	spdk_json_write_array_end(w);
650 	spdk_json_write_object_end(w);
651 }
652 
653 struct rpc_bdev_nvme_get_controllers {
654 	char *name;
655 };
656 
657 static void
658 free_rpc_bdev_nvme_get_controllers(struct rpc_bdev_nvme_get_controllers *r)
659 {
660 	free(r->name);
661 }
662 
663 static const struct spdk_json_object_decoder rpc_bdev_nvme_get_controllers_decoders[] = {
664 	{"name", offsetof(struct rpc_bdev_nvme_get_controllers, name), spdk_json_decode_string, true},
665 };
666 
667 static void
668 rpc_bdev_nvme_get_controllers(struct spdk_jsonrpc_request *request,
669 			      const struct spdk_json_val *params)
670 {
671 	struct rpc_bdev_nvme_get_controllers req = {};
672 	struct spdk_json_write_ctx *w;
673 	struct nvme_bdev_ctrlr *nbdev_ctrlr = NULL;
674 
675 	if (params && spdk_json_decode_object(params, rpc_bdev_nvme_get_controllers_decoders,
676 					      SPDK_COUNTOF(rpc_bdev_nvme_get_controllers_decoders),
677 					      &req)) {
678 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
679 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
680 						 "spdk_json_decode_object failed");
681 		goto cleanup;
682 	}
683 
684 	if (req.name) {
685 		nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name(req.name);
686 		if (nbdev_ctrlr == NULL) {
687 			SPDK_ERRLOG("ctrlr '%s' does not exist\n", req.name);
688 			spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Controller %s does not exist", req.name);
689 			goto cleanup;
690 		}
691 	}
692 
693 	w = spdk_jsonrpc_begin_result(request);
694 	spdk_json_write_array_begin(w);
695 
696 	if (nbdev_ctrlr != NULL) {
697 		rpc_dump_nvme_bdev_controller_info(nbdev_ctrlr, w);
698 	} else {
699 		nvme_bdev_ctrlr_for_each(rpc_dump_nvme_bdev_controller_info, w);
700 	}
701 
702 	spdk_json_write_array_end(w);
703 
704 	spdk_jsonrpc_end_result(request, w);
705 
706 cleanup:
707 	free_rpc_bdev_nvme_get_controllers(&req);
708 }
709 SPDK_RPC_REGISTER("bdev_nvme_get_controllers", rpc_bdev_nvme_get_controllers, SPDK_RPC_RUNTIME)
710 
711 struct rpc_bdev_nvme_detach_controller {
712 	char *name;
713 	char *trtype;
714 	char *adrfam;
715 	char *traddr;
716 	char *trsvcid;
717 	char *subnqn;
718 	char *hostaddr;
719 	char *hostsvcid;
720 };
721 
722 static void
723 free_rpc_bdev_nvme_detach_controller(struct rpc_bdev_nvme_detach_controller *req)
724 {
725 	free(req->name);
726 	free(req->trtype);
727 	free(req->adrfam);
728 	free(req->traddr);
729 	free(req->trsvcid);
730 	free(req->subnqn);
731 	free(req->hostaddr);
732 	free(req->hostsvcid);
733 }
734 
735 static const struct spdk_json_object_decoder rpc_bdev_nvme_detach_controller_decoders[] = {
736 	{"name", offsetof(struct rpc_bdev_nvme_detach_controller, name), spdk_json_decode_string},
737 	{"trtype", offsetof(struct rpc_bdev_nvme_detach_controller, trtype), spdk_json_decode_string, true},
738 	{"traddr", offsetof(struct rpc_bdev_nvme_detach_controller, traddr), spdk_json_decode_string, true},
739 	{"adrfam", offsetof(struct rpc_bdev_nvme_detach_controller, adrfam), spdk_json_decode_string, true},
740 	{"trsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, trsvcid), spdk_json_decode_string, true},
741 	{"subnqn", offsetof(struct rpc_bdev_nvme_detach_controller, subnqn), spdk_json_decode_string, true},
742 	{"hostaddr", offsetof(struct rpc_bdev_nvme_detach_controller, hostaddr), spdk_json_decode_string, true},
743 	{"hostsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, hostsvcid), spdk_json_decode_string, true},
744 };
745 
746 static void
747 rpc_bdev_nvme_detach_controller_done(void *arg, int rc)
748 {
749 	struct spdk_jsonrpc_request *request = arg;
750 
751 	if (rc == 0) {
752 		spdk_jsonrpc_send_bool_response(request, true);
753 	} else {
754 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
755 	}
756 }
757 
758 static void
759 rpc_bdev_nvme_detach_controller(struct spdk_jsonrpc_request *request,
760 				const struct spdk_json_val *params)
761 {
762 	struct rpc_bdev_nvme_detach_controller req = {NULL};
763 	struct nvme_path_id path = {};
764 	size_t len, maxlen;
765 	int rc = 0;
766 
767 	if (spdk_json_decode_object(params, rpc_bdev_nvme_detach_controller_decoders,
768 				    SPDK_COUNTOF(rpc_bdev_nvme_detach_controller_decoders),
769 				    &req)) {
770 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
771 						 "spdk_json_decode_object failed");
772 		goto cleanup;
773 	}
774 
775 	if (req.trtype != NULL) {
776 		rc = spdk_nvme_transport_id_populate_trstring(&path.trid, req.trtype);
777 		if (rc < 0) {
778 			SPDK_ERRLOG("Failed to parse trtype: %s\n", req.trtype);
779 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s",
780 							     req.trtype);
781 			goto cleanup;
782 		}
783 
784 		rc = spdk_nvme_transport_id_parse_trtype(&path.trid.trtype, req.trtype);
785 		if (rc < 0) {
786 			SPDK_ERRLOG("Failed to parse trtype: %s\n", req.trtype);
787 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s",
788 							     req.trtype);
789 			goto cleanup;
790 		}
791 	}
792 
793 	if (req.traddr != NULL) {
794 		maxlen = sizeof(path.trid.traddr);
795 		len = strnlen(req.traddr, maxlen);
796 		if (len == maxlen) {
797 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s",
798 							     req.traddr);
799 			goto cleanup;
800 		}
801 		memcpy(path.trid.traddr, req.traddr, len + 1);
802 	}
803 
804 	if (req.adrfam != NULL) {
805 		rc = spdk_nvme_transport_id_parse_adrfam(&path.trid.adrfam, req.adrfam);
806 		if (rc < 0) {
807 			SPDK_ERRLOG("Failed to parse adrfam: %s\n", req.adrfam);
808 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s",
809 							     req.adrfam);
810 			goto cleanup;
811 		}
812 	}
813 
814 	if (req.trsvcid != NULL) {
815 		maxlen = sizeof(path.trid.trsvcid);
816 		len = strnlen(req.trsvcid, maxlen);
817 		if (len == maxlen) {
818 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s",
819 							     req.trsvcid);
820 			goto cleanup;
821 		}
822 		memcpy(path.trid.trsvcid, req.trsvcid, len + 1);
823 	}
824 
825 	/* Parse subnqn */
826 	if (req.subnqn != NULL) {
827 		maxlen = sizeof(path.trid.subnqn);
828 		len = strnlen(req.subnqn, maxlen);
829 		if (len == maxlen) {
830 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s",
831 							     req.subnqn);
832 			goto cleanup;
833 		}
834 		memcpy(path.trid.subnqn, req.subnqn, len + 1);
835 	}
836 
837 	if (req.hostaddr) {
838 		maxlen = sizeof(path.hostid.hostaddr);
839 		len = strnlen(req.hostaddr, maxlen);
840 		if (len == maxlen) {
841 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostaddr too long: %s",
842 							     req.hostaddr);
843 			goto cleanup;
844 		}
845 		snprintf(path.hostid.hostaddr, maxlen, "%s", req.hostaddr);
846 	}
847 
848 	if (req.hostsvcid) {
849 		maxlen = sizeof(path.hostid.hostsvcid);
850 		len = strnlen(req.hostsvcid, maxlen);
851 		if (len == maxlen) {
852 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostsvcid too long: %s",
853 							     req.hostsvcid);
854 			goto cleanup;
855 		}
856 		snprintf(path.hostid.hostsvcid, maxlen, "%s", req.hostsvcid);
857 	}
858 
859 	rc = bdev_nvme_delete(req.name, &path, rpc_bdev_nvme_detach_controller_done, request);
860 
861 	if (rc != 0) {
862 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
863 	}
864 
865 cleanup:
866 	free_rpc_bdev_nvme_detach_controller(&req);
867 }
868 SPDK_RPC_REGISTER("bdev_nvme_detach_controller", rpc_bdev_nvme_detach_controller,
869 		  SPDK_RPC_RUNTIME)
870 
871 struct rpc_apply_firmware {
872 	char *filename;
873 	char *bdev_name;
874 };
875 
876 static void
877 free_rpc_apply_firmware(struct rpc_apply_firmware *req)
878 {
879 	free(req->filename);
880 	free(req->bdev_name);
881 }
882 
883 static const struct spdk_json_object_decoder rpc_apply_firmware_decoders[] = {
884 	{"filename", offsetof(struct rpc_apply_firmware, filename), spdk_json_decode_string},
885 	{"bdev_name", offsetof(struct rpc_apply_firmware, bdev_name), spdk_json_decode_string},
886 };
887 
888 struct firmware_update_info {
889 	void				*fw_image;
890 	void				*p;
891 	unsigned int			size;
892 	unsigned int			size_remaining;
893 	unsigned int			offset;
894 	unsigned int			transfer;
895 	bool				success;
896 
897 	struct spdk_bdev_desc		*desc;
898 	struct spdk_io_channel		*ch;
899 	struct spdk_thread		*orig_thread;
900 	struct spdk_jsonrpc_request	*request;
901 	struct spdk_nvme_ctrlr		*ctrlr;
902 	struct rpc_apply_firmware	req;
903 };
904 
905 static void
906 apply_firmware_cleanup(struct firmware_update_info *firm_ctx)
907 {
908 	assert(firm_ctx != NULL);
909 	assert(firm_ctx->orig_thread == spdk_get_thread());
910 
911 	if (firm_ctx->fw_image) {
912 		spdk_free(firm_ctx->fw_image);
913 	}
914 
915 	free_rpc_apply_firmware(&firm_ctx->req);
916 
917 	if (firm_ctx->ch) {
918 		spdk_put_io_channel(firm_ctx->ch);
919 	}
920 
921 	if (firm_ctx->desc) {
922 		spdk_bdev_close(firm_ctx->desc);
923 	}
924 
925 	free(firm_ctx);
926 }
927 
928 static void
929 _apply_firmware_complete_reset(void *ctx)
930 {
931 	struct spdk_json_write_ctx		*w;
932 	struct firmware_update_info *firm_ctx = ctx;
933 
934 	assert(firm_ctx->orig_thread == spdk_get_thread());
935 
936 	if (!firm_ctx->success) {
937 		spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
938 						 "firmware commit failed.");
939 		apply_firmware_cleanup(firm_ctx);
940 		return;
941 	}
942 
943 	if (spdk_nvme_ctrlr_reset(firm_ctx->ctrlr) != 0) {
944 		spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
945 						 "Controller reset failed.");
946 		apply_firmware_cleanup(firm_ctx);
947 		return;
948 	}
949 
950 	w = spdk_jsonrpc_begin_result(firm_ctx->request);
951 	spdk_json_write_string(w, "firmware commit succeeded. Controller reset in progress.");
952 	spdk_jsonrpc_end_result(firm_ctx->request, w);
953 	apply_firmware_cleanup(firm_ctx);
954 }
955 
956 static void
957 apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
958 {
959 	struct firmware_update_info *firm_ctx = cb_arg;
960 
961 	spdk_bdev_free_io(bdev_io);
962 
963 	firm_ctx->success = success;
964 
965 	spdk_thread_exec_msg(firm_ctx->orig_thread, _apply_firmware_complete_reset, firm_ctx);
966 }
967 
968 static void apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg);
969 
970 static void
971 _apply_firmware_complete(void *ctx)
972 {
973 	struct spdk_nvme_cmd			cmd = {};
974 	struct spdk_nvme_fw_commit		fw_commit;
975 	int					slot = 0;
976 	int					rc;
977 	struct firmware_update_info *firm_ctx = ctx;
978 	enum spdk_nvme_fw_commit_action commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG;
979 
980 	assert(firm_ctx->orig_thread == spdk_get_thread());
981 
982 	if (!firm_ctx->success) {
983 		spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
984 						 "firmware download failed .");
985 		apply_firmware_cleanup(firm_ctx);
986 		return;
987 	}
988 
989 	firm_ctx->p += firm_ctx->transfer;
990 	firm_ctx->offset += firm_ctx->transfer;
991 	firm_ctx->size_remaining -= firm_ctx->transfer;
992 
993 	switch (firm_ctx->size_remaining) {
994 	case 0:
995 		/* firmware download completed. Commit firmware */
996 		memset(&fw_commit, 0, sizeof(struct spdk_nvme_fw_commit));
997 		fw_commit.fs = slot;
998 		fw_commit.ca = commit_action;
999 
1000 		cmd.opc = SPDK_NVME_OPC_FIRMWARE_COMMIT;
1001 		memcpy(&cmd.cdw10, &fw_commit, sizeof(uint32_t));
1002 		rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, NULL, 0,
1003 						   apply_firmware_complete_reset, firm_ctx);
1004 		if (rc) {
1005 			spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1006 							 "firmware commit failed.");
1007 			apply_firmware_cleanup(firm_ctx);
1008 			return;
1009 		}
1010 		break;
1011 	default:
1012 		firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096);
1013 		cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD;
1014 
1015 		cmd.cdw10 = spdk_nvme_bytes_to_numd(firm_ctx->transfer);
1016 		cmd.cdw11 = firm_ctx->offset >> 2;
1017 		rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, firm_ctx->p,
1018 						   firm_ctx->transfer, apply_firmware_complete, firm_ctx);
1019 		if (rc) {
1020 			spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1021 							 "firmware download failed.");
1022 			apply_firmware_cleanup(firm_ctx);
1023 			return;
1024 		}
1025 		break;
1026 	}
1027 }
1028 
1029 static void
1030 apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
1031 {
1032 	struct firmware_update_info *firm_ctx = cb_arg;
1033 
1034 	spdk_bdev_free_io(bdev_io);
1035 
1036 	firm_ctx->success = success;
1037 
1038 	spdk_thread_exec_msg(firm_ctx->orig_thread, _apply_firmware_complete, firm_ctx);
1039 }
1040 
1041 static void
1042 apply_firmware_open_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx)
1043 {
1044 }
1045 
1046 static void
1047 rpc_bdev_nvme_apply_firmware(struct spdk_jsonrpc_request *request,
1048 			     const struct spdk_json_val *params)
1049 {
1050 	int					rc;
1051 	int					fd = -1;
1052 	struct stat				fw_stat;
1053 	struct spdk_bdev			*bdev;
1054 	struct spdk_nvme_cmd			cmd = {};
1055 	struct firmware_update_info		*firm_ctx;
1056 
1057 	firm_ctx = calloc(1, sizeof(struct firmware_update_info));
1058 	if (!firm_ctx) {
1059 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1060 						 "Memory allocation error.");
1061 		return;
1062 	}
1063 	firm_ctx->fw_image = NULL;
1064 	firm_ctx->request = request;
1065 	firm_ctx->orig_thread = spdk_get_thread();
1066 
1067 	if (spdk_json_decode_object(params, rpc_apply_firmware_decoders,
1068 				    SPDK_COUNTOF(rpc_apply_firmware_decoders), &firm_ctx->req)) {
1069 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1070 						 "spdk_json_decode_object failed.");
1071 		goto err;
1072 	}
1073 
1074 	if (spdk_bdev_open_ext(firm_ctx->req.bdev_name, true, apply_firmware_open_cb, NULL,
1075 			       &firm_ctx->desc) != 0) {
1076 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1077 						     "bdev %s could not be opened",
1078 						     firm_ctx->req.bdev_name);
1079 		goto err;
1080 	}
1081 	bdev = spdk_bdev_desc_get_bdev(firm_ctx->desc);
1082 
1083 	if ((firm_ctx->ctrlr = bdev_nvme_get_ctrlr(bdev)) == NULL) {
1084 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1085 						     "Controller information for %s were not found.",
1086 						     firm_ctx->req.bdev_name);
1087 		goto err;
1088 	}
1089 
1090 	firm_ctx->ch = spdk_bdev_get_io_channel(firm_ctx->desc);
1091 	if (!firm_ctx->ch) {
1092 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1093 						 "No channels were found.");
1094 		goto err;
1095 	}
1096 
1097 	fd = open(firm_ctx->req.filename, O_RDONLY);
1098 	if (fd < 0) {
1099 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1100 						 "open file failed.");
1101 		goto err;
1102 	}
1103 
1104 	rc = fstat(fd, &fw_stat);
1105 	if (rc < 0) {
1106 		close(fd);
1107 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1108 						 "fstat failed.");
1109 		goto err;
1110 	}
1111 
1112 	firm_ctx->size = fw_stat.st_size;
1113 	if (fw_stat.st_size % 4) {
1114 		close(fd);
1115 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1116 						 "Firmware image size is not multiple of 4.");
1117 		goto err;
1118 	}
1119 
1120 	firm_ctx->fw_image = spdk_zmalloc(firm_ctx->size, 4096, NULL,
1121 					  SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
1122 	if (!firm_ctx->fw_image) {
1123 		close(fd);
1124 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1125 						 "Memory allocation error.");
1126 		goto err;
1127 	}
1128 	firm_ctx->p = firm_ctx->fw_image;
1129 
1130 	if (read(fd, firm_ctx->p, firm_ctx->size) != ((ssize_t)(firm_ctx->size))) {
1131 		close(fd);
1132 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1133 						 "Read firmware image failed!");
1134 		goto err;
1135 	}
1136 	close(fd);
1137 
1138 	firm_ctx->offset = 0;
1139 	firm_ctx->size_remaining = firm_ctx->size;
1140 	firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096);
1141 
1142 	cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD;
1143 	cmd.cdw10 = spdk_nvme_bytes_to_numd(firm_ctx->transfer);
1144 	cmd.cdw11 = firm_ctx->offset >> 2;
1145 
1146 	rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, firm_ctx->p,
1147 					   firm_ctx->transfer, apply_firmware_complete, firm_ctx);
1148 	if (rc == 0) {
1149 		/* normal return here. */
1150 		return;
1151 	}
1152 
1153 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1154 					 "Read firmware image failed!");
1155 err:
1156 	apply_firmware_cleanup(firm_ctx);
1157 }
1158 SPDK_RPC_REGISTER("bdev_nvme_apply_firmware", rpc_bdev_nvme_apply_firmware, SPDK_RPC_RUNTIME)
1159 
1160 struct rpc_bdev_nvme_transport_stat_ctx {
1161 	struct spdk_jsonrpc_request *request;
1162 	struct spdk_json_write_ctx *w;
1163 };
1164 
1165 static void
1166 rpc_bdev_nvme_rdma_stats(struct spdk_json_write_ctx *w,
1167 			 struct spdk_nvme_transport_poll_group_stat *stat)
1168 {
1169 	struct spdk_nvme_rdma_device_stat *device_stats;
1170 	uint32_t i;
1171 
1172 	spdk_json_write_named_array_begin(w, "devices");
1173 
1174 	for (i = 0; i < stat->rdma.num_devices; i++) {
1175 		device_stats = &stat->rdma.device_stats[i];
1176 		spdk_json_write_object_begin(w);
1177 		spdk_json_write_named_string(w, "dev_name", device_stats->name);
1178 		spdk_json_write_named_uint64(w, "polls", device_stats->polls);
1179 		spdk_json_write_named_uint64(w, "idle_polls", device_stats->idle_polls);
1180 		spdk_json_write_named_uint64(w, "completions", device_stats->completions);
1181 		spdk_json_write_named_uint64(w, "queued_requests", device_stats->queued_requests);
1182 		spdk_json_write_named_uint64(w, "total_send_wrs", device_stats->total_send_wrs);
1183 		spdk_json_write_named_uint64(w, "send_doorbell_updates", device_stats->send_doorbell_updates);
1184 		spdk_json_write_named_uint64(w, "total_recv_wrs", device_stats->total_recv_wrs);
1185 		spdk_json_write_named_uint64(w, "recv_doorbell_updates", device_stats->recv_doorbell_updates);
1186 		spdk_json_write_object_end(w);
1187 	}
1188 	spdk_json_write_array_end(w);
1189 }
1190 
1191 static void
1192 rpc_bdev_nvme_pcie_stats(struct spdk_json_write_ctx *w,
1193 			 struct spdk_nvme_transport_poll_group_stat *stat)
1194 {
1195 	spdk_json_write_named_uint64(w, "polls", stat->pcie.polls);
1196 	spdk_json_write_named_uint64(w, "idle_polls", stat->pcie.idle_polls);
1197 	spdk_json_write_named_uint64(w, "completions", stat->pcie.completions);
1198 	spdk_json_write_named_uint64(w, "cq_mmio_doorbell_updates", stat->pcie.cq_mmio_doorbell_updates);
1199 	spdk_json_write_named_uint64(w, "cq_shadow_doorbell_updates",
1200 				     stat->pcie.cq_shadow_doorbell_updates);
1201 	spdk_json_write_named_uint64(w, "queued_requests", stat->pcie.queued_requests);
1202 	spdk_json_write_named_uint64(w, "submitted_requests", stat->pcie.submitted_requests);
1203 	spdk_json_write_named_uint64(w, "sq_mmio_doorbell_updates", stat->pcie.sq_mmio_doorbell_updates);
1204 	spdk_json_write_named_uint64(w, "sq_shadow_doorbell_updates",
1205 				     stat->pcie.sq_shadow_doorbell_updates);
1206 }
1207 
1208 static void
1209 rpc_bdev_nvme_tcp_stats(struct spdk_json_write_ctx *w,
1210 			struct spdk_nvme_transport_poll_group_stat *stat)
1211 {
1212 	spdk_json_write_named_uint64(w, "polls", stat->tcp.polls);
1213 	spdk_json_write_named_uint64(w, "idle_polls", stat->tcp.idle_polls);
1214 	spdk_json_write_named_uint64(w, "socket_completions", stat->tcp.socket_completions);
1215 	spdk_json_write_named_uint64(w, "nvme_completions", stat->tcp.nvme_completions);
1216 	spdk_json_write_named_uint64(w, "queued_requests", stat->tcp.queued_requests);
1217 	spdk_json_write_named_uint64(w, "submitted_requests", stat->tcp.submitted_requests);
1218 }
1219 
1220 static void
1221 rpc_bdev_nvme_stats_per_channel(struct spdk_io_channel_iter *i)
1222 {
1223 	struct rpc_bdev_nvme_transport_stat_ctx *ctx;
1224 	struct spdk_io_channel *ch;
1225 	struct nvme_poll_group *group;
1226 	struct spdk_nvme_poll_group_stat *stat;
1227 	struct spdk_nvme_transport_poll_group_stat *tr_stat;
1228 	uint32_t j;
1229 	int rc;
1230 
1231 	ctx = spdk_io_channel_iter_get_ctx(i);
1232 	ch = spdk_io_channel_iter_get_channel(i);
1233 	group = spdk_io_channel_get_ctx(ch);
1234 
1235 	rc = spdk_nvme_poll_group_get_stats(group->group, &stat);
1236 	if (rc) {
1237 		spdk_for_each_channel_continue(i, rc);
1238 		return;
1239 	}
1240 
1241 	spdk_json_write_object_begin(ctx->w);
1242 	spdk_json_write_named_string(ctx->w, "thread", spdk_thread_get_name(spdk_get_thread()));
1243 	spdk_json_write_named_array_begin(ctx->w, "transports");
1244 
1245 	for (j = 0; j < stat->num_transports; j++) {
1246 		tr_stat = stat->transport_stat[j];
1247 		spdk_json_write_object_begin(ctx->w);
1248 		spdk_json_write_named_string(ctx->w, "trname", spdk_nvme_transport_id_trtype_str(tr_stat->trtype));
1249 
1250 		switch (stat->transport_stat[j]->trtype) {
1251 		case SPDK_NVME_TRANSPORT_RDMA:
1252 			rpc_bdev_nvme_rdma_stats(ctx->w, tr_stat);
1253 			break;
1254 		case SPDK_NVME_TRANSPORT_PCIE:
1255 		case SPDK_NVME_TRANSPORT_VFIOUSER:
1256 			rpc_bdev_nvme_pcie_stats(ctx->w, tr_stat);
1257 			break;
1258 		case SPDK_NVME_TRANSPORT_TCP:
1259 			rpc_bdev_nvme_tcp_stats(ctx->w, tr_stat);
1260 			break;
1261 		default:
1262 			SPDK_WARNLOG("Can't handle trtype %d %s\n", tr_stat->trtype,
1263 				     spdk_nvme_transport_id_trtype_str(tr_stat->trtype));
1264 		}
1265 		spdk_json_write_object_end(ctx->w);
1266 	}
1267 	/* transports array */
1268 	spdk_json_write_array_end(ctx->w);
1269 	spdk_json_write_object_end(ctx->w);
1270 
1271 	spdk_nvme_poll_group_free_stats(group->group, stat);
1272 	spdk_for_each_channel_continue(i, 0);
1273 }
1274 
1275 static void
1276 rpc_bdev_nvme_stats_done(struct spdk_io_channel_iter *i, int status)
1277 {
1278 	struct rpc_bdev_nvme_transport_stat_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1279 
1280 	spdk_json_write_array_end(ctx->w);
1281 	spdk_json_write_object_end(ctx->w);
1282 	spdk_jsonrpc_end_result(ctx->request, ctx->w);
1283 	free(ctx);
1284 }
1285 
1286 static void
1287 rpc_bdev_nvme_get_transport_statistics(struct spdk_jsonrpc_request *request,
1288 				       const struct spdk_json_val *params)
1289 {
1290 	struct rpc_bdev_nvme_transport_stat_ctx *ctx;
1291 
1292 	if (params) {
1293 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1294 						 "'bdev_nvme_get_transport_statistics' requires no arguments");
1295 		return;
1296 	}
1297 
1298 	ctx = calloc(1, sizeof(*ctx));
1299 	if (!ctx) {
1300 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1301 						 "Memory allocation error");
1302 		return;
1303 	}
1304 	ctx->request = request;
1305 	ctx->w = spdk_jsonrpc_begin_result(ctx->request);
1306 	spdk_json_write_object_begin(ctx->w);
1307 	spdk_json_write_named_array_begin(ctx->w, "poll_groups");
1308 
1309 	spdk_for_each_channel(&g_nvme_bdev_ctrlrs,
1310 			      rpc_bdev_nvme_stats_per_channel,
1311 			      ctx,
1312 			      rpc_bdev_nvme_stats_done);
1313 }
1314 SPDK_RPC_REGISTER("bdev_nvme_get_transport_statistics", rpc_bdev_nvme_get_transport_statistics,
1315 		  SPDK_RPC_RUNTIME)
1316 
1317 struct rpc_bdev_nvme_controller_op_req {
1318 	char *name;
1319 	uint16_t cntlid;
1320 };
1321 
1322 static void
1323 free_rpc_bdev_nvme_controller_op_req(struct rpc_bdev_nvme_controller_op_req *r)
1324 {
1325 	free(r->name);
1326 }
1327 
1328 static const struct spdk_json_object_decoder rpc_bdev_nvme_controller_op_req_decoders[] = {
1329 	{"name", offsetof(struct rpc_bdev_nvme_controller_op_req, name), spdk_json_decode_string},
1330 	{"cntlid", offsetof(struct rpc_bdev_nvme_controller_op_req, cntlid), spdk_json_decode_uint16, true},
1331 };
1332 
1333 static void
1334 rpc_bdev_nvme_controller_op_cb(void *cb_arg, int rc)
1335 {
1336 	struct spdk_jsonrpc_request *request = cb_arg;
1337 
1338 	if (rc == 0) {
1339 		spdk_jsonrpc_send_bool_response(request, true);
1340 	} else {
1341 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1342 	}
1343 }
1344 
1345 static void
1346 rpc_bdev_nvme_controller_op(struct spdk_jsonrpc_request *request,
1347 			    const struct spdk_json_val *params,
1348 			    enum nvme_ctrlr_op op)
1349 {
1350 	struct rpc_bdev_nvme_controller_op_req req = {NULL};
1351 	struct nvme_bdev_ctrlr *nbdev_ctrlr;
1352 	struct nvme_ctrlr *nvme_ctrlr;
1353 
1354 	if (spdk_json_decode_object(params, rpc_bdev_nvme_controller_op_req_decoders,
1355 				    SPDK_COUNTOF(rpc_bdev_nvme_controller_op_req_decoders),
1356 				    &req)) {
1357 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1358 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(EINVAL));
1359 		goto exit;
1360 	}
1361 
1362 	nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name(req.name);
1363 	if (nbdev_ctrlr == NULL) {
1364 		SPDK_ERRLOG("Failed at NVMe bdev controller lookup\n");
1365 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1366 		goto exit;
1367 	}
1368 
1369 	if (req.cntlid == 0) {
1370 		nvme_bdev_ctrlr_op_rpc(nbdev_ctrlr, op, rpc_bdev_nvme_controller_op_cb, request);
1371 	} else {
1372 		nvme_ctrlr = nvme_bdev_ctrlr_get_ctrlr_by_id(nbdev_ctrlr, req.cntlid);
1373 		if (nvme_ctrlr == NULL) {
1374 			SPDK_ERRLOG("Failed at NVMe controller lookup\n");
1375 			spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1376 			goto exit;
1377 		}
1378 		nvme_ctrlr_op_rpc(nvme_ctrlr, op, rpc_bdev_nvme_controller_op_cb, request);
1379 	}
1380 
1381 exit:
1382 	free_rpc_bdev_nvme_controller_op_req(&req);
1383 }
1384 
1385 static void
1386 rpc_bdev_nvme_reset_controller(struct spdk_jsonrpc_request *request,
1387 			       const struct spdk_json_val *params)
1388 {
1389 	rpc_bdev_nvme_controller_op(request, params, NVME_CTRLR_OP_RESET);
1390 }
1391 SPDK_RPC_REGISTER("bdev_nvme_reset_controller", rpc_bdev_nvme_reset_controller, SPDK_RPC_RUNTIME)
1392 
1393 static void
1394 rpc_bdev_nvme_enable_controller(struct spdk_jsonrpc_request *request,
1395 				const struct spdk_json_val *params)
1396 {
1397 	rpc_bdev_nvme_controller_op(request, params, NVME_CTRLR_OP_ENABLE);
1398 }
1399 SPDK_RPC_REGISTER("bdev_nvme_enable_controller", rpc_bdev_nvme_enable_controller, SPDK_RPC_RUNTIME)
1400 
1401 static void
1402 rpc_bdev_nvme_disable_controller(struct spdk_jsonrpc_request *request,
1403 				 const struct spdk_json_val *params)
1404 {
1405 	rpc_bdev_nvme_controller_op(request, params, NVME_CTRLR_OP_DISABLE);
1406 }
1407 SPDK_RPC_REGISTER("bdev_nvme_disable_controller", rpc_bdev_nvme_disable_controller,
1408 		  SPDK_RPC_RUNTIME)
1409 
1410 struct rpc_get_controller_health_info {
1411 	char *name;
1412 };
1413 
1414 struct spdk_nvme_health_info_context {
1415 	struct spdk_jsonrpc_request *request;
1416 	struct spdk_nvme_ctrlr *ctrlr;
1417 	struct spdk_nvme_health_information_page health_page;
1418 };
1419 
1420 static void
1421 free_rpc_get_controller_health_info(struct rpc_get_controller_health_info *r)
1422 {
1423 	free(r->name);
1424 }
1425 
1426 static const struct spdk_json_object_decoder rpc_get_controller_health_info_decoders[] = {
1427 	{"name", offsetof(struct rpc_get_controller_health_info, name), spdk_json_decode_string, true},
1428 };
1429 
1430 static void
1431 nvme_health_info_cleanup(struct spdk_nvme_health_info_context *context, bool response)
1432 {
1433 	if (response == true) {
1434 		spdk_jsonrpc_send_error_response(context->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1435 						 "Internal error.");
1436 	}
1437 
1438 	free(context);
1439 }
1440 
1441 static void
1442 get_health_log_page_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
1443 {
1444 	int i;
1445 	char buf[128];
1446 	struct spdk_nvme_health_info_context *context = cb_arg;
1447 	struct spdk_jsonrpc_request *request = context->request;
1448 	struct spdk_json_write_ctx *w;
1449 	struct spdk_nvme_ctrlr *ctrlr = context->ctrlr;
1450 	const struct spdk_nvme_transport_id *trid = NULL;
1451 	const struct spdk_nvme_ctrlr_data *cdata = NULL;
1452 	struct spdk_nvme_health_information_page *health_page = NULL;
1453 
1454 	if (spdk_nvme_cpl_is_error(cpl)) {
1455 		nvme_health_info_cleanup(context, true);
1456 		SPDK_ERRLOG("get log page failed\n");
1457 		return;
1458 	}
1459 
1460 	if (ctrlr == NULL) {
1461 		nvme_health_info_cleanup(context, true);
1462 		SPDK_ERRLOG("ctrlr is NULL\n");
1463 		return;
1464 	} else {
1465 		trid = spdk_nvme_ctrlr_get_transport_id(ctrlr);
1466 		cdata = spdk_nvme_ctrlr_get_data(ctrlr);
1467 		health_page = &(context->health_page);
1468 	}
1469 
1470 	w = spdk_jsonrpc_begin_result(request);
1471 
1472 	spdk_json_write_object_begin(w);
1473 	snprintf(buf, sizeof(cdata->mn) + 1, "%s", cdata->mn);
1474 	spdk_str_trim(buf);
1475 	spdk_json_write_named_string(w, "model_number", buf);
1476 	snprintf(buf, sizeof(cdata->sn) + 1, "%s", cdata->sn);
1477 	spdk_str_trim(buf);
1478 	spdk_json_write_named_string(w, "serial_number", buf);
1479 	snprintf(buf, sizeof(cdata->fr) + 1, "%s", cdata->fr);
1480 	spdk_str_trim(buf);
1481 	spdk_json_write_named_string(w, "firmware_revision", buf);
1482 	spdk_json_write_named_string(w, "traddr", trid->traddr);
1483 	spdk_json_write_named_uint64(w, "critical_warning", health_page->critical_warning.raw);
1484 	spdk_json_write_named_uint64(w, "temperature_celsius", health_page->temperature - 273);
1485 	spdk_json_write_named_uint64(w, "available_spare_percentage", health_page->available_spare);
1486 	spdk_json_write_named_uint64(w, "available_spare_threshold_percentage",
1487 				     health_page->available_spare_threshold);
1488 	spdk_json_write_named_uint64(w, "percentage_used", health_page->percentage_used);
1489 	spdk_json_write_named_uint128(w, "data_units_read",
1490 				      health_page->data_units_read[0], health_page->data_units_read[1]);
1491 	spdk_json_write_named_uint128(w, "data_units_written",
1492 				      health_page->data_units_written[0], health_page->data_units_written[1]);
1493 	spdk_json_write_named_uint128(w, "host_read_commands",
1494 				      health_page->host_read_commands[0], health_page->host_read_commands[1]);
1495 	spdk_json_write_named_uint128(w, "host_write_commands",
1496 				      health_page->host_write_commands[0], health_page->host_write_commands[1]);
1497 	spdk_json_write_named_uint128(w, "controller_busy_time",
1498 				      health_page->controller_busy_time[0], health_page->controller_busy_time[1]);
1499 	spdk_json_write_named_uint128(w, "power_cycles",
1500 				      health_page->power_cycles[0], health_page->power_cycles[1]);
1501 	spdk_json_write_named_uint128(w, "power_on_hours",
1502 				      health_page->power_on_hours[0], health_page->power_on_hours[1]);
1503 	spdk_json_write_named_uint128(w, "unsafe_shutdowns",
1504 				      health_page->unsafe_shutdowns[0], health_page->unsafe_shutdowns[1]);
1505 	spdk_json_write_named_uint128(w, "media_errors",
1506 				      health_page->media_errors[0], health_page->media_errors[1]);
1507 	spdk_json_write_named_uint128(w, "num_err_log_entries",
1508 				      health_page->num_error_info_log_entries[0], health_page->num_error_info_log_entries[1]);
1509 	spdk_json_write_named_uint64(w, "warning_temperature_time_minutes", health_page->warning_temp_time);
1510 	spdk_json_write_named_uint64(w, "critical_composite_temperature_time_minutes",
1511 				     health_page->critical_temp_time);
1512 	for (i = 0; i < 8; i++) {
1513 		if (health_page->temp_sensor[i] != 0) {
1514 			spdk_json_write_named_uint64(w, "temperature_sensor_celsius", health_page->temp_sensor[i] - 273);
1515 		}
1516 	}
1517 	spdk_json_write_object_end(w);
1518 
1519 	spdk_jsonrpc_end_result(request, w);
1520 	nvme_health_info_cleanup(context, false);
1521 }
1522 
1523 static void
1524 get_health_log_page(struct spdk_nvme_health_info_context *context)
1525 {
1526 	struct spdk_nvme_ctrlr *ctrlr = context->ctrlr;
1527 
1528 	if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_HEALTH_INFORMATION,
1529 					     SPDK_NVME_GLOBAL_NS_TAG,
1530 					     &(context->health_page), sizeof(context->health_page), 0,
1531 					     get_health_log_page_completion, context)) {
1532 		nvme_health_info_cleanup(context, true);
1533 		SPDK_ERRLOG("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
1534 	}
1535 }
1536 
1537 static void
1538 get_temperature_threshold_feature_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
1539 {
1540 	struct spdk_nvme_health_info_context *context = cb_arg;
1541 
1542 	if (spdk_nvme_cpl_is_error(cpl)) {
1543 		nvme_health_info_cleanup(context, true);
1544 		SPDK_ERRLOG("feature SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD failed in completion\n");
1545 	} else {
1546 		get_health_log_page(context);
1547 	}
1548 }
1549 
1550 static int
1551 get_temperature_threshold_feature(struct spdk_nvme_health_info_context *context)
1552 {
1553 	struct spdk_nvme_cmd cmd = {};
1554 
1555 	cmd.opc = SPDK_NVME_OPC_GET_FEATURES;
1556 	cmd.cdw10 = SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD;
1557 
1558 	return spdk_nvme_ctrlr_cmd_admin_raw(context->ctrlr, &cmd, NULL, 0,
1559 					     get_temperature_threshold_feature_completion, context);
1560 }
1561 
1562 static void
1563 get_controller_health_info(struct spdk_jsonrpc_request *request, struct spdk_nvme_ctrlr *ctrlr)
1564 {
1565 	struct spdk_nvme_health_info_context *context;
1566 
1567 	context = calloc(1, sizeof(struct spdk_nvme_health_info_context));
1568 	if (!context) {
1569 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1570 						 "Memory allocation error.");
1571 		return;
1572 	}
1573 
1574 	context->request = request;
1575 	context->ctrlr = ctrlr;
1576 
1577 	if (get_temperature_threshold_feature(context)) {
1578 		nvme_health_info_cleanup(context, true);
1579 		SPDK_ERRLOG("feature SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD failed to submit\n");
1580 	}
1581 
1582 	return;
1583 }
1584 
1585 static void
1586 rpc_bdev_nvme_get_controller_health_info(struct spdk_jsonrpc_request *request,
1587 		const struct spdk_json_val *params)
1588 {
1589 	struct rpc_get_controller_health_info req = {};
1590 	struct nvme_ctrlr *nvme_ctrlr = NULL;
1591 
1592 	if (!params) {
1593 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1594 						 "Missing device name");
1595 
1596 		return;
1597 	}
1598 	if (spdk_json_decode_object(params, rpc_get_controller_health_info_decoders,
1599 				    SPDK_COUNTOF(rpc_get_controller_health_info_decoders), &req)) {
1600 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1601 		free_rpc_get_controller_health_info(&req);
1602 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1603 						 "Invalid parameters");
1604 
1605 		return;
1606 	}
1607 
1608 	nvme_ctrlr = nvme_ctrlr_get_by_name(req.name);
1609 
1610 	if (!nvme_ctrlr) {
1611 		SPDK_ERRLOG("nvme ctrlr name '%s' does not exist\n", req.name);
1612 		free_rpc_get_controller_health_info(&req);
1613 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1614 						 "Device not found");
1615 		return;
1616 	}
1617 
1618 	get_controller_health_info(request, nvme_ctrlr->ctrlr);
1619 	free_rpc_get_controller_health_info(&req);
1620 
1621 	return;
1622 }
1623 SPDK_RPC_REGISTER("bdev_nvme_get_controller_health_info",
1624 		  rpc_bdev_nvme_get_controller_health_info, SPDK_RPC_RUNTIME)
1625 
1626 struct rpc_bdev_nvme_start_discovery {
1627 	char *name;
1628 	char *trtype;
1629 	char *adrfam;
1630 	char *traddr;
1631 	char *trsvcid;
1632 	char *hostnqn;
1633 	bool wait_for_attach;
1634 	uint64_t attach_timeout_ms;
1635 	struct spdk_nvme_ctrlr_opts opts;
1636 	struct spdk_bdev_nvme_ctrlr_opts bdev_opts;
1637 };
1638 
1639 static void
1640 free_rpc_bdev_nvme_start_discovery(struct rpc_bdev_nvme_start_discovery *req)
1641 {
1642 	free(req->name);
1643 	free(req->trtype);
1644 	free(req->adrfam);
1645 	free(req->traddr);
1646 	free(req->trsvcid);
1647 	free(req->hostnqn);
1648 }
1649 
1650 static const struct spdk_json_object_decoder rpc_bdev_nvme_start_discovery_decoders[] = {
1651 	{"name", offsetof(struct rpc_bdev_nvme_start_discovery, name), spdk_json_decode_string},
1652 	{"trtype", offsetof(struct rpc_bdev_nvme_start_discovery, trtype), spdk_json_decode_string},
1653 	{"traddr", offsetof(struct rpc_bdev_nvme_start_discovery, traddr), spdk_json_decode_string},
1654 	{"adrfam", offsetof(struct rpc_bdev_nvme_start_discovery, adrfam), spdk_json_decode_string, true},
1655 	{"trsvcid", offsetof(struct rpc_bdev_nvme_start_discovery, trsvcid), spdk_json_decode_string, true},
1656 	{"hostnqn", offsetof(struct rpc_bdev_nvme_start_discovery, hostnqn), spdk_json_decode_string, true},
1657 	{"wait_for_attach", offsetof(struct rpc_bdev_nvme_start_discovery, wait_for_attach), spdk_json_decode_bool, true},
1658 	{"attach_timeout_ms", offsetof(struct rpc_bdev_nvme_start_discovery, attach_timeout_ms), spdk_json_decode_uint64, true},
1659 	{"ctrlr_loss_timeout_sec", offsetof(struct rpc_bdev_nvme_start_discovery, bdev_opts.ctrlr_loss_timeout_sec), spdk_json_decode_int32, true},
1660 	{"reconnect_delay_sec", offsetof(struct rpc_bdev_nvme_start_discovery, bdev_opts.reconnect_delay_sec), spdk_json_decode_uint32, true},
1661 	{"fast_io_fail_timeout_sec", offsetof(struct rpc_bdev_nvme_start_discovery, bdev_opts.fast_io_fail_timeout_sec), spdk_json_decode_uint32, true},
1662 };
1663 
1664 struct rpc_bdev_nvme_start_discovery_ctx {
1665 	struct rpc_bdev_nvme_start_discovery req;
1666 	struct spdk_jsonrpc_request *request;
1667 };
1668 
1669 static void
1670 rpc_bdev_nvme_start_discovery_done(void *ctx, int status)
1671 {
1672 	struct spdk_jsonrpc_request *request = ctx;
1673 
1674 	if (status != 0) {
1675 		spdk_jsonrpc_send_error_response(request, status, spdk_strerror(-status));
1676 	} else {
1677 		spdk_jsonrpc_send_bool_response(request, true);
1678 	}
1679 }
1680 
1681 static void
1682 rpc_bdev_nvme_start_discovery(struct spdk_jsonrpc_request *request,
1683 			      const struct spdk_json_val *params)
1684 {
1685 	struct rpc_bdev_nvme_start_discovery_ctx *ctx;
1686 	struct spdk_nvme_transport_id trid = {};
1687 	size_t len, maxlen;
1688 	int rc;
1689 	spdk_bdev_nvme_start_discovery_fn cb_fn;
1690 	void *cb_ctx;
1691 
1692 	ctx = calloc(1, sizeof(*ctx));
1693 	if (!ctx) {
1694 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1695 		return;
1696 	}
1697 
1698 	spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->req.opts, sizeof(ctx->req.opts));
1699 
1700 	if (spdk_json_decode_object(params, rpc_bdev_nvme_start_discovery_decoders,
1701 				    SPDK_COUNTOF(rpc_bdev_nvme_start_discovery_decoders),
1702 				    &ctx->req)) {
1703 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1704 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1705 						 "spdk_json_decode_object failed");
1706 		goto cleanup;
1707 	}
1708 
1709 	/* Parse trstring */
1710 	rc = spdk_nvme_transport_id_populate_trstring(&trid, ctx->req.trtype);
1711 	if (rc < 0) {
1712 		SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype);
1713 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s",
1714 						     ctx->req.trtype);
1715 		goto cleanup;
1716 	}
1717 
1718 	/* Parse trtype */
1719 	rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype);
1720 	assert(rc == 0);
1721 
1722 	/* Parse traddr */
1723 	maxlen = sizeof(trid.traddr);
1724 	len = strnlen(ctx->req.traddr, maxlen);
1725 	if (len == maxlen) {
1726 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s",
1727 						     ctx->req.traddr);
1728 		goto cleanup;
1729 	}
1730 	memcpy(trid.traddr, ctx->req.traddr, len + 1);
1731 
1732 	/* Parse adrfam */
1733 	if (ctx->req.adrfam) {
1734 		rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam);
1735 		if (rc < 0) {
1736 			SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam);
1737 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s",
1738 							     ctx->req.adrfam);
1739 			goto cleanup;
1740 		}
1741 	}
1742 
1743 	/* Parse trsvcid */
1744 	if (ctx->req.trsvcid) {
1745 		maxlen = sizeof(trid.trsvcid);
1746 		len = strnlen(ctx->req.trsvcid, maxlen);
1747 		if (len == maxlen) {
1748 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s",
1749 							     ctx->req.trsvcid);
1750 			goto cleanup;
1751 		}
1752 		memcpy(trid.trsvcid, ctx->req.trsvcid, len + 1);
1753 	}
1754 
1755 	if (ctx->req.hostnqn) {
1756 		snprintf(ctx->req.opts.hostnqn, sizeof(ctx->req.opts.hostnqn), "%s",
1757 			 ctx->req.hostnqn);
1758 	}
1759 
1760 	if (ctx->req.attach_timeout_ms != 0) {
1761 		ctx->req.wait_for_attach = true;
1762 	}
1763 
1764 	ctx->request = request;
1765 	cb_fn = ctx->req.wait_for_attach ? rpc_bdev_nvme_start_discovery_done : NULL;
1766 	cb_ctx = ctx->req.wait_for_attach ? request : NULL;
1767 	rc = bdev_nvme_start_discovery(&trid, ctx->req.name, &ctx->req.opts, &ctx->req.bdev_opts,
1768 				       ctx->req.attach_timeout_ms, false, cb_fn, cb_ctx);
1769 	if (rc) {
1770 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1771 	} else if (!ctx->req.wait_for_attach) {
1772 		rpc_bdev_nvme_start_discovery_done(request, 0);
1773 	}
1774 
1775 cleanup:
1776 	free_rpc_bdev_nvme_start_discovery(&ctx->req);
1777 	free(ctx);
1778 }
1779 SPDK_RPC_REGISTER("bdev_nvme_start_discovery", rpc_bdev_nvme_start_discovery,
1780 		  SPDK_RPC_RUNTIME)
1781 
1782 struct rpc_bdev_nvme_stop_discovery {
1783 	char *name;
1784 };
1785 
1786 static const struct spdk_json_object_decoder rpc_bdev_nvme_stop_discovery_decoders[] = {
1787 	{"name", offsetof(struct rpc_bdev_nvme_stop_discovery, name), spdk_json_decode_string},
1788 };
1789 
1790 struct rpc_bdev_nvme_stop_discovery_ctx {
1791 	struct rpc_bdev_nvme_stop_discovery req;
1792 	struct spdk_jsonrpc_request *request;
1793 };
1794 
1795 static void
1796 rpc_bdev_nvme_stop_discovery_done(void *cb_ctx)
1797 {
1798 	struct rpc_bdev_nvme_stop_discovery_ctx *ctx = cb_ctx;
1799 
1800 	spdk_jsonrpc_send_bool_response(ctx->request, true);
1801 	free(ctx->req.name);
1802 	free(ctx);
1803 }
1804 
1805 static void
1806 rpc_bdev_nvme_stop_discovery(struct spdk_jsonrpc_request *request,
1807 			     const struct spdk_json_val *params)
1808 {
1809 	struct rpc_bdev_nvme_stop_discovery_ctx *ctx;
1810 	int rc;
1811 
1812 	ctx = calloc(1, sizeof(*ctx));
1813 	if (!ctx) {
1814 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1815 		return;
1816 	}
1817 
1818 	if (spdk_json_decode_object(params, rpc_bdev_nvme_stop_discovery_decoders,
1819 				    SPDK_COUNTOF(rpc_bdev_nvme_stop_discovery_decoders),
1820 				    &ctx->req)) {
1821 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1822 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1823 						 "spdk_json_decode_object failed");
1824 		goto cleanup;
1825 	}
1826 
1827 	ctx->request = request;
1828 	rc = bdev_nvme_stop_discovery(ctx->req.name, rpc_bdev_nvme_stop_discovery_done, ctx);
1829 	if (rc) {
1830 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1831 		goto cleanup;
1832 	}
1833 
1834 	return;
1835 
1836 cleanup:
1837 	free(ctx->req.name);
1838 	free(ctx);
1839 }
1840 SPDK_RPC_REGISTER("bdev_nvme_stop_discovery", rpc_bdev_nvme_stop_discovery,
1841 		  SPDK_RPC_RUNTIME)
1842 
1843 static void
1844 rpc_bdev_nvme_get_discovery_info(struct spdk_jsonrpc_request *request,
1845 				 const struct spdk_json_val *params)
1846 {
1847 	struct spdk_json_write_ctx *w;
1848 
1849 	w = spdk_jsonrpc_begin_result(request);
1850 	bdev_nvme_get_discovery_info(w);
1851 	spdk_jsonrpc_end_result(request, w);
1852 }
1853 SPDK_RPC_REGISTER("bdev_nvme_get_discovery_info", rpc_bdev_nvme_get_discovery_info,
1854 		  SPDK_RPC_RUNTIME)
1855 
1856 enum error_injection_cmd_type {
1857 	NVME_ADMIN_CMD = 1,
1858 	NVME_IO_CMD,
1859 };
1860 
1861 struct rpc_add_error_injection {
1862 	char *name;
1863 	enum error_injection_cmd_type cmd_type;
1864 	uint8_t opc;
1865 	bool do_not_submit;
1866 	uint64_t timeout_in_us;
1867 	uint32_t err_count;
1868 	uint8_t sct;
1869 	uint8_t sc;
1870 };
1871 
1872 static void
1873 free_rpc_add_error_injection(struct rpc_add_error_injection *req)
1874 {
1875 	free(req->name);
1876 }
1877 
1878 static int
1879 rpc_error_injection_decode_cmd_type(const struct spdk_json_val *val, void *out)
1880 {
1881 	int *cmd_type = out;
1882 
1883 	if (spdk_json_strequal(val, "admin")) {
1884 		*cmd_type = NVME_ADMIN_CMD;
1885 	} else if (spdk_json_strequal(val, "io")) {
1886 		*cmd_type = NVME_IO_CMD;
1887 	} else {
1888 		SPDK_ERRLOG("Invalid parameter value: cmd_type\n");
1889 		return -EINVAL;
1890 	}
1891 
1892 	return 0;
1893 }
1894 
1895 static const struct spdk_json_object_decoder rpc_add_error_injection_decoders[] = {
1896 	{ "name", offsetof(struct rpc_add_error_injection, name), spdk_json_decode_string },
1897 	{ "cmd_type", offsetof(struct rpc_add_error_injection, cmd_type), rpc_error_injection_decode_cmd_type },
1898 	{ "opc", offsetof(struct rpc_add_error_injection, opc), spdk_json_decode_uint8 },
1899 	{ "do_not_submit", offsetof(struct rpc_add_error_injection, do_not_submit), spdk_json_decode_bool, true },
1900 	{ "timeout_in_us", offsetof(struct rpc_add_error_injection, timeout_in_us), spdk_json_decode_uint64, true },
1901 	{ "err_count", offsetof(struct rpc_add_error_injection, err_count), spdk_json_decode_uint32, true },
1902 	{ "sct", offsetof(struct rpc_add_error_injection, sct), spdk_json_decode_uint8, true},
1903 	{ "sc", offsetof(struct rpc_add_error_injection, sc), spdk_json_decode_uint8, true},
1904 };
1905 
1906 struct rpc_add_error_injection_ctx {
1907 	struct spdk_jsonrpc_request *request;
1908 	struct rpc_add_error_injection rpc;
1909 };
1910 
1911 static void
1912 rpc_add_error_injection_done(struct nvme_ctrlr *nvme_ctrlr, void *_ctx, int status)
1913 {
1914 	struct rpc_add_error_injection_ctx *ctx = _ctx;
1915 
1916 	if (status) {
1917 		spdk_jsonrpc_send_error_response(ctx->request, status,
1918 						 "Failed to add the error injection.");
1919 	} else {
1920 		spdk_jsonrpc_send_bool_response(ctx->request, true);
1921 	}
1922 
1923 	free_rpc_add_error_injection(&ctx->rpc);
1924 	free(ctx);
1925 }
1926 
1927 static void
1928 rpc_add_error_injection_per_channel(struct nvme_ctrlr_channel_iter *i,
1929 				    struct nvme_ctrlr *nvme_ctrlr,
1930 				    struct nvme_ctrlr_channel *ctrlr_ch,
1931 				    void *_ctx)
1932 {
1933 	struct rpc_add_error_injection_ctx *ctx = _ctx;
1934 	struct spdk_nvme_qpair *qpair = ctrlr_ch->qpair->qpair;
1935 	struct spdk_nvme_ctrlr *ctrlr = ctrlr_ch->qpair->ctrlr->ctrlr;
1936 	int rc = 0;
1937 
1938 	if (qpair != NULL) {
1939 		rc = spdk_nvme_qpair_add_cmd_error_injection(ctrlr, qpair, ctx->rpc.opc,
1940 				ctx->rpc.do_not_submit, ctx->rpc.timeout_in_us, ctx->rpc.err_count,
1941 				ctx->rpc.sct, ctx->rpc.sc);
1942 	}
1943 
1944 	nvme_ctrlr_for_each_channel_continue(i, rc);
1945 }
1946 
1947 static void
1948 rpc_bdev_nvme_add_error_injection(
1949 	struct spdk_jsonrpc_request *request,
1950 	const struct spdk_json_val *params)
1951 {
1952 	struct rpc_add_error_injection_ctx *ctx;
1953 	struct nvme_ctrlr *nvme_ctrlr;
1954 	int rc;
1955 
1956 	ctx = calloc(1, sizeof(*ctx));
1957 	if (!ctx) {
1958 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1959 		return;
1960 	}
1961 	ctx->rpc.err_count = 1;
1962 	ctx->request = request;
1963 
1964 	if (spdk_json_decode_object(params,
1965 				    rpc_add_error_injection_decoders,
1966 				    SPDK_COUNTOF(rpc_add_error_injection_decoders),
1967 				    &ctx->rpc)) {
1968 		spdk_jsonrpc_send_error_response(request, -EINVAL,
1969 						 "Failed to parse the request");
1970 		goto cleanup;
1971 	}
1972 
1973 	nvme_ctrlr = nvme_ctrlr_get_by_name(ctx->rpc.name);
1974 	if (nvme_ctrlr == NULL) {
1975 		SPDK_ERRLOG("No controller with specified name was found.\n");
1976 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1977 		goto cleanup;
1978 	}
1979 
1980 	if (ctx->rpc.cmd_type == NVME_IO_CMD) {
1981 		nvme_ctrlr_for_each_channel(nvme_ctrlr,
1982 					    rpc_add_error_injection_per_channel,
1983 					    ctx,
1984 					    rpc_add_error_injection_done);
1985 
1986 		return;
1987 	} else {
1988 		rc = spdk_nvme_qpair_add_cmd_error_injection(nvme_ctrlr->ctrlr, NULL, ctx->rpc.opc,
1989 				ctx->rpc.do_not_submit, ctx->rpc.timeout_in_us, ctx->rpc.err_count,
1990 				ctx->rpc.sct, ctx->rpc.sc);
1991 		if (rc) {
1992 			spdk_jsonrpc_send_error_response(request, -rc,
1993 							 "Failed to add the error injection");
1994 		} else {
1995 			spdk_jsonrpc_send_bool_response(ctx->request, true);
1996 		}
1997 	}
1998 
1999 cleanup:
2000 	free_rpc_add_error_injection(&ctx->rpc);
2001 	free(ctx);
2002 }
2003 SPDK_RPC_REGISTER("bdev_nvme_add_error_injection", rpc_bdev_nvme_add_error_injection,
2004 		  SPDK_RPC_RUNTIME)
2005 
2006 struct rpc_remove_error_injection {
2007 	char *name;
2008 	enum error_injection_cmd_type cmd_type;
2009 	uint8_t opc;
2010 };
2011 
2012 static void
2013 free_rpc_remove_error_injection(struct rpc_remove_error_injection *req)
2014 {
2015 	free(req->name);
2016 }
2017 
2018 static const struct spdk_json_object_decoder rpc_remove_error_injection_decoders[] = {
2019 	{ "name", offsetof(struct rpc_remove_error_injection, name), spdk_json_decode_string },
2020 	{ "cmd_type", offsetof(struct rpc_remove_error_injection, cmd_type), rpc_error_injection_decode_cmd_type },
2021 	{ "opc", offsetof(struct rpc_remove_error_injection, opc), spdk_json_decode_uint8 },
2022 };
2023 
2024 struct rpc_remove_error_injection_ctx {
2025 	struct spdk_jsonrpc_request *request;
2026 	struct rpc_remove_error_injection rpc;
2027 };
2028 
2029 static void
2030 rpc_remove_error_injection_done(struct nvme_ctrlr *nvme_ctrlr, void *_ctx, int status)
2031 {
2032 	struct rpc_remove_error_injection_ctx *ctx = _ctx;
2033 
2034 	if (status) {
2035 		spdk_jsonrpc_send_error_response(ctx->request, status,
2036 						 "Failed to remove the error injection.");
2037 	} else {
2038 		spdk_jsonrpc_send_bool_response(ctx->request, true);
2039 	}
2040 
2041 	free_rpc_remove_error_injection(&ctx->rpc);
2042 	free(ctx);
2043 }
2044 
2045 static void
2046 rpc_remove_error_injection_per_channel(struct nvme_ctrlr_channel_iter *i,
2047 				       struct nvme_ctrlr *nvme_ctrlr,
2048 				       struct nvme_ctrlr_channel *ctrlr_ch,
2049 				       void *_ctx)
2050 {
2051 	struct rpc_remove_error_injection_ctx *ctx = _ctx;
2052 	struct spdk_nvme_qpair *qpair = ctrlr_ch->qpair->qpair;
2053 	struct spdk_nvme_ctrlr *ctrlr = ctrlr_ch->qpair->ctrlr->ctrlr;
2054 
2055 	if (qpair != NULL) {
2056 		spdk_nvme_qpair_remove_cmd_error_injection(ctrlr, qpair, ctx->rpc.opc);
2057 	}
2058 
2059 	nvme_ctrlr_for_each_channel_continue(i, 0);
2060 }
2061 
2062 static void
2063 rpc_bdev_nvme_remove_error_injection(struct spdk_jsonrpc_request *request,
2064 				     const struct spdk_json_val *params)
2065 {
2066 	struct rpc_remove_error_injection_ctx *ctx;
2067 	struct nvme_ctrlr *nvme_ctrlr;
2068 
2069 	ctx = calloc(1, sizeof(*ctx));
2070 	if (!ctx) {
2071 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
2072 		return;
2073 	}
2074 	ctx->request = request;
2075 
2076 	if (spdk_json_decode_object(params,
2077 				    rpc_remove_error_injection_decoders,
2078 				    SPDK_COUNTOF(rpc_remove_error_injection_decoders),
2079 				    &ctx->rpc)) {
2080 		spdk_jsonrpc_send_error_response(request, -EINVAL,
2081 						 "Failed to parse the request");
2082 		goto cleanup;
2083 	}
2084 
2085 	nvme_ctrlr = nvme_ctrlr_get_by_name(ctx->rpc.name);
2086 	if (nvme_ctrlr == NULL) {
2087 		SPDK_ERRLOG("No controller with specified name was found.\n");
2088 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
2089 		goto cleanup;
2090 	}
2091 
2092 	if (ctx->rpc.cmd_type == NVME_IO_CMD) {
2093 		nvme_ctrlr_for_each_channel(nvme_ctrlr,
2094 					    rpc_remove_error_injection_per_channel,
2095 					    ctx,
2096 					    rpc_remove_error_injection_done);
2097 		return;
2098 	} else {
2099 		spdk_nvme_qpair_remove_cmd_error_injection(nvme_ctrlr->ctrlr, NULL, ctx->rpc.opc);
2100 		spdk_jsonrpc_send_bool_response(ctx->request, true);
2101 	}
2102 
2103 cleanup:
2104 	free_rpc_remove_error_injection(&ctx->rpc);
2105 	free(ctx);
2106 }
2107 SPDK_RPC_REGISTER("bdev_nvme_remove_error_injection", rpc_bdev_nvme_remove_error_injection,
2108 		  SPDK_RPC_RUNTIME)
2109 
2110 struct rpc_get_io_paths {
2111 	char *name;
2112 };
2113 
2114 static void
2115 free_rpc_get_io_paths(struct rpc_get_io_paths *r)
2116 {
2117 	free(r->name);
2118 }
2119 
2120 static const struct spdk_json_object_decoder rpc_get_io_paths_decoders[] = {
2121 	{"name", offsetof(struct rpc_get_io_paths, name), spdk_json_decode_string, true},
2122 };
2123 
2124 struct rpc_get_io_paths_ctx {
2125 	struct rpc_get_io_paths req;
2126 	struct spdk_jsonrpc_request *request;
2127 	struct spdk_json_write_ctx *w;
2128 };
2129 
2130 static void
2131 rpc_bdev_nvme_get_io_paths_done(struct spdk_io_channel_iter *i, int status)
2132 {
2133 	struct rpc_get_io_paths_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2134 
2135 	spdk_json_write_array_end(ctx->w);
2136 
2137 	spdk_json_write_object_end(ctx->w);
2138 
2139 	spdk_jsonrpc_end_result(ctx->request, ctx->w);
2140 
2141 	free_rpc_get_io_paths(&ctx->req);
2142 	free(ctx);
2143 }
2144 
2145 static void
2146 _rpc_bdev_nvme_get_io_paths(struct spdk_io_channel_iter *i)
2147 {
2148 	struct spdk_io_channel *_ch = spdk_io_channel_iter_get_channel(i);
2149 	struct nvme_poll_group *group = spdk_io_channel_get_ctx(_ch);
2150 	struct rpc_get_io_paths_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2151 	struct nvme_qpair *qpair;
2152 	struct nvme_io_path *io_path;
2153 	struct nvme_bdev *nbdev;
2154 
2155 	spdk_json_write_object_begin(ctx->w);
2156 
2157 	spdk_json_write_named_string(ctx->w, "thread", spdk_thread_get_name(spdk_get_thread()));
2158 
2159 	spdk_json_write_named_array_begin(ctx->w, "io_paths");
2160 
2161 	TAILQ_FOREACH(qpair, &group->qpair_list, tailq) {
2162 		TAILQ_FOREACH(io_path, &qpair->io_path_list, tailq) {
2163 			nbdev = io_path->nvme_ns->bdev;
2164 
2165 			if (ctx->req.name != NULL &&
2166 			    strcmp(ctx->req.name, nbdev->disk.name) != 0) {
2167 				continue;
2168 			}
2169 
2170 			nvme_io_path_info_json(ctx->w, io_path);
2171 		}
2172 	}
2173 
2174 	spdk_json_write_array_end(ctx->w);
2175 
2176 	spdk_json_write_object_end(ctx->w);
2177 
2178 	spdk_for_each_channel_continue(i, 0);
2179 }
2180 
2181 static void
2182 rpc_bdev_nvme_get_io_paths(struct spdk_jsonrpc_request *request,
2183 			   const struct spdk_json_val *params)
2184 {
2185 	struct rpc_get_io_paths_ctx *ctx;
2186 
2187 	ctx = calloc(1, sizeof(*ctx));
2188 	if (ctx == NULL) {
2189 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
2190 		return;
2191 	}
2192 
2193 	if (params != NULL &&
2194 	    spdk_json_decode_object(params, rpc_get_io_paths_decoders,
2195 				    SPDK_COUNTOF(rpc_get_io_paths_decoders),
2196 				    &ctx->req)) {
2197 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
2198 						 "bdev_nvme_get_io_paths requires no parameters");
2199 
2200 		free_rpc_get_io_paths(&ctx->req);
2201 		free(ctx);
2202 		return;
2203 	}
2204 
2205 	ctx->request = request;
2206 	ctx->w = spdk_jsonrpc_begin_result(request);
2207 
2208 	spdk_json_write_object_begin(ctx->w);
2209 
2210 	spdk_json_write_named_array_begin(ctx->w, "poll_groups");
2211 
2212 	spdk_for_each_channel(&g_nvme_bdev_ctrlrs,
2213 			      _rpc_bdev_nvme_get_io_paths,
2214 			      ctx,
2215 			      rpc_bdev_nvme_get_io_paths_done);
2216 }
2217 SPDK_RPC_REGISTER("bdev_nvme_get_io_paths", rpc_bdev_nvme_get_io_paths, SPDK_RPC_RUNTIME)
2218 
2219 struct rpc_bdev_nvme_set_preferred_path {
2220 	char *name;
2221 	uint16_t cntlid;
2222 };
2223 
2224 static void
2225 free_rpc_bdev_nvme_set_preferred_path(struct rpc_bdev_nvme_set_preferred_path *req)
2226 {
2227 	free(req->name);
2228 }
2229 
2230 static const struct spdk_json_object_decoder rpc_bdev_nvme_set_preferred_path_decoders[] = {
2231 	{"name", offsetof(struct rpc_bdev_nvme_set_preferred_path, name), spdk_json_decode_string},
2232 	{"cntlid", offsetof(struct rpc_bdev_nvme_set_preferred_path, cntlid), spdk_json_decode_uint16},
2233 };
2234 
2235 struct rpc_bdev_nvme_set_preferred_path_ctx {
2236 	struct rpc_bdev_nvme_set_preferred_path req;
2237 	struct spdk_jsonrpc_request *request;
2238 };
2239 
2240 static void
2241 rpc_bdev_nvme_set_preferred_path_done(void *cb_arg, int rc)
2242 {
2243 	struct rpc_bdev_nvme_set_preferred_path_ctx *ctx = cb_arg;
2244 
2245 	if (rc == 0) {
2246 		spdk_jsonrpc_send_bool_response(ctx->request, true);
2247 	} else {
2248 		spdk_jsonrpc_send_error_response(ctx->request, rc, spdk_strerror(-rc));
2249 	}
2250 
2251 	free_rpc_bdev_nvme_set_preferred_path(&ctx->req);
2252 	free(ctx);
2253 }
2254 
2255 static void
2256 rpc_bdev_nvme_set_preferred_path(struct spdk_jsonrpc_request *request,
2257 				 const struct spdk_json_val *params)
2258 {
2259 	struct rpc_bdev_nvme_set_preferred_path_ctx *ctx;
2260 
2261 	ctx = calloc(1, sizeof(*ctx));
2262 	if (ctx == NULL) {
2263 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
2264 		return;
2265 	}
2266 
2267 	if (spdk_json_decode_object(params, rpc_bdev_nvme_set_preferred_path_decoders,
2268 				    SPDK_COUNTOF(rpc_bdev_nvme_set_preferred_path_decoders),
2269 				    &ctx->req)) {
2270 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
2271 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2272 						 "spdk_json_decode_object failed");
2273 		goto cleanup;
2274 	}
2275 
2276 	ctx->request = request;
2277 
2278 	bdev_nvme_set_preferred_path(ctx->req.name, ctx->req.cntlid,
2279 				     rpc_bdev_nvme_set_preferred_path_done, ctx);
2280 	return;
2281 
2282 cleanup:
2283 	free_rpc_bdev_nvme_set_preferred_path(&ctx->req);
2284 	free(ctx);
2285 }
2286 SPDK_RPC_REGISTER("bdev_nvme_set_preferred_path", rpc_bdev_nvme_set_preferred_path,
2287 		  SPDK_RPC_RUNTIME)
2288 
2289 struct rpc_set_multipath_policy {
2290 	char *name;
2291 	enum spdk_bdev_nvme_multipath_policy policy;
2292 	enum spdk_bdev_nvme_multipath_selector selector;
2293 	uint32_t rr_min_io;
2294 };
2295 
2296 static void
2297 free_rpc_set_multipath_policy(struct rpc_set_multipath_policy *req)
2298 {
2299 	free(req->name);
2300 }
2301 
2302 static int
2303 rpc_decode_mp_policy(const struct spdk_json_val *val, void *out)
2304 {
2305 	enum spdk_bdev_nvme_multipath_policy *policy = out;
2306 
2307 	if (spdk_json_strequal(val, "active_passive") == true) {
2308 		*policy = BDEV_NVME_MP_POLICY_ACTIVE_PASSIVE;
2309 	} else if (spdk_json_strequal(val, "active_active") == true) {
2310 		*policy = BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE;
2311 	} else {
2312 		SPDK_NOTICELOG("Invalid parameter value: policy\n");
2313 		return -EINVAL;
2314 	}
2315 
2316 	return 0;
2317 }
2318 
2319 static int
2320 rpc_decode_mp_selector(const struct spdk_json_val *val, void *out)
2321 {
2322 	enum spdk_bdev_nvme_multipath_selector *selector = out;
2323 
2324 	if (spdk_json_strequal(val, "round_robin") == true) {
2325 		*selector = BDEV_NVME_MP_SELECTOR_ROUND_ROBIN;
2326 	} else if (spdk_json_strequal(val, "queue_depth") == true) {
2327 		*selector = BDEV_NVME_MP_SELECTOR_QUEUE_DEPTH;
2328 	} else {
2329 		SPDK_NOTICELOG("Invalid parameter value: selector\n");
2330 		return -EINVAL;
2331 	}
2332 
2333 	return 0;
2334 }
2335 
2336 static const struct spdk_json_object_decoder rpc_set_multipath_policy_decoders[] = {
2337 	{"name", offsetof(struct rpc_set_multipath_policy, name), spdk_json_decode_string},
2338 	{"policy", offsetof(struct rpc_set_multipath_policy, policy), rpc_decode_mp_policy},
2339 	{"selector", offsetof(struct rpc_set_multipath_policy, selector), rpc_decode_mp_selector, true},
2340 	{"rr_min_io", offsetof(struct rpc_set_multipath_policy, rr_min_io), spdk_json_decode_uint32, true},
2341 };
2342 
2343 struct rpc_set_multipath_policy_ctx {
2344 	struct rpc_set_multipath_policy req;
2345 	struct spdk_jsonrpc_request *request;
2346 };
2347 
2348 static void
2349 rpc_bdev_nvme_set_multipath_policy_done(void *cb_arg, int rc)
2350 {
2351 	struct rpc_set_multipath_policy_ctx *ctx = cb_arg;
2352 
2353 	if (rc == 0) {
2354 		spdk_jsonrpc_send_bool_response(ctx->request, true);
2355 	} else {
2356 		spdk_jsonrpc_send_error_response(ctx->request, rc, spdk_strerror(-rc));
2357 	}
2358 
2359 	free_rpc_set_multipath_policy(&ctx->req);
2360 	free(ctx);
2361 }
2362 
2363 static void
2364 rpc_bdev_nvme_set_multipath_policy(struct spdk_jsonrpc_request *request,
2365 				   const struct spdk_json_val *params)
2366 {
2367 	struct rpc_set_multipath_policy_ctx *ctx;
2368 
2369 	ctx = calloc(1, sizeof(*ctx));
2370 	if (ctx == NULL) {
2371 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
2372 		return;
2373 	}
2374 
2375 	ctx->req.rr_min_io = UINT32_MAX;
2376 	ctx->req.selector = UINT32_MAX;
2377 
2378 	if (spdk_json_decode_object(params, rpc_set_multipath_policy_decoders,
2379 				    SPDK_COUNTOF(rpc_set_multipath_policy_decoders),
2380 				    &ctx->req)) {
2381 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
2382 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2383 						 "spdk_json_decode_object failed");
2384 		goto cleanup;
2385 	}
2386 
2387 	ctx->request = request;
2388 	if (ctx->req.selector == UINT32_MAX) {
2389 		if (ctx->req.policy == BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE) {
2390 			ctx->req.selector = BDEV_NVME_MP_SELECTOR_ROUND_ROBIN;
2391 		} else {
2392 			ctx->req.selector = 0;
2393 		}
2394 	}
2395 
2396 	if (ctx->req.policy != BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE && ctx->req.selector > 0) {
2397 		SPDK_ERRLOG("selector only works in active_active mode\n");
2398 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2399 						 "spdk_json_decode_object failed");
2400 		goto cleanup;
2401 	}
2402 
2403 	spdk_bdev_nvme_set_multipath_policy(ctx->req.name, ctx->req.policy, ctx->req.selector,
2404 					    ctx->req.rr_min_io,
2405 					    rpc_bdev_nvme_set_multipath_policy_done, ctx);
2406 	return;
2407 
2408 cleanup:
2409 	free_rpc_set_multipath_policy(&ctx->req);
2410 	free(ctx);
2411 }
2412 SPDK_RPC_REGISTER("bdev_nvme_set_multipath_policy", rpc_bdev_nvme_set_multipath_policy,
2413 		  SPDK_RPC_RUNTIME)
2414 
2415 struct rpc_bdev_nvme_start_mdns_discovery {
2416 	char *name;
2417 	char *svcname;
2418 	char *hostnqn;
2419 	struct spdk_nvme_ctrlr_opts opts;
2420 	struct spdk_bdev_nvme_ctrlr_opts bdev_opts;
2421 };
2422 
2423 static void
2424 free_rpc_bdev_nvme_start_mdns_discovery(struct rpc_bdev_nvme_start_mdns_discovery *req)
2425 {
2426 	free(req->name);
2427 	free(req->svcname);
2428 	free(req->hostnqn);
2429 }
2430 
2431 static const struct spdk_json_object_decoder rpc_bdev_nvme_start_mdns_discovery_decoders[] = {
2432 	{"name", offsetof(struct rpc_bdev_nvme_start_mdns_discovery, name), spdk_json_decode_string},
2433 	{"svcname", offsetof(struct rpc_bdev_nvme_start_mdns_discovery, svcname), spdk_json_decode_string},
2434 	{"hostnqn", offsetof(struct rpc_bdev_nvme_start_mdns_discovery, hostnqn), spdk_json_decode_string, true},
2435 };
2436 
2437 struct rpc_bdev_nvme_start_mdns_discovery_ctx {
2438 	struct rpc_bdev_nvme_start_mdns_discovery req;
2439 	struct spdk_jsonrpc_request *request;
2440 };
2441 
2442 static void
2443 rpc_bdev_nvme_start_mdns_discovery(struct spdk_jsonrpc_request *request,
2444 				   const struct spdk_json_val *params)
2445 {
2446 	struct rpc_bdev_nvme_start_mdns_discovery_ctx *ctx;
2447 	int rc;
2448 
2449 	ctx = calloc(1, sizeof(*ctx));
2450 	if (!ctx) {
2451 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
2452 		return;
2453 	}
2454 
2455 	spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->req.opts, sizeof(ctx->req.opts));
2456 
2457 	if (spdk_json_decode_object(params, rpc_bdev_nvme_start_mdns_discovery_decoders,
2458 				    SPDK_COUNTOF(rpc_bdev_nvme_start_mdns_discovery_decoders),
2459 				    &ctx->req)) {
2460 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
2461 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2462 						 "spdk_json_decode_object failed");
2463 		goto cleanup;
2464 	}
2465 
2466 	if (ctx->req.hostnqn) {
2467 		snprintf(ctx->req.opts.hostnqn, sizeof(ctx->req.opts.hostnqn), "%s",
2468 			 ctx->req.hostnqn);
2469 	}
2470 	ctx->request = request;
2471 	rc = bdev_nvme_start_mdns_discovery(ctx->req.name, ctx->req.svcname, &ctx->req.opts,
2472 					    &ctx->req.bdev_opts);
2473 	if (rc) {
2474 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
2475 	} else {
2476 		spdk_jsonrpc_send_bool_response(request, true);
2477 	}
2478 
2479 cleanup:
2480 	free_rpc_bdev_nvme_start_mdns_discovery(&ctx->req);
2481 	free(ctx);
2482 }
2483 SPDK_RPC_REGISTER("bdev_nvme_start_mdns_discovery", rpc_bdev_nvme_start_mdns_discovery,
2484 		  SPDK_RPC_RUNTIME)
2485 
2486 struct rpc_bdev_nvme_stop_mdns_discovery {
2487 	char *name;
2488 };
2489 
2490 static const struct spdk_json_object_decoder rpc_bdev_nvme_stop_mdns_discovery_decoders[] = {
2491 	{"name", offsetof(struct rpc_bdev_nvme_stop_mdns_discovery, name), spdk_json_decode_string},
2492 };
2493 
2494 struct rpc_bdev_nvme_stop_mdns_discovery_ctx {
2495 	struct rpc_bdev_nvme_stop_mdns_discovery req;
2496 	struct spdk_jsonrpc_request *request;
2497 };
2498 
2499 static void
2500 rpc_bdev_nvme_stop_mdns_discovery(struct spdk_jsonrpc_request *request,
2501 				  const struct spdk_json_val *params)
2502 {
2503 	struct rpc_bdev_nvme_stop_mdns_discovery_ctx *ctx;
2504 	int rc;
2505 
2506 	ctx = calloc(1, sizeof(*ctx));
2507 	if (!ctx) {
2508 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
2509 		return;
2510 	}
2511 
2512 	if (spdk_json_decode_object(params, rpc_bdev_nvme_stop_mdns_discovery_decoders,
2513 				    SPDK_COUNTOF(rpc_bdev_nvme_stop_mdns_discovery_decoders),
2514 				    &ctx->req)) {
2515 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
2516 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2517 						 "spdk_json_decode_object failed");
2518 		goto cleanup;
2519 	}
2520 
2521 	ctx->request = request;
2522 	rc = bdev_nvme_stop_mdns_discovery(ctx->req.name);
2523 
2524 	if (rc) {
2525 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
2526 		goto cleanup;
2527 	}
2528 	spdk_jsonrpc_send_bool_response(ctx->request, true);
2529 
2530 cleanup:
2531 	free(ctx->req.name);
2532 	free(ctx);
2533 }
2534 SPDK_RPC_REGISTER("bdev_nvme_stop_mdns_discovery", rpc_bdev_nvme_stop_mdns_discovery,
2535 		  SPDK_RPC_RUNTIME)
2536 
2537 static void
2538 rpc_bdev_nvme_get_mdns_discovery_info(struct spdk_jsonrpc_request *request,
2539 				      const struct spdk_json_val *params)
2540 {
2541 	bdev_nvme_get_mdns_discovery_info(request);
2542 }
2543 
2544 SPDK_RPC_REGISTER("bdev_nvme_get_mdns_discovery_info", rpc_bdev_nvme_get_mdns_discovery_info,
2545 		  SPDK_RPC_RUNTIME)
2546 
2547 struct rpc_get_path_stat {
2548 	char	*name;
2549 };
2550 
2551 struct path_stat {
2552 	struct spdk_bdev_io_stat	stat;
2553 	struct spdk_nvme_transport_id	trid;
2554 	struct nvme_ns			*ns;
2555 };
2556 
2557 struct rpc_bdev_nvme_path_stat_ctx {
2558 	struct spdk_jsonrpc_request	*request;
2559 	struct path_stat		*path_stat;
2560 	uint32_t			num_paths;
2561 	struct spdk_bdev_desc		*desc;
2562 };
2563 
2564 static void
2565 free_rpc_get_path_stat(struct rpc_get_path_stat *req)
2566 {
2567 	free(req->name);
2568 }
2569 
2570 static const struct spdk_json_object_decoder rpc_get_path_stat_decoders[] = {
2571 	{"name", offsetof(struct rpc_get_path_stat, name), spdk_json_decode_string},
2572 };
2573 
2574 static void
2575 dummy_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx)
2576 {
2577 }
2578 
2579 static void
2580 rpc_bdev_nvme_path_stat_per_channel(struct nvme_bdev_channel_iter *i,
2581 				    struct nvme_bdev *nbdev,
2582 				    struct nvme_bdev_channel *nbdev_ch,
2583 				    void *_ctx)
2584 {
2585 	struct rpc_bdev_nvme_path_stat_ctx *ctx = _ctx;
2586 	struct nvme_io_path *io_path;
2587 	struct path_stat *path_stat;
2588 	uint32_t j;
2589 
2590 	assert(ctx->num_paths != 0);
2591 
2592 	for (j = 0; j < ctx->num_paths; j++) {
2593 		path_stat = &ctx->path_stat[j];
2594 
2595 		STAILQ_FOREACH(io_path, &nbdev_ch->io_path_list, stailq) {
2596 			if (path_stat->ns == io_path->nvme_ns) {
2597 				assert(io_path->stat != NULL);
2598 				spdk_bdev_add_io_stat(&path_stat->stat, io_path->stat);
2599 			}
2600 		}
2601 	}
2602 
2603 	nvme_bdev_for_each_channel_continue(i, 0);
2604 }
2605 
2606 static void
2607 rpc_bdev_nvme_path_stat_done(struct nvme_bdev *nbdev, void *_ctx, int status)
2608 {
2609 	struct rpc_bdev_nvme_path_stat_ctx *ctx = _ctx;
2610 	struct spdk_json_write_ctx *w;
2611 	struct path_stat *path_stat;
2612 	uint32_t j;
2613 
2614 	assert(ctx->num_paths != 0);
2615 
2616 	w = spdk_jsonrpc_begin_result(ctx->request);
2617 	spdk_json_write_object_begin(w);
2618 	spdk_json_write_named_string(w, "name", nbdev->disk.name);
2619 	spdk_json_write_named_array_begin(w, "stats");
2620 
2621 	for (j = 0; j < ctx->num_paths; j++) {
2622 		path_stat = &ctx->path_stat[j];
2623 		spdk_json_write_object_begin(w);
2624 
2625 		spdk_json_write_named_object_begin(w, "trid");
2626 		nvme_bdev_dump_trid_json(&path_stat->trid, w);
2627 		spdk_json_write_object_end(w);
2628 
2629 		spdk_json_write_named_object_begin(w, "stat");
2630 		spdk_bdev_dump_io_stat_json(&path_stat->stat, w);
2631 		spdk_json_write_object_end(w);
2632 
2633 		spdk_json_write_object_end(w);
2634 	}
2635 
2636 	spdk_json_write_array_end(w);
2637 	spdk_json_write_object_end(w);
2638 	spdk_jsonrpc_end_result(ctx->request, w);
2639 
2640 	spdk_bdev_close(ctx->desc);
2641 	free(ctx->path_stat);
2642 	free(ctx);
2643 }
2644 
2645 static void
2646 rpc_bdev_nvme_get_path_iostat(struct spdk_jsonrpc_request *request,
2647 			      const struct spdk_json_val *params)
2648 {
2649 	struct rpc_get_path_stat req = {};
2650 	struct spdk_bdev_desc *desc = NULL;
2651 	struct spdk_bdev *bdev;
2652 	struct nvme_bdev *nbdev;
2653 	struct nvme_ns *nvme_ns;
2654 	struct path_stat *path_stat;
2655 	struct rpc_bdev_nvme_path_stat_ctx *ctx;
2656 	struct spdk_bdev_nvme_opts opts;
2657 	uint32_t num_paths = 0, i = 0;
2658 	int rc;
2659 
2660 	bdev_nvme_get_opts(&opts);
2661 	if (!opts.io_path_stat) {
2662 		SPDK_ERRLOG("RPC not enabled if enable_io_path_stat is false\n");
2663 		spdk_jsonrpc_send_error_response(request, -EPERM,
2664 						 "RPC not enabled if enable_io_path_stat is false");
2665 		return;
2666 	}
2667 
2668 	if (spdk_json_decode_object(params, rpc_get_path_stat_decoders,
2669 				    SPDK_COUNTOF(rpc_get_path_stat_decoders),
2670 				    &req)) {
2671 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
2672 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2673 						 "spdk_json_decode_object failed");
2674 		free_rpc_get_path_stat(&req);
2675 		return;
2676 	}
2677 
2678 	rc = spdk_bdev_open_ext(req.name, false, dummy_bdev_event_cb, NULL, &desc);
2679 	if (rc != 0) {
2680 		SPDK_ERRLOG("Failed to open bdev '%s': %d\n", req.name, rc);
2681 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
2682 		free_rpc_get_path_stat(&req);
2683 		return;
2684 	}
2685 
2686 	free_rpc_get_path_stat(&req);
2687 
2688 	ctx = calloc(1, sizeof(struct rpc_bdev_nvme_path_stat_ctx));
2689 	if (ctx == NULL) {
2690 		spdk_bdev_close(desc);
2691 		SPDK_ERRLOG("Failed to allocate rpc_bdev_nvme_path_stat_ctx struct\n");
2692 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
2693 		return;
2694 	}
2695 
2696 	bdev = spdk_bdev_desc_get_bdev(desc);
2697 	nbdev = bdev->ctxt;
2698 
2699 	pthread_mutex_lock(&nbdev->mutex);
2700 	if (nbdev->ref == 0) {
2701 		rc = -ENOENT;
2702 		goto err;
2703 	}
2704 
2705 	num_paths = nbdev->ref;
2706 	path_stat = calloc(num_paths, sizeof(struct path_stat));
2707 	if (path_stat == NULL) {
2708 		rc = -ENOMEM;
2709 		SPDK_ERRLOG("Failed to allocate memory for path_stat.\n");
2710 		goto err;
2711 	}
2712 
2713 	/* store the history stat */
2714 	TAILQ_FOREACH(nvme_ns, &nbdev->nvme_ns_list, tailq) {
2715 		assert(i < num_paths);
2716 		path_stat[i].ns = nvme_ns;
2717 		path_stat[i].trid = nvme_ns->ctrlr->active_path_id->trid;
2718 
2719 		assert(nvme_ns->stat != NULL);
2720 		memcpy(&path_stat[i].stat, nvme_ns->stat, sizeof(struct spdk_bdev_io_stat));
2721 		i++;
2722 	}
2723 	pthread_mutex_unlock(&nbdev->mutex);
2724 
2725 	ctx->request = request;
2726 	ctx->desc = desc;
2727 	ctx->path_stat = path_stat;
2728 	ctx->num_paths = num_paths;
2729 
2730 	nvme_bdev_for_each_channel(nbdev,
2731 				   rpc_bdev_nvme_path_stat_per_channel,
2732 				   ctx,
2733 				   rpc_bdev_nvme_path_stat_done);
2734 	return;
2735 
2736 err:
2737 	pthread_mutex_unlock(&nbdev->mutex);
2738 	spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
2739 	spdk_bdev_close(desc);
2740 	free(ctx);
2741 }
2742 SPDK_RPC_REGISTER("bdev_nvme_get_path_iostat", rpc_bdev_nvme_get_path_iostat,
2743 		  SPDK_RPC_RUNTIME)
2744 
2745 struct rpc_bdev_nvme_set_keys {
2746 	char *name;
2747 	char *dhchap_key;
2748 	char *dhchap_ctrlr_key;
2749 };
2750 
2751 static const struct spdk_json_object_decoder rpc_bdev_nvme_set_keys_decoders[] = {
2752 	{"name", offsetof(struct rpc_bdev_nvme_set_keys, name), spdk_json_decode_string},
2753 	{"dhchap_key", offsetof(struct rpc_bdev_nvme_set_keys, dhchap_key), spdk_json_decode_string, true},
2754 	{"dhchap_ctrlr_key", offsetof(struct rpc_bdev_nvme_set_keys, dhchap_ctrlr_key), spdk_json_decode_string, true},
2755 };
2756 
2757 static void
2758 free_rpc_bdev_nvme_set_keys(struct rpc_bdev_nvme_set_keys *req)
2759 {
2760 	free(req->name);
2761 	free(req->dhchap_key);
2762 	free(req->dhchap_ctrlr_key);
2763 }
2764 
2765 static void
2766 rpc_bdev_nvme_set_keys_done(void *ctx, int status)
2767 {
2768 	struct spdk_jsonrpc_request *request = ctx;
2769 
2770 	if (status != 0) {
2771 		spdk_jsonrpc_send_error_response(request, status, spdk_strerror(-status));
2772 	} else {
2773 		spdk_jsonrpc_send_bool_response(request, true);
2774 	}
2775 }
2776 
2777 static void
2778 rpc_bdev_nvme_set_keys(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
2779 {
2780 	struct rpc_bdev_nvme_set_keys req = {};
2781 	int rc;
2782 
2783 	if (spdk_json_decode_object(params, rpc_bdev_nvme_set_keys_decoders,
2784 				    SPDK_COUNTOF(rpc_bdev_nvme_set_keys_decoders), &req)) {
2785 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
2786 						 "spdk_json_decode_object failed");
2787 		return;
2788 	}
2789 
2790 	rc = bdev_nvme_set_keys(req.name, req.dhchap_key, req.dhchap_ctrlr_key,
2791 				rpc_bdev_nvme_set_keys_done, request);
2792 	if (rc != 0) {
2793 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
2794 	}
2795 	free_rpc_bdev_nvme_set_keys(&req);
2796 }
2797 SPDK_RPC_REGISTER("bdev_nvme_set_keys", rpc_bdev_nvme_set_keys, SPDK_RPC_RUNTIME)
2798