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