xref: /spdk/module/bdev/nvme/bdev_nvme_rpc.c (revision d7f0a1820eb52bfce7ca511df55ddc0ca9dffab8)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation. All rights reserved.
5  *   Copyright (c) 2019-2021 Mellanox Technologies LTD. All rights reserved.
6  *   Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
7  *
8  *   Redistribution and use in source and binary forms, with or without
9  *   modification, are permitted provided that the following conditions
10  *   are met:
11  *
12  *     * Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *     * Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in
16  *       the documentation and/or other materials provided with the
17  *       distribution.
18  *     * Neither the name of Intel Corporation nor the names of its
19  *       contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "spdk/stdinc.h"
36 
37 #include "bdev_nvme.h"
38 
39 #include "spdk/config.h"
40 
41 #include "spdk/string.h"
42 #include "spdk/rpc.h"
43 #include "spdk/util.h"
44 #include "spdk/env.h"
45 #include "spdk/nvme.h"
46 #include "spdk/nvme_spec.h"
47 
48 #include "spdk/log.h"
49 #include "spdk/bdev_module.h"
50 
51 struct open_descriptors {
52 	void *desc;
53 	struct  spdk_bdev *bdev;
54 	TAILQ_ENTRY(open_descriptors) tqlst;
55 	struct spdk_thread *thread;
56 };
57 typedef TAILQ_HEAD(, open_descriptors) open_descriptors_t;
58 
59 static int
60 rpc_decode_action_on_timeout(const struct spdk_json_val *val, void *out)
61 {
62 	enum spdk_bdev_timeout_action *action = out;
63 
64 	if (spdk_json_strequal(val, "none") == true) {
65 		*action = SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE;
66 	} else if (spdk_json_strequal(val, "abort") == true) {
67 		*action = SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT;
68 	} else if (spdk_json_strequal(val, "reset") == true) {
69 		*action = SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET;
70 	} else {
71 		SPDK_NOTICELOG("Invalid parameter value: action_on_timeout\n");
72 		return -EINVAL;
73 	}
74 
75 	return 0;
76 }
77 
78 static const struct spdk_json_object_decoder rpc_bdev_nvme_options_decoders[] = {
79 	{"action_on_timeout", offsetof(struct spdk_bdev_nvme_opts, action_on_timeout), rpc_decode_action_on_timeout, true},
80 	{"timeout_us", offsetof(struct spdk_bdev_nvme_opts, timeout_us), spdk_json_decode_uint64, true},
81 	{"timeout_admin_us", offsetof(struct spdk_bdev_nvme_opts, timeout_admin_us), spdk_json_decode_uint64, true},
82 	{"keep_alive_timeout_ms", offsetof(struct spdk_bdev_nvme_opts, keep_alive_timeout_ms), spdk_json_decode_uint32, true},
83 	{"retry_count", offsetof(struct spdk_bdev_nvme_opts, transport_retry_count), spdk_json_decode_uint32, true},
84 	{"arbitration_burst", offsetof(struct spdk_bdev_nvme_opts, arbitration_burst), spdk_json_decode_uint32, true},
85 	{"low_priority_weight", offsetof(struct spdk_bdev_nvme_opts, low_priority_weight), spdk_json_decode_uint32, true},
86 	{"medium_priority_weight", offsetof(struct spdk_bdev_nvme_opts, medium_priority_weight), spdk_json_decode_uint32, true},
87 	{"high_priority_weight", offsetof(struct spdk_bdev_nvme_opts, high_priority_weight), spdk_json_decode_uint32, true},
88 	{"nvme_adminq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_adminq_poll_period_us), spdk_json_decode_uint64, true},
89 	{"nvme_ioq_poll_period_us", offsetof(struct spdk_bdev_nvme_opts, nvme_ioq_poll_period_us), spdk_json_decode_uint64, true},
90 	{"io_queue_requests", offsetof(struct spdk_bdev_nvme_opts, io_queue_requests), spdk_json_decode_uint32, true},
91 	{"delay_cmd_submit", offsetof(struct spdk_bdev_nvme_opts, delay_cmd_submit), spdk_json_decode_bool, true},
92 	{"transport_retry_count", offsetof(struct spdk_bdev_nvme_opts, transport_retry_count), spdk_json_decode_uint32, true},
93 	{"bdev_retry_count", offsetof(struct spdk_bdev_nvme_opts, bdev_retry_count), spdk_json_decode_int32, true},
94 	{"transport_ack_timeout", offsetof(struct spdk_bdev_nvme_opts, transport_ack_timeout), spdk_json_decode_uint8, true},
95 	{"ctrlr_loss_timeout_sec", offsetof(struct spdk_bdev_nvme_opts, ctrlr_loss_timeout_sec), spdk_json_decode_int32, true},
96 	{"reconnect_delay_sec", offsetof(struct spdk_bdev_nvme_opts, reconnect_delay_sec), spdk_json_decode_uint32, true},
97 	{"fast_io_fail_timeout_sec", offsetof(struct spdk_bdev_nvme_opts, fast_io_fail_timeout_sec), spdk_json_decode_uint32, true},
98 };
99 
100 static void
101 rpc_bdev_nvme_set_options(struct spdk_jsonrpc_request *request,
102 			  const struct spdk_json_val *params)
103 {
104 	struct spdk_bdev_nvme_opts opts;
105 	int rc;
106 
107 	bdev_nvme_get_opts(&opts);
108 	if (params && spdk_json_decode_object(params, rpc_bdev_nvme_options_decoders,
109 					      SPDK_COUNTOF(rpc_bdev_nvme_options_decoders),
110 					      &opts)) {
111 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
112 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
113 						 "spdk_json_decode_object failed");
114 		return;
115 	}
116 
117 	rc = bdev_nvme_set_opts(&opts);
118 	if (rc) {
119 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
120 		return;
121 	}
122 
123 	spdk_jsonrpc_send_bool_response(request, true);
124 
125 	return;
126 }
127 SPDK_RPC_REGISTER("bdev_nvme_set_options", rpc_bdev_nvme_set_options,
128 		  SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME)
129 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_set_options, set_bdev_nvme_options)
130 
131 struct rpc_bdev_nvme_hotplug {
132 	bool enabled;
133 	uint64_t period_us;
134 };
135 
136 static const struct spdk_json_object_decoder rpc_bdev_nvme_hotplug_decoders[] = {
137 	{"enable", offsetof(struct rpc_bdev_nvme_hotplug, enabled), spdk_json_decode_bool, false},
138 	{"period_us", offsetof(struct rpc_bdev_nvme_hotplug, period_us), spdk_json_decode_uint64, true},
139 };
140 
141 static void
142 rpc_bdev_nvme_set_hotplug_done(void *ctx)
143 {
144 	struct spdk_jsonrpc_request *request = ctx;
145 
146 	spdk_jsonrpc_send_bool_response(request, true);
147 }
148 
149 static void
150 rpc_bdev_nvme_set_hotplug(struct spdk_jsonrpc_request *request,
151 			  const struct spdk_json_val *params)
152 {
153 	struct rpc_bdev_nvme_hotplug req = {false, 0};
154 	int rc;
155 
156 	if (spdk_json_decode_object(params, rpc_bdev_nvme_hotplug_decoders,
157 				    SPDK_COUNTOF(rpc_bdev_nvme_hotplug_decoders), &req)) {
158 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
159 		rc = -EINVAL;
160 		goto invalid;
161 	}
162 
163 	rc = bdev_nvme_set_hotplug(req.enabled, req.period_us, rpc_bdev_nvme_set_hotplug_done,
164 				   request);
165 	if (rc) {
166 		goto invalid;
167 	}
168 
169 	return;
170 invalid:
171 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc));
172 }
173 SPDK_RPC_REGISTER("bdev_nvme_set_hotplug", rpc_bdev_nvme_set_hotplug, SPDK_RPC_RUNTIME)
174 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_set_hotplug, set_bdev_nvme_hotplug)
175 
176 struct rpc_bdev_nvme_attach_controller {
177 	char *name;
178 	char *trtype;
179 	char *adrfam;
180 	char *traddr;
181 	char *trsvcid;
182 	char *priority;
183 	char *subnqn;
184 	char *hostnqn;
185 	char *hostaddr;
186 	char *hostsvcid;
187 	char *multipath;
188 	struct nvme_ctrlr_opts bdev_opts;
189 	struct spdk_nvme_ctrlr_opts drv_opts;
190 };
191 
192 static void
193 free_rpc_bdev_nvme_attach_controller(struct rpc_bdev_nvme_attach_controller *req)
194 {
195 	free(req->name);
196 	free(req->trtype);
197 	free(req->adrfam);
198 	free(req->traddr);
199 	free(req->trsvcid);
200 	free(req->priority);
201 	free(req->subnqn);
202 	free(req->hostnqn);
203 	free(req->hostaddr);
204 	free(req->hostsvcid);
205 	free(req->multipath);
206 }
207 
208 static int
209 bdev_nvme_decode_reftag(const struct spdk_json_val *val, void *out)
210 {
211 	uint32_t *flag = out;
212 	bool reftag;
213 	int rc;
214 
215 	rc = spdk_json_decode_bool(val, &reftag);
216 	if (rc == 0 && reftag == true) {
217 		*flag |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG;
218 	}
219 
220 	return rc;
221 }
222 
223 static int
224 bdev_nvme_decode_guard(const struct spdk_json_val *val, void *out)
225 {
226 	uint32_t *flag = out;
227 	bool guard;
228 	int rc;
229 
230 	rc = spdk_json_decode_bool(val, &guard);
231 	if (rc == 0 && guard == true) {
232 		*flag |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD;
233 	}
234 
235 	return rc;
236 }
237 
238 static const struct spdk_json_object_decoder rpc_bdev_nvme_attach_controller_decoders[] = {
239 	{"name", offsetof(struct rpc_bdev_nvme_attach_controller, name), spdk_json_decode_string},
240 	{"trtype", offsetof(struct rpc_bdev_nvme_attach_controller, trtype), spdk_json_decode_string},
241 	{"traddr", offsetof(struct rpc_bdev_nvme_attach_controller, traddr), spdk_json_decode_string},
242 
243 	{"adrfam", offsetof(struct rpc_bdev_nvme_attach_controller, adrfam), spdk_json_decode_string, true},
244 	{"trsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, trsvcid), spdk_json_decode_string, true},
245 	{"priority", offsetof(struct rpc_bdev_nvme_attach_controller, priority), spdk_json_decode_string, true},
246 	{"subnqn", offsetof(struct rpc_bdev_nvme_attach_controller, subnqn), spdk_json_decode_string, true},
247 	{"hostnqn", offsetof(struct rpc_bdev_nvme_attach_controller, hostnqn), spdk_json_decode_string, true},
248 	{"hostaddr", offsetof(struct rpc_bdev_nvme_attach_controller, hostaddr), spdk_json_decode_string, true},
249 	{"hostsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, hostsvcid), spdk_json_decode_string, true},
250 
251 	{"prchk_reftag", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.prchk_flags), bdev_nvme_decode_reftag, true},
252 	{"prchk_guard", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.prchk_flags), bdev_nvme_decode_guard, true},
253 	{"hdgst", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.header_digest), spdk_json_decode_bool, true},
254 	{"ddgst", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.data_digest), spdk_json_decode_bool, true},
255 	{"fabrics_connect_timeout_us", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.fabrics_connect_timeout_us), spdk_json_decode_uint64, true},
256 	{"multipath", offsetof(struct rpc_bdev_nvme_attach_controller, multipath), spdk_json_decode_string, true},
257 	{"num_io_queues", offsetof(struct rpc_bdev_nvme_attach_controller, drv_opts.num_io_queues), spdk_json_decode_uint32, true},
258 	{"ctrlr_loss_timeout_sec", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.ctrlr_loss_timeout_sec), spdk_json_decode_int32, true},
259 	{"reconnect_delay_sec", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.reconnect_delay_sec), spdk_json_decode_uint32, true},
260 	{"fast_io_fail_timeout_sec", offsetof(struct rpc_bdev_nvme_attach_controller, bdev_opts.fast_io_fail_timeout_sec), spdk_json_decode_uint32, true},
261 };
262 
263 #define NVME_MAX_BDEVS_PER_RPC 128
264 
265 struct rpc_bdev_nvme_attach_controller_ctx {
266 	struct rpc_bdev_nvme_attach_controller req;
267 	uint32_t count;
268 	size_t bdev_count;
269 	const char *names[NVME_MAX_BDEVS_PER_RPC];
270 	struct spdk_jsonrpc_request *request;
271 };
272 
273 static void
274 rpc_bdev_nvme_attach_controller_examined(void *cb_ctx)
275 {
276 	struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx;
277 	struct spdk_jsonrpc_request *request = ctx->request;
278 	struct spdk_json_write_ctx *w;
279 	size_t i;
280 
281 	w = spdk_jsonrpc_begin_result(request);
282 	spdk_json_write_array_begin(w);
283 	for (i = 0; i < ctx->bdev_count; i++) {
284 		spdk_json_write_string(w, ctx->names[i]);
285 	}
286 	spdk_json_write_array_end(w);
287 	spdk_jsonrpc_end_result(request, w);
288 
289 	free_rpc_bdev_nvme_attach_controller(&ctx->req);
290 	free(ctx);
291 }
292 
293 static void
294 rpc_bdev_nvme_attach_controller_done(void *cb_ctx, size_t bdev_count, int rc)
295 {
296 	struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx;
297 	struct spdk_jsonrpc_request *request = ctx->request;
298 
299 	if (rc < 0) {
300 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
301 		free_rpc_bdev_nvme_attach_controller(&ctx->req);
302 		free(ctx);
303 		return;
304 	}
305 
306 	ctx->bdev_count = bdev_count;
307 	spdk_bdev_wait_for_examine(rpc_bdev_nvme_attach_controller_examined, ctx);
308 }
309 
310 static void
311 rpc_bdev_nvme_attach_controller(struct spdk_jsonrpc_request *request,
312 				const struct spdk_json_val *params)
313 {
314 	struct rpc_bdev_nvme_attach_controller_ctx *ctx;
315 	struct spdk_nvme_transport_id trid = {};
316 	const struct spdk_nvme_ctrlr_opts *drv_opts;
317 	const struct spdk_nvme_transport_id *ctrlr_trid;
318 	struct nvme_ctrlr *ctrlr = NULL;
319 	size_t len, maxlen;
320 	bool multipath = false;
321 	int rc;
322 
323 	ctx = calloc(1, sizeof(*ctx));
324 	if (!ctx) {
325 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
326 		return;
327 	}
328 
329 	spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->req.drv_opts, sizeof(ctx->req.drv_opts));
330 	bdev_nvme_get_default_ctrlr_opts(&ctx->req.bdev_opts);
331 
332 	if (spdk_json_decode_object(params, rpc_bdev_nvme_attach_controller_decoders,
333 				    SPDK_COUNTOF(rpc_bdev_nvme_attach_controller_decoders),
334 				    &ctx->req)) {
335 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
336 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
337 						 "spdk_json_decode_object failed");
338 		goto cleanup;
339 	}
340 
341 	/* Parse trstring */
342 	rc = spdk_nvme_transport_id_populate_trstring(&trid, ctx->req.trtype);
343 	if (rc < 0) {
344 		SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype);
345 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s",
346 						     ctx->req.trtype);
347 		goto cleanup;
348 	}
349 
350 	/* Parse trtype */
351 	rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype);
352 	assert(rc == 0);
353 
354 	/* Parse traddr */
355 	maxlen = sizeof(trid.traddr);
356 	len = strnlen(ctx->req.traddr, maxlen);
357 	if (len == maxlen) {
358 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s",
359 						     ctx->req.traddr);
360 		goto cleanup;
361 	}
362 	memcpy(trid.traddr, ctx->req.traddr, len + 1);
363 
364 	/* Parse adrfam */
365 	if (ctx->req.adrfam) {
366 		rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam);
367 		if (rc < 0) {
368 			SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam);
369 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s",
370 							     ctx->req.adrfam);
371 			goto cleanup;
372 		}
373 	}
374 
375 	/* Parse trsvcid */
376 	if (ctx->req.trsvcid) {
377 		maxlen = sizeof(trid.trsvcid);
378 		len = strnlen(ctx->req.trsvcid, maxlen);
379 		if (len == maxlen) {
380 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s",
381 							     ctx->req.trsvcid);
382 			goto cleanup;
383 		}
384 		memcpy(trid.trsvcid, ctx->req.trsvcid, len + 1);
385 	}
386 
387 	/* Parse priority for the NVMe-oF transport connection */
388 	if (ctx->req.priority) {
389 		trid.priority = spdk_strtol(ctx->req.priority, 10);
390 	}
391 
392 	/* Parse subnqn */
393 	if (ctx->req.subnqn) {
394 		maxlen = sizeof(trid.subnqn);
395 		len = strnlen(ctx->req.subnqn, maxlen);
396 		if (len == maxlen) {
397 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s",
398 							     ctx->req.subnqn);
399 			goto cleanup;
400 		}
401 		memcpy(trid.subnqn, ctx->req.subnqn, len + 1);
402 	}
403 
404 	if (ctx->req.hostnqn) {
405 		snprintf(ctx->req.drv_opts.hostnqn, sizeof(ctx->req.drv_opts.hostnqn), "%s",
406 			 ctx->req.hostnqn);
407 	}
408 
409 	if (ctx->req.hostaddr) {
410 		maxlen = sizeof(ctx->req.drv_opts.src_addr);
411 		len = strnlen(ctx->req.hostaddr, maxlen);
412 		if (len == maxlen) {
413 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostaddr too long: %s",
414 							     ctx->req.hostaddr);
415 			goto cleanup;
416 		}
417 		snprintf(ctx->req.drv_opts.src_addr, maxlen, "%s", ctx->req.hostaddr);
418 	}
419 
420 	if (ctx->req.hostsvcid) {
421 		maxlen = sizeof(ctx->req.drv_opts.src_svcid);
422 		len = strnlen(ctx->req.hostsvcid, maxlen);
423 		if (len == maxlen) {
424 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostsvcid too long: %s",
425 							     ctx->req.hostsvcid);
426 			goto cleanup;
427 		}
428 		snprintf(ctx->req.drv_opts.src_svcid, maxlen, "%s", ctx->req.hostsvcid);
429 	}
430 
431 	ctrlr = nvme_ctrlr_get_by_name(ctx->req.name);
432 
433 	if (ctrlr) {
434 		if (ctx->req.multipath == NULL) {
435 			/* For now, this means add a failover path. This maintains backward compatibility
436 			 * with past behavior. In the future, this behavior will change to "disable". */
437 			SPDK_ERRLOG("The multipath parameter was not specified to bdev_nvme_attach_controller but "
438 				    "it was used to add a failover path. This behavior will default to rejecting "
439 				    "the request in the future. Specify the 'multipath' parameter to control the behavior\n");
440 			ctx->req.multipath = strdup("failover");
441 			if (ctx->req.multipath == NULL) {
442 				SPDK_ERRLOG("cannot allocate multipath failover string\n");
443 				goto cleanup;
444 			}
445 		}
446 
447 		drv_opts = spdk_nvme_ctrlr_get_opts(ctrlr->ctrlr);
448 		ctrlr_trid = spdk_nvme_ctrlr_get_transport_id(ctrlr->ctrlr);
449 
450 		/* This controller already exists. Check what the user wants to do. */
451 		if (strcasecmp(ctx->req.multipath, "disable") == 0) {
452 			/* The user does not want to do any form of multipathing. */
453 			spdk_jsonrpc_send_error_response_fmt(request, -EALREADY,
454 							     "A controller named %s already exists and multipath is disabled\n",
455 							     ctx->req.name);
456 			goto cleanup;
457 		} else if (strcasecmp(ctx->req.multipath, "failover") == 0 ||
458 			   strcasecmp(ctx->req.multipath, "multipath") == 0) {
459 			/* The user wants to add this as a failover path or add this to create multipath. */
460 
461 			if (strncmp(trid.traddr, ctrlr_trid->traddr, sizeof(trid.traddr)) == 0 &&
462 			    strncmp(trid.trsvcid, ctrlr_trid->trsvcid, sizeof(trid.trsvcid)) == 0 &&
463 			    strncmp(ctx->req.drv_opts.src_addr, drv_opts->src_addr, sizeof(drv_opts->src_addr)) == 0 &&
464 			    strncmp(ctx->req.drv_opts.src_svcid, drv_opts->src_svcid, sizeof(drv_opts->src_svcid)) == 0) {
465 				/* Exactly same network path can't be added a second time */
466 				spdk_jsonrpc_send_error_response_fmt(request, -EALREADY,
467 								     "A controller named %s already exists with the specified network path\n",
468 								     ctx->req.name);
469 				goto cleanup;
470 			}
471 		} else {
472 			/* Invalid multipath option */
473 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL,
474 							     "Invalid multipath parameter: %s\n",
475 							     ctx->req.multipath);
476 			goto cleanup;
477 		}
478 
479 		if (strncmp(trid.subnqn,
480 			    ctrlr_trid->subnqn,
481 			    SPDK_NVMF_NQN_MAX_LEN) != 0) {
482 			/* Different SUBNQN is not allowed when specifying the same controller name. */
483 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL,
484 							     "A controller named %s already exists, but uses a different subnqn (%s)\n",
485 							     ctx->req.name, ctrlr_trid->subnqn);
486 			goto cleanup;
487 		}
488 
489 
490 
491 		if (strncmp(ctx->req.drv_opts.hostnqn, drv_opts->hostnqn, SPDK_NVMF_NQN_MAX_LEN) != 0) {
492 			/* Different HOSTNQN is not allowed when specifying the same controller name. */
493 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL,
494 							     "A controller named %s already exists, but uses a different hostnqn (%s)\n",
495 							     ctx->req.name, drv_opts->hostnqn);
496 			goto cleanup;
497 		}
498 
499 		if (ctx->req.bdev_opts.prchk_flags) {
500 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL,
501 							     "A controller named %s already exists. To add a path, do not specify PI options.\n",
502 							     ctx->req.name);
503 			goto cleanup;
504 		}
505 	}
506 
507 	if (ctx->req.multipath != NULL && strcasecmp(ctx->req.multipath, "multipath") == 0) {
508 		multipath = true;
509 	}
510 
511 	if (ctx->req.drv_opts.num_io_queues == 0 || ctx->req.drv_opts.num_io_queues > UINT16_MAX + 1) {
512 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL,
513 						     "num_io_queues out of bounds, min: %u max: %u\n",
514 						     1, UINT16_MAX + 1);
515 		goto cleanup;
516 	}
517 
518 	ctx->request = request;
519 	ctx->count = NVME_MAX_BDEVS_PER_RPC;
520 	rc = bdev_nvme_create(&trid, ctx->req.name, ctx->names, ctx->count,
521 			      rpc_bdev_nvme_attach_controller_done, ctx, &ctx->req.drv_opts,
522 			      &ctx->req.bdev_opts, multipath);
523 	if (rc) {
524 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
525 		goto cleanup;
526 	}
527 
528 	return;
529 
530 cleanup:
531 	free_rpc_bdev_nvme_attach_controller(&ctx->req);
532 	free(ctx);
533 }
534 SPDK_RPC_REGISTER("bdev_nvme_attach_controller", rpc_bdev_nvme_attach_controller,
535 		  SPDK_RPC_RUNTIME)
536 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_attach_controller, construct_nvme_bdev)
537 
538 static const char *
539 nvme_ctrlr_get_state_str(struct nvme_ctrlr *nvme_ctrlr)
540 {
541 	if (nvme_ctrlr->destruct) {
542 		return "deleting";
543 	} else if (spdk_nvme_ctrlr_is_failed(nvme_ctrlr->ctrlr)) {
544 		return "failed";
545 	} else if (nvme_ctrlr->resetting) {
546 		return "resetting";
547 	} else if (nvme_ctrlr->reconnect_is_delayed > 0) {
548 		return "reconnect_is_delayed";
549 	} else {
550 		return "enabled";
551 	}
552 }
553 
554 static void
555 rpc_dump_nvme_bdev_controller_info(struct nvme_bdev_ctrlr *nbdev_ctrlr, void *ctx)
556 {
557 	struct spdk_json_write_ctx	*w = ctx;
558 	struct spdk_nvme_transport_id   *trid;
559 	struct nvme_ctrlr		*nvme_ctrlr;
560 	const struct spdk_nvme_ctrlr_opts *opts;
561 
562 	spdk_json_write_object_begin(w);
563 	spdk_json_write_named_string(w, "name", nbdev_ctrlr->name);
564 
565 	spdk_json_write_named_array_begin(w, "ctrlrs");
566 	TAILQ_FOREACH(nvme_ctrlr, &nbdev_ctrlr->ctrlrs, tailq) {
567 		spdk_json_write_object_begin(w);
568 
569 		spdk_json_write_named_string(w, "state", nvme_ctrlr_get_state_str(nvme_ctrlr));
570 
571 #ifdef SPDK_CONFIG_NVME_CUSE
572 		size_t cuse_name_size = 128;
573 		char cuse_name[cuse_name_size];
574 
575 		int rc = spdk_nvme_cuse_get_ctrlr_name(nvme_ctrlr->ctrlr, cuse_name, &cuse_name_size);
576 		if (rc == 0) {
577 			spdk_json_write_named_string(w, "cuse_device", cuse_name);
578 		}
579 #endif
580 		trid = &nvme_ctrlr->active_path_id->trid;
581 		spdk_json_write_named_object_begin(w, "trid");
582 		nvme_bdev_dump_trid_json(trid, w);
583 		spdk_json_write_object_end(w);
584 
585 		opts = spdk_nvme_ctrlr_get_opts(nvme_ctrlr->ctrlr);
586 		spdk_json_write_named_object_begin(w, "host");
587 		spdk_json_write_named_string(w, "nqn", opts->hostnqn);
588 		spdk_json_write_named_string(w, "addr", opts->src_addr);
589 		spdk_json_write_named_string(w, "svcid", opts->src_svcid);
590 		spdk_json_write_object_end(w);
591 		spdk_json_write_object_end(w);
592 	}
593 	spdk_json_write_array_end(w);
594 	spdk_json_write_object_end(w);
595 }
596 
597 struct rpc_bdev_nvme_get_controllers {
598 	char *name;
599 };
600 
601 static void
602 free_rpc_bdev_nvme_get_controllers(struct rpc_bdev_nvme_get_controllers *r)
603 {
604 	free(r->name);
605 }
606 
607 static const struct spdk_json_object_decoder rpc_bdev_nvme_get_controllers_decoders[] = {
608 	{"name", offsetof(struct rpc_bdev_nvme_get_controllers, name), spdk_json_decode_string, true},
609 };
610 
611 static void
612 rpc_bdev_nvme_get_controllers(struct spdk_jsonrpc_request *request,
613 			      const struct spdk_json_val *params)
614 {
615 	struct rpc_bdev_nvme_get_controllers req = {};
616 	struct spdk_json_write_ctx *w;
617 	struct nvme_bdev_ctrlr *nbdev_ctrlr = NULL;
618 
619 	if (params && spdk_json_decode_object(params, rpc_bdev_nvme_get_controllers_decoders,
620 					      SPDK_COUNTOF(rpc_bdev_nvme_get_controllers_decoders),
621 					      &req)) {
622 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
623 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
624 						 "spdk_json_decode_object failed");
625 		goto cleanup;
626 	}
627 
628 	if (req.name) {
629 		nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name(req.name);
630 		if (nbdev_ctrlr == NULL) {
631 			SPDK_ERRLOG("ctrlr '%s' does not exist\n", req.name);
632 			spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Controller %s does not exist", req.name);
633 			goto cleanup;
634 		}
635 	}
636 
637 	w = spdk_jsonrpc_begin_result(request);
638 	spdk_json_write_array_begin(w);
639 
640 	if (nbdev_ctrlr != NULL) {
641 		rpc_dump_nvme_bdev_controller_info(nbdev_ctrlr, w);
642 	} else {
643 		nvme_bdev_ctrlr_for_each(rpc_dump_nvme_bdev_controller_info, w);
644 	}
645 
646 	spdk_json_write_array_end(w);
647 
648 	spdk_jsonrpc_end_result(request, w);
649 
650 cleanup:
651 	free_rpc_bdev_nvme_get_controllers(&req);
652 }
653 SPDK_RPC_REGISTER("bdev_nvme_get_controllers", rpc_bdev_nvme_get_controllers, SPDK_RPC_RUNTIME)
654 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_get_controllers, get_nvme_controllers)
655 
656 struct rpc_bdev_nvme_detach_controller {
657 	char *name;
658 	char *trtype;
659 	char *adrfam;
660 	char *traddr;
661 	char *trsvcid;
662 	char *subnqn;
663 	char *hostaddr;
664 	char *hostsvcid;
665 };
666 
667 static void
668 free_rpc_bdev_nvme_detach_controller(struct rpc_bdev_nvme_detach_controller *req)
669 {
670 	free(req->name);
671 	free(req->trtype);
672 	free(req->adrfam);
673 	free(req->traddr);
674 	free(req->trsvcid);
675 	free(req->subnqn);
676 	free(req->hostaddr);
677 	free(req->hostsvcid);
678 }
679 
680 static const struct spdk_json_object_decoder rpc_bdev_nvme_detach_controller_decoders[] = {
681 	{"name", offsetof(struct rpc_bdev_nvme_detach_controller, name), spdk_json_decode_string},
682 	{"trtype", offsetof(struct rpc_bdev_nvme_detach_controller, trtype), spdk_json_decode_string, true},
683 	{"traddr", offsetof(struct rpc_bdev_nvme_detach_controller, traddr), spdk_json_decode_string, true},
684 	{"adrfam", offsetof(struct rpc_bdev_nvme_detach_controller, adrfam), spdk_json_decode_string, true},
685 	{"trsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, trsvcid), spdk_json_decode_string, true},
686 	{"subnqn", offsetof(struct rpc_bdev_nvme_detach_controller, subnqn), spdk_json_decode_string, true},
687 	{"hostaddr", offsetof(struct rpc_bdev_nvme_detach_controller, hostaddr), spdk_json_decode_string, true},
688 	{"hostsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, hostsvcid), spdk_json_decode_string, true},
689 };
690 
691 static void
692 rpc_bdev_nvme_detach_controller(struct spdk_jsonrpc_request *request,
693 				const struct spdk_json_val *params)
694 {
695 	struct rpc_bdev_nvme_detach_controller req = {NULL};
696 	struct nvme_path_id path = {};
697 	size_t len, maxlen;
698 	int rc = 0;
699 
700 	if (spdk_json_decode_object(params, rpc_bdev_nvme_detach_controller_decoders,
701 				    SPDK_COUNTOF(rpc_bdev_nvme_detach_controller_decoders),
702 				    &req)) {
703 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
704 						 "spdk_json_decode_object failed");
705 		goto cleanup;
706 	}
707 
708 	if (req.trtype != NULL) {
709 		rc = spdk_nvme_transport_id_populate_trstring(&path.trid, req.trtype);
710 		if (rc < 0) {
711 			SPDK_ERRLOG("Failed to parse trtype: %s\n", req.trtype);
712 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s",
713 							     req.trtype);
714 			goto cleanup;
715 		}
716 
717 		rc = spdk_nvme_transport_id_parse_trtype(&path.trid.trtype, req.trtype);
718 		if (rc < 0) {
719 			SPDK_ERRLOG("Failed to parse trtype: %s\n", req.trtype);
720 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s",
721 							     req.trtype);
722 			goto cleanup;
723 		}
724 	}
725 
726 	if (req.traddr != NULL) {
727 		maxlen = sizeof(path.trid.traddr);
728 		len = strnlen(req.traddr, maxlen);
729 		if (len == maxlen) {
730 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s",
731 							     req.traddr);
732 			goto cleanup;
733 		}
734 		memcpy(path.trid.traddr, req.traddr, len + 1);
735 	}
736 
737 	if (req.adrfam != NULL) {
738 		rc = spdk_nvme_transport_id_parse_adrfam(&path.trid.adrfam, req.adrfam);
739 		if (rc < 0) {
740 			SPDK_ERRLOG("Failed to parse adrfam: %s\n", req.adrfam);
741 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s",
742 							     req.adrfam);
743 			goto cleanup;
744 		}
745 	}
746 
747 	if (req.trsvcid != NULL) {
748 		maxlen = sizeof(path.trid.trsvcid);
749 		len = strnlen(req.trsvcid, maxlen);
750 		if (len == maxlen) {
751 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s",
752 							     req.trsvcid);
753 			goto cleanup;
754 		}
755 		memcpy(path.trid.trsvcid, req.trsvcid, len + 1);
756 	}
757 
758 	/* Parse subnqn */
759 	if (req.subnqn != NULL) {
760 		maxlen = sizeof(path.trid.subnqn);
761 		len = strnlen(req.subnqn, maxlen);
762 		if (len == maxlen) {
763 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s",
764 							     req.subnqn);
765 			goto cleanup;
766 		}
767 		memcpy(path.trid.subnqn, req.subnqn, len + 1);
768 	}
769 
770 	if (req.hostaddr) {
771 		maxlen = sizeof(path.hostid.hostaddr);
772 		len = strnlen(req.hostaddr, maxlen);
773 		if (len == maxlen) {
774 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostaddr too long: %s",
775 							     req.hostaddr);
776 			goto cleanup;
777 		}
778 		snprintf(path.hostid.hostaddr, maxlen, "%s", req.hostaddr);
779 	}
780 
781 	if (req.hostsvcid) {
782 		maxlen = sizeof(path.hostid.hostsvcid);
783 		len = strnlen(req.hostsvcid, maxlen);
784 		if (len == maxlen) {
785 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostsvcid too long: %s",
786 							     req.hostsvcid);
787 			goto cleanup;
788 		}
789 		snprintf(path.hostid.hostsvcid, maxlen, "%s", req.hostsvcid);
790 	}
791 
792 	rc = bdev_nvme_delete(req.name, &path);
793 
794 	if (rc != 0) {
795 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
796 		goto cleanup;
797 	}
798 
799 	spdk_jsonrpc_send_bool_response(request, true);
800 
801 cleanup:
802 	free_rpc_bdev_nvme_detach_controller(&req);
803 }
804 SPDK_RPC_REGISTER("bdev_nvme_detach_controller", rpc_bdev_nvme_detach_controller,
805 		  SPDK_RPC_RUNTIME)
806 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_detach_controller, delete_nvme_controller)
807 
808 struct rpc_apply_firmware {
809 	char *filename;
810 	char *bdev_name;
811 };
812 
813 static void
814 free_rpc_apply_firmware(struct rpc_apply_firmware *req)
815 {
816 	free(req->filename);
817 	free(req->bdev_name);
818 }
819 
820 static const struct spdk_json_object_decoder rpc_apply_firmware_decoders[] = {
821 	{"filename", offsetof(struct rpc_apply_firmware, filename), spdk_json_decode_string},
822 	{"bdev_name", offsetof(struct rpc_apply_firmware, bdev_name), spdk_json_decode_string},
823 };
824 
825 struct firmware_update_info {
826 	void				*fw_image;
827 	void				*p;
828 	unsigned int			size;
829 	unsigned int			size_remaining;
830 	unsigned int			offset;
831 	unsigned int			transfer;
832 
833 	void				*desc;
834 	struct spdk_io_channel		*ch;
835 	struct spdk_jsonrpc_request	*request;
836 	struct spdk_nvme_ctrlr		*ctrlr;
837 	open_descriptors_t		desc_head;
838 	struct rpc_apply_firmware	*req;
839 };
840 
841 static void
842 _apply_firmware_cleanup(void *ctx)
843 {
844 	struct spdk_bdev_desc *desc = ctx;
845 
846 	spdk_bdev_close(desc);
847 }
848 
849 static void
850 apply_firmware_cleanup(void *cb_arg)
851 {
852 	struct open_descriptors			*opt, *tmp;
853 	struct firmware_update_info *firm_ctx = cb_arg;
854 
855 	if (!firm_ctx) {
856 		return;
857 	}
858 
859 	if (firm_ctx->fw_image) {
860 		spdk_free(firm_ctx->fw_image);
861 	}
862 
863 	if (firm_ctx->req) {
864 		free_rpc_apply_firmware(firm_ctx->req);
865 		free(firm_ctx->req);
866 	}
867 
868 	if (firm_ctx->ch) {
869 		spdk_put_io_channel(firm_ctx->ch);
870 	}
871 
872 	TAILQ_FOREACH_SAFE(opt, &firm_ctx->desc_head, tqlst, tmp) {
873 		TAILQ_REMOVE(&firm_ctx->desc_head, opt, tqlst);
874 		/* Close the underlying bdev on its same opened thread. */
875 		if (opt->thread && opt->thread != spdk_get_thread()) {
876 			spdk_thread_send_msg(opt->thread, _apply_firmware_cleanup, opt->desc);
877 		} else {
878 			spdk_bdev_close(opt->desc);
879 		}
880 		free(opt);
881 	}
882 	free(firm_ctx);
883 }
884 
885 static void
886 apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
887 {
888 	struct spdk_json_write_ctx		*w;
889 	struct firmware_update_info *firm_ctx = cb_arg;
890 
891 	spdk_bdev_free_io(bdev_io);
892 
893 	if (!success) {
894 		spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
895 						 "firmware commit failed.");
896 		apply_firmware_cleanup(firm_ctx);
897 		return;
898 	}
899 
900 	if (spdk_nvme_ctrlr_reset(firm_ctx->ctrlr) != 0) {
901 		spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
902 						 "Controller reset failed.");
903 		apply_firmware_cleanup(firm_ctx);
904 		return;
905 	}
906 
907 	w = spdk_jsonrpc_begin_result(firm_ctx->request);
908 	spdk_json_write_string(w, "firmware commit succeeded. Controller reset in progress.");
909 	spdk_jsonrpc_end_result(firm_ctx->request, w);
910 	apply_firmware_cleanup(firm_ctx);
911 }
912 
913 static void
914 apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
915 {
916 	struct spdk_nvme_cmd			cmd = {};
917 	struct spdk_nvme_fw_commit		fw_commit;
918 	int					slot = 0;
919 	int					rc;
920 	struct firmware_update_info *firm_ctx = cb_arg;
921 	enum spdk_nvme_fw_commit_action commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG;
922 
923 	spdk_bdev_free_io(bdev_io);
924 
925 	if (!success) {
926 		spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
927 						 "firmware download failed .");
928 		apply_firmware_cleanup(firm_ctx);
929 		return;
930 	}
931 
932 	firm_ctx->p += firm_ctx->transfer;
933 	firm_ctx->offset += firm_ctx->transfer;
934 	firm_ctx->size_remaining -= firm_ctx->transfer;
935 
936 	switch (firm_ctx->size_remaining) {
937 	case 0:
938 		/* firmware download completed. Commit firmware */
939 		memset(&fw_commit, 0, sizeof(struct spdk_nvme_fw_commit));
940 		fw_commit.fs = slot;
941 		fw_commit.ca = commit_action;
942 
943 		cmd.opc = SPDK_NVME_OPC_FIRMWARE_COMMIT;
944 		memcpy(&cmd.cdw10, &fw_commit, sizeof(uint32_t));
945 		rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, NULL, 0,
946 						   apply_firmware_complete_reset, firm_ctx);
947 		if (rc) {
948 			spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
949 							 "firmware commit failed.");
950 			apply_firmware_cleanup(firm_ctx);
951 			return;
952 		}
953 		break;
954 	default:
955 		firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096);
956 		cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD;
957 
958 		cmd.cdw10 = spdk_nvme_bytes_to_numd(firm_ctx->transfer);
959 		cmd.cdw11 = firm_ctx->offset >> 2;
960 		rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, firm_ctx->p,
961 						   firm_ctx->transfer, apply_firmware_complete, firm_ctx);
962 		if (rc) {
963 			spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
964 							 "firmware download failed.");
965 			apply_firmware_cleanup(firm_ctx);
966 			return;
967 		}
968 		break;
969 	}
970 }
971 
972 static void
973 apply_firmware_open_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx)
974 {
975 }
976 
977 static void
978 rpc_bdev_nvme_apply_firmware(struct spdk_jsonrpc_request *request,
979 			     const struct spdk_json_val *params)
980 {
981 	int					rc;
982 	int					fd = -1;
983 	struct stat				fw_stat;
984 	struct spdk_nvme_ctrlr			*ctrlr;
985 	char					msg[1024];
986 	struct spdk_bdev			*bdev;
987 	struct spdk_bdev			*bdev2;
988 	struct open_descriptors			*opt;
989 	struct spdk_bdev_desc			*desc;
990 	struct spdk_nvme_cmd			*cmd;
991 	struct firmware_update_info		*firm_ctx;
992 
993 	firm_ctx = calloc(1, sizeof(struct firmware_update_info));
994 	if (!firm_ctx) {
995 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
996 						 "Memory allocation error.");
997 		return;
998 	}
999 	firm_ctx->fw_image = NULL;
1000 	TAILQ_INIT(&firm_ctx->desc_head);
1001 	firm_ctx->request = request;
1002 
1003 	firm_ctx->req = calloc(1, sizeof(struct rpc_apply_firmware));
1004 	if (!firm_ctx->req) {
1005 		snprintf(msg, sizeof(msg), "Memory allocation error.");
1006 		goto err;
1007 	}
1008 
1009 	if (spdk_json_decode_object(params, rpc_apply_firmware_decoders,
1010 				    SPDK_COUNTOF(rpc_apply_firmware_decoders), firm_ctx->req)) {
1011 		snprintf(msg, sizeof(msg), "spdk_json_decode_object failed.");
1012 		goto err;
1013 	}
1014 
1015 	if ((bdev = spdk_bdev_get_by_name(firm_ctx->req->bdev_name)) == NULL) {
1016 		snprintf(msg, sizeof(msg), "bdev %s were not found", firm_ctx->req->bdev_name);
1017 		goto err;
1018 	}
1019 
1020 	if ((ctrlr = bdev_nvme_get_ctrlr(bdev)) == NULL) {
1021 		snprintf(msg, sizeof(msg), "Controller information for %s were not found.",
1022 			 firm_ctx->req->bdev_name);
1023 		goto err;
1024 	}
1025 	firm_ctx->ctrlr = ctrlr;
1026 
1027 	for (bdev2 = spdk_bdev_first(); bdev2; bdev2 = spdk_bdev_next(bdev2)) {
1028 
1029 		if (bdev_nvme_get_ctrlr(bdev2) != ctrlr) {
1030 			continue;
1031 		}
1032 
1033 		if (!(opt = malloc(sizeof(struct open_descriptors)))) {
1034 			snprintf(msg, sizeof(msg), "Memory allocation error.");
1035 			goto err;
1036 		}
1037 
1038 		if (spdk_bdev_open_ext(spdk_bdev_get_name(bdev2), true, apply_firmware_open_cb, NULL, &desc) != 0) {
1039 			snprintf(msg, sizeof(msg), "Device %s is in use.", firm_ctx->req->bdev_name);
1040 			free(opt);
1041 			goto err;
1042 		}
1043 
1044 		/* Save the thread where the base device is opened */
1045 		opt->thread = spdk_get_thread();
1046 
1047 		opt->desc = desc;
1048 		opt->bdev = bdev;
1049 		TAILQ_INSERT_TAIL(&firm_ctx->desc_head, opt, tqlst);
1050 	}
1051 
1052 	/*
1053 	 * find a descriptor associated with our bdev
1054 	 */
1055 	firm_ctx->desc = NULL;
1056 	TAILQ_FOREACH(opt, &firm_ctx->desc_head, tqlst) {
1057 		if (opt->bdev == bdev) {
1058 			firm_ctx->desc = opt->desc;
1059 			break;
1060 		}
1061 	}
1062 
1063 	if (!firm_ctx->desc) {
1064 		snprintf(msg, sizeof(msg), "No descriptor were found.");
1065 		goto err;
1066 	}
1067 
1068 	firm_ctx->ch = spdk_bdev_get_io_channel(firm_ctx->desc);
1069 	if (!firm_ctx->ch) {
1070 		snprintf(msg, sizeof(msg), "No channels were found.");
1071 		goto err;
1072 	}
1073 
1074 	fd = open(firm_ctx->req->filename, O_RDONLY);
1075 	if (fd < 0) {
1076 		snprintf(msg, sizeof(msg), "open file failed.");
1077 		goto err;
1078 	}
1079 
1080 	rc = fstat(fd, &fw_stat);
1081 	if (rc < 0) {
1082 		close(fd);
1083 		snprintf(msg, sizeof(msg), "fstat failed.");
1084 		goto err;
1085 	}
1086 
1087 	firm_ctx->size = fw_stat.st_size;
1088 	if (fw_stat.st_size % 4) {
1089 		close(fd);
1090 		snprintf(msg, sizeof(msg), "Firmware image size is not multiple of 4.");
1091 		goto err;
1092 	}
1093 
1094 	firm_ctx->fw_image = spdk_zmalloc(firm_ctx->size, 4096, NULL,
1095 					  SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
1096 	if (!firm_ctx->fw_image) {
1097 		close(fd);
1098 		snprintf(msg, sizeof(msg), "Memory allocation error.");
1099 		goto err;
1100 	}
1101 	firm_ctx->p = firm_ctx->fw_image;
1102 
1103 	if (read(fd, firm_ctx->p, firm_ctx->size) != ((ssize_t)(firm_ctx->size))) {
1104 		close(fd);
1105 		snprintf(msg, sizeof(msg), "Read firmware image failed!");
1106 		goto err;
1107 	}
1108 	close(fd);
1109 
1110 	firm_ctx->offset = 0;
1111 	firm_ctx->size_remaining = firm_ctx->size;
1112 	firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096);
1113 
1114 	cmd = malloc(sizeof(struct spdk_nvme_cmd));
1115 	if (!cmd) {
1116 		snprintf(msg, sizeof(msg), "Memory allocation error.");
1117 		goto err;
1118 	}
1119 	memset(cmd, 0, sizeof(struct spdk_nvme_cmd));
1120 	cmd->opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD;
1121 
1122 	cmd->cdw10 = spdk_nvme_bytes_to_numd(firm_ctx->transfer);
1123 	cmd->cdw11 = firm_ctx->offset >> 2;
1124 
1125 	rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, cmd, firm_ctx->p,
1126 					   firm_ctx->transfer, apply_firmware_complete, firm_ctx);
1127 	if (rc == 0) {
1128 		/* normal return here. */
1129 		return;
1130 	}
1131 
1132 	free(cmd);
1133 	snprintf(msg, sizeof(msg), "Read firmware image failed!");
1134 err:
1135 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg);
1136 	apply_firmware_cleanup(firm_ctx);
1137 }
1138 SPDK_RPC_REGISTER("bdev_nvme_apply_firmware", rpc_bdev_nvme_apply_firmware, SPDK_RPC_RUNTIME)
1139 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_apply_firmware, apply_nvme_firmware)
1140 
1141 struct rpc_bdev_nvme_transport_stat_ctx {
1142 	struct spdk_jsonrpc_request *request;
1143 	struct spdk_json_write_ctx *w;
1144 };
1145 
1146 static void
1147 rpc_bdev_nvme_rdma_stats(struct spdk_json_write_ctx *w,
1148 			 struct spdk_nvme_transport_poll_group_stat *stat)
1149 {
1150 	struct spdk_nvme_rdma_device_stat *device_stats;
1151 	uint32_t i;
1152 
1153 	spdk_json_write_named_array_begin(w, "devices");
1154 
1155 	for (i = 0; i < stat->rdma.num_devices; i++) {
1156 		device_stats = &stat->rdma.device_stats[i];
1157 		spdk_json_write_object_begin(w);
1158 		spdk_json_write_named_string(w, "dev_name", device_stats->name);
1159 		spdk_json_write_named_uint64(w, "polls", device_stats->polls);
1160 		spdk_json_write_named_uint64(w, "idle_polls", device_stats->idle_polls);
1161 		spdk_json_write_named_uint64(w, "completions", device_stats->completions);
1162 		spdk_json_write_named_uint64(w, "queued_requests", device_stats->queued_requests);
1163 		spdk_json_write_named_uint64(w, "total_send_wrs", device_stats->total_send_wrs);
1164 		spdk_json_write_named_uint64(w, "send_doorbell_updates", device_stats->send_doorbell_updates);
1165 		spdk_json_write_named_uint64(w, "total_recv_wrs", device_stats->total_recv_wrs);
1166 		spdk_json_write_named_uint64(w, "recv_doorbell_updates", device_stats->recv_doorbell_updates);
1167 		spdk_json_write_object_end(w);
1168 	}
1169 	spdk_json_write_array_end(w);
1170 }
1171 
1172 static void
1173 rpc_bdev_nvme_pcie_stats(struct spdk_json_write_ctx *w,
1174 			 struct spdk_nvme_transport_poll_group_stat *stat)
1175 {
1176 	spdk_json_write_named_uint64(w, "polls", stat->pcie.polls);
1177 	spdk_json_write_named_uint64(w, "idle_polls", stat->pcie.idle_polls);
1178 	spdk_json_write_named_uint64(w, "completions", stat->pcie.completions);
1179 	spdk_json_write_named_uint64(w, "cq_mmio_doorbell_updates", stat->pcie.cq_mmio_doorbell_updates);
1180 	spdk_json_write_named_uint64(w, "cq_shadow_doorbell_updates",
1181 				     stat->pcie.cq_shadow_doorbell_updates);
1182 	spdk_json_write_named_uint64(w, "queued_requests", stat->pcie.queued_requests);
1183 	spdk_json_write_named_uint64(w, "submitted_requests", stat->pcie.submitted_requests);
1184 	spdk_json_write_named_uint64(w, "sq_mmio_doorbell_updates", stat->pcie.sq_mmio_doorbell_updates);
1185 	spdk_json_write_named_uint64(w, "sq_shadow_doorbell_updates",
1186 				     stat->pcie.sq_shadow_doorbell_updates);
1187 }
1188 
1189 static void
1190 rpc_bdev_nvme_tcp_stats(struct spdk_json_write_ctx *w,
1191 			struct spdk_nvme_transport_poll_group_stat *stat)
1192 {
1193 	spdk_json_write_named_uint64(w, "polls", stat->tcp.polls);
1194 	spdk_json_write_named_uint64(w, "idle_polls", stat->tcp.idle_polls);
1195 	spdk_json_write_named_uint64(w, "socket_completions", stat->tcp.socket_completions);
1196 	spdk_json_write_named_uint64(w, "nvme_completions", stat->tcp.nvme_completions);
1197 	spdk_json_write_named_uint64(w, "queued_requests", stat->tcp.queued_requests);
1198 	spdk_json_write_named_uint64(w, "submitted_requests", stat->tcp.submitted_requests);
1199 }
1200 
1201 static void
1202 rpc_bdev_nvme_stats_per_channel(struct spdk_io_channel_iter *i)
1203 {
1204 	struct rpc_bdev_nvme_transport_stat_ctx *ctx;
1205 	struct spdk_io_channel *ch;
1206 	struct nvme_poll_group *group;
1207 	struct spdk_nvme_poll_group_stat *stat;
1208 	struct spdk_nvme_transport_poll_group_stat *tr_stat;
1209 	uint32_t j;
1210 	int rc;
1211 
1212 	ctx = spdk_io_channel_iter_get_ctx(i);
1213 	ch = spdk_io_channel_iter_get_channel(i);
1214 	group = spdk_io_channel_get_ctx(ch);
1215 
1216 	rc = spdk_nvme_poll_group_get_stats(group->group, &stat);
1217 	if (rc) {
1218 		spdk_for_each_channel_continue(i, rc);
1219 		return;
1220 	}
1221 
1222 	spdk_json_write_object_begin(ctx->w);
1223 	spdk_json_write_named_string(ctx->w, "thread", spdk_thread_get_name(spdk_get_thread()));
1224 	spdk_json_write_named_array_begin(ctx->w, "transports");
1225 
1226 	for (j = 0; j < stat->num_transports; j++) {
1227 		tr_stat = stat->transport_stat[j];
1228 		spdk_json_write_object_begin(ctx->w);
1229 		spdk_json_write_named_string(ctx->w, "trname", spdk_nvme_transport_id_trtype_str(tr_stat->trtype));
1230 
1231 		switch (stat->transport_stat[j]->trtype) {
1232 		case SPDK_NVME_TRANSPORT_RDMA:
1233 			rpc_bdev_nvme_rdma_stats(ctx->w, tr_stat);
1234 			break;
1235 		case SPDK_NVME_TRANSPORT_PCIE:
1236 			rpc_bdev_nvme_pcie_stats(ctx->w, tr_stat);
1237 			break;
1238 		case SPDK_NVME_TRANSPORT_TCP:
1239 			rpc_bdev_nvme_tcp_stats(ctx->w, tr_stat);
1240 			break;
1241 		default:
1242 			SPDK_WARNLOG("Can't handle trtype %d %s\n", tr_stat->trtype,
1243 				     spdk_nvme_transport_id_trtype_str(tr_stat->trtype));
1244 		}
1245 		spdk_json_write_object_end(ctx->w);
1246 	}
1247 	/* transports array */
1248 	spdk_json_write_array_end(ctx->w);
1249 	spdk_json_write_object_end(ctx->w);
1250 
1251 	spdk_nvme_poll_group_free_stats(group->group, stat);
1252 	spdk_for_each_channel_continue(i, 0);
1253 }
1254 
1255 static void
1256 rpc_bdev_nvme_stats_done(struct spdk_io_channel_iter *i, int status)
1257 {
1258 	struct rpc_bdev_nvme_transport_stat_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1259 
1260 	spdk_json_write_array_end(ctx->w);
1261 	spdk_json_write_object_end(ctx->w);
1262 	spdk_jsonrpc_end_result(ctx->request, ctx->w);
1263 	free(ctx);
1264 }
1265 
1266 static void
1267 rpc_bdev_nvme_get_transport_statistics(struct spdk_jsonrpc_request *request,
1268 				       const struct spdk_json_val *params)
1269 {
1270 	struct rpc_bdev_nvme_transport_stat_ctx *ctx;
1271 
1272 	if (params) {
1273 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1274 						 "'bdev_nvme_get_transport_statistics' requires no arguments");
1275 		return;
1276 	}
1277 
1278 	ctx = calloc(1, sizeof(*ctx));
1279 	if (!ctx) {
1280 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1281 						 "Memory allocation error");
1282 		return;
1283 	}
1284 	ctx->request = request;
1285 	ctx->w = spdk_jsonrpc_begin_result(ctx->request);
1286 	spdk_json_write_object_begin(ctx->w);
1287 	spdk_json_write_named_array_begin(ctx->w, "poll_groups");
1288 
1289 	spdk_for_each_channel(&g_nvme_bdev_ctrlrs,
1290 			      rpc_bdev_nvme_stats_per_channel,
1291 			      ctx,
1292 			      rpc_bdev_nvme_stats_done);
1293 }
1294 SPDK_RPC_REGISTER("bdev_nvme_get_transport_statistics", rpc_bdev_nvme_get_transport_statistics,
1295 		  SPDK_RPC_RUNTIME)
1296 
1297 struct rpc_bdev_nvme_reset_controller_req {
1298 	char *name;
1299 };
1300 
1301 static void
1302 free_rpc_bdev_nvme_reset_controller_req(struct rpc_bdev_nvme_reset_controller_req *r)
1303 {
1304 	free(r->name);
1305 }
1306 
1307 static const struct spdk_json_object_decoder rpc_bdev_nvme_reset_controller_req_decoders[] = {
1308 	{"name", offsetof(struct rpc_bdev_nvme_reset_controller_req, name), spdk_json_decode_string},
1309 };
1310 
1311 struct rpc_bdev_nvme_reset_controller_ctx {
1312 	struct spdk_jsonrpc_request *request;
1313 	bool success;
1314 	struct spdk_thread *orig_thread;
1315 };
1316 
1317 static void
1318 _rpc_bdev_nvme_reset_controller_cb(void *_ctx)
1319 {
1320 	struct rpc_bdev_nvme_reset_controller_ctx *ctx = _ctx;
1321 
1322 	spdk_jsonrpc_send_bool_response(ctx->request, ctx->success);
1323 
1324 	free(ctx);
1325 }
1326 
1327 static void
1328 rpc_bdev_nvme_reset_controller_cb(void *cb_arg, bool success)
1329 {
1330 	struct rpc_bdev_nvme_reset_controller_ctx *ctx = cb_arg;
1331 
1332 	ctx->success = success;
1333 
1334 	spdk_thread_send_msg(ctx->orig_thread, _rpc_bdev_nvme_reset_controller_cb, ctx);
1335 }
1336 
1337 static void
1338 rpc_bdev_nvme_reset_controller(struct spdk_jsonrpc_request *request,
1339 			       const struct spdk_json_val *params)
1340 {
1341 	struct rpc_bdev_nvme_reset_controller_req req = {NULL};
1342 	struct rpc_bdev_nvme_reset_controller_ctx *ctx;
1343 	struct nvme_ctrlr *nvme_ctrlr;
1344 	int rc;
1345 
1346 	ctx = calloc(1, sizeof(*ctx));
1347 	if (ctx == NULL) {
1348 		SPDK_ERRLOG("Memory allocation failed\n");
1349 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1350 						 "Memory allocation failed");
1351 		return;
1352 	}
1353 
1354 	if (spdk_json_decode_object(params, rpc_bdev_nvme_reset_controller_req_decoders,
1355 				    SPDK_COUNTOF(rpc_bdev_nvme_reset_controller_req_decoders),
1356 				    &req)) {
1357 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1358 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(EINVAL));
1359 		goto err;
1360 	}
1361 
1362 	nvme_ctrlr = nvme_ctrlr_get_by_name(req.name);
1363 	if (nvme_ctrlr == NULL) {
1364 		SPDK_ERRLOG("Failed at device lookup\n");
1365 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1366 		goto err;
1367 	}
1368 
1369 	ctx->request = request;
1370 	ctx->orig_thread = spdk_get_thread();
1371 
1372 	rc = bdev_nvme_reset_rpc(nvme_ctrlr, rpc_bdev_nvme_reset_controller_cb, ctx);
1373 	if (rc != 0) {
1374 		SPDK_NOTICELOG("Failed at bdev_nvme_reset_rpc\n");
1375 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc));
1376 		goto err;
1377 	}
1378 
1379 	free_rpc_bdev_nvme_reset_controller_req(&req);
1380 	return;
1381 
1382 err:
1383 	free_rpc_bdev_nvme_reset_controller_req(&req);
1384 	free(ctx);
1385 }
1386 SPDK_RPC_REGISTER("bdev_nvme_reset_controller", rpc_bdev_nvme_reset_controller, SPDK_RPC_RUNTIME)
1387 
1388 struct rpc_get_controller_health_info {
1389 	char *name;
1390 };
1391 
1392 struct spdk_nvme_health_info_context {
1393 	struct spdk_jsonrpc_request *request;
1394 	struct spdk_nvme_ctrlr *ctrlr;
1395 	struct spdk_nvme_health_information_page health_page;
1396 };
1397 
1398 static void
1399 free_rpc_get_controller_health_info(struct rpc_get_controller_health_info *r)
1400 {
1401 	free(r->name);
1402 }
1403 
1404 static const struct spdk_json_object_decoder rpc_get_controller_health_info_decoders[] = {
1405 	{"name", offsetof(struct rpc_get_controller_health_info, name), spdk_json_decode_string, true},
1406 };
1407 
1408 static void nvme_health_info_cleanup(struct spdk_nvme_health_info_context *context, bool response)
1409 {
1410 	if (response == true) {
1411 		spdk_jsonrpc_send_error_response(context->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1412 						 "Internal error.");
1413 	}
1414 
1415 	free(context);
1416 }
1417 
1418 static void
1419 get_health_log_page_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
1420 {
1421 	int i;
1422 	char buf[128];
1423 	struct spdk_nvme_health_info_context *context = cb_arg;
1424 	struct spdk_jsonrpc_request *request = context->request;
1425 	struct spdk_json_write_ctx *w;
1426 	struct spdk_nvme_ctrlr *ctrlr = context->ctrlr;
1427 	const struct spdk_nvme_transport_id *trid = NULL;
1428 	const struct spdk_nvme_ctrlr_data *cdata = NULL;
1429 	struct spdk_nvme_health_information_page *health_page = NULL;
1430 
1431 	if (spdk_nvme_cpl_is_error(cpl)) {
1432 		nvme_health_info_cleanup(context, true);
1433 		SPDK_ERRLOG("get log page failed\n");
1434 		return;
1435 	}
1436 
1437 	if (ctrlr == NULL) {
1438 		nvme_health_info_cleanup(context, true);
1439 		SPDK_ERRLOG("ctrlr is NULL\n");
1440 		return;
1441 	} else {
1442 		trid = spdk_nvme_ctrlr_get_transport_id(ctrlr);
1443 		cdata = spdk_nvme_ctrlr_get_data(ctrlr);
1444 		health_page = &(context->health_page);
1445 	}
1446 
1447 	w = spdk_jsonrpc_begin_result(request);
1448 
1449 	spdk_json_write_object_begin(w);
1450 	snprintf(buf, sizeof(cdata->mn) + 1, "%s", cdata->mn);
1451 	spdk_str_trim(buf);
1452 	spdk_json_write_named_string(w, "model_number", buf);
1453 	snprintf(buf, sizeof(cdata->sn) + 1, "%s", cdata->sn);
1454 	spdk_str_trim(buf);
1455 	spdk_json_write_named_string(w, "serial_number", buf);
1456 	snprintf(buf, sizeof(cdata->fr) + 1, "%s", cdata->fr);
1457 	spdk_str_trim(buf);
1458 	spdk_json_write_named_string(w, "firmware_revision", buf);
1459 	spdk_json_write_named_string(w, "traddr", trid->traddr);
1460 	spdk_json_write_named_uint64(w, "temperature_celsius", health_page->temperature - 273);
1461 	spdk_json_write_named_uint64(w, "available_spare_percentage", health_page->available_spare);
1462 	spdk_json_write_named_uint64(w, "available_spare_threshold_percentage",
1463 				     health_page->available_spare_threshold);
1464 	spdk_json_write_named_uint64(w, "percentage_used", health_page->percentage_used);
1465 	spdk_json_write_named_uint128(w, "data_units_read",
1466 				      health_page->data_units_read[0], health_page->data_units_read[1]);
1467 	spdk_json_write_named_uint128(w, "data_units_written",
1468 				      health_page->data_units_written[0], health_page->data_units_written[1]);
1469 	spdk_json_write_named_uint128(w, "host_read_commands",
1470 				      health_page->host_read_commands[0], health_page->host_read_commands[1]);
1471 	spdk_json_write_named_uint128(w, "host_write_commands",
1472 				      health_page->host_write_commands[0], health_page->host_write_commands[1]);
1473 	spdk_json_write_named_uint128(w, "controller_busy_time",
1474 				      health_page->controller_busy_time[0], health_page->controller_busy_time[1]);
1475 	spdk_json_write_named_uint128(w, "power_cycles",
1476 				      health_page->power_cycles[0], health_page->power_cycles[1]);
1477 	spdk_json_write_named_uint128(w, "power_on_hours",
1478 				      health_page->power_on_hours[0], health_page->power_on_hours[1]);
1479 	spdk_json_write_named_uint128(w, "unsafe_shutdowns",
1480 				      health_page->unsafe_shutdowns[0], health_page->unsafe_shutdowns[1]);
1481 	spdk_json_write_named_uint128(w, "media_errors",
1482 				      health_page->media_errors[0], health_page->media_errors[1]);
1483 	spdk_json_write_named_uint128(w, "num_err_log_entries",
1484 				      health_page->num_error_info_log_entries[0], health_page->num_error_info_log_entries[1]);
1485 	spdk_json_write_named_uint64(w, "warning_temperature_time_minutes", health_page->warning_temp_time);
1486 	spdk_json_write_named_uint64(w, "critical_composite_temperature_time_minutes",
1487 				     health_page->critical_temp_time);
1488 	for (i = 0; i < 8; i++) {
1489 		if (health_page->temp_sensor[i] != 0) {
1490 			spdk_json_write_named_uint64(w, "temperature_sensor_celsius", health_page->temp_sensor[i] - 273);
1491 		}
1492 	}
1493 	spdk_json_write_object_end(w);
1494 
1495 	spdk_jsonrpc_end_result(request, w);
1496 	nvme_health_info_cleanup(context, false);
1497 }
1498 
1499 static void
1500 get_health_log_page(struct spdk_nvme_health_info_context *context)
1501 {
1502 	struct spdk_nvme_ctrlr *ctrlr = context->ctrlr;
1503 
1504 	if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_HEALTH_INFORMATION,
1505 					     SPDK_NVME_GLOBAL_NS_TAG,
1506 					     &(context->health_page), sizeof(context->health_page), 0,
1507 					     get_health_log_page_completion, context)) {
1508 		nvme_health_info_cleanup(context, true);
1509 		SPDK_ERRLOG("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
1510 	}
1511 }
1512 
1513 static void
1514 get_temperature_threshold_feature_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
1515 {
1516 	struct spdk_nvme_health_info_context *context = cb_arg;
1517 
1518 	if (spdk_nvme_cpl_is_error(cpl)) {
1519 		nvme_health_info_cleanup(context, true);
1520 		SPDK_ERRLOG("feature SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD failed in completion\n");
1521 	} else {
1522 		get_health_log_page(context);
1523 	}
1524 }
1525 
1526 static int
1527 get_temperature_threshold_feature(struct spdk_nvme_health_info_context *context)
1528 {
1529 	struct spdk_nvme_cmd cmd = {};
1530 
1531 	cmd.opc = SPDK_NVME_OPC_GET_FEATURES;
1532 	cmd.cdw10 = SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD;
1533 
1534 	return spdk_nvme_ctrlr_cmd_admin_raw(context->ctrlr, &cmd, NULL, 0,
1535 					     get_temperature_threshold_feature_completion, context);
1536 }
1537 
1538 static void
1539 get_controller_health_info(struct spdk_jsonrpc_request *request, struct spdk_nvme_ctrlr *ctrlr)
1540 {
1541 	struct spdk_nvme_health_info_context *context;
1542 
1543 	context = calloc(1, sizeof(struct spdk_nvme_health_info_context));
1544 	if (!context) {
1545 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1546 						 "Memory allocation error.");
1547 		return;
1548 	}
1549 
1550 	context->request = request;
1551 	context->ctrlr = ctrlr;
1552 
1553 	if (get_temperature_threshold_feature(context)) {
1554 		nvme_health_info_cleanup(context, true);
1555 		SPDK_ERRLOG("feature SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD failed to submit\n");
1556 	}
1557 
1558 	return;
1559 }
1560 
1561 static void
1562 rpc_bdev_nvme_get_controller_health_info(struct spdk_jsonrpc_request *request,
1563 		const struct spdk_json_val *params)
1564 {
1565 	struct rpc_get_controller_health_info req = {};
1566 	struct nvme_ctrlr *nvme_ctrlr = NULL;
1567 
1568 	if (!params) {
1569 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1570 						 "Missing device name");
1571 
1572 		return;
1573 	}
1574 	if (spdk_json_decode_object(params, rpc_get_controller_health_info_decoders,
1575 				    SPDK_COUNTOF(rpc_get_controller_health_info_decoders), &req)) {
1576 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1577 		free_rpc_get_controller_health_info(&req);
1578 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1579 						 "Invalid parameters");
1580 
1581 		return;
1582 	}
1583 
1584 	nvme_ctrlr = nvme_ctrlr_get_by_name(req.name);
1585 
1586 	if (!nvme_ctrlr) {
1587 		SPDK_ERRLOG("nvme ctrlr name '%s' does not exist\n", req.name);
1588 		free_rpc_get_controller_health_info(&req);
1589 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1590 						 "Device not found");
1591 		return;
1592 	}
1593 
1594 	get_controller_health_info(request, nvme_ctrlr->ctrlr);
1595 	free_rpc_get_controller_health_info(&req);
1596 
1597 	return;
1598 }
1599 SPDK_RPC_REGISTER("bdev_nvme_get_controller_health_info",
1600 		  rpc_bdev_nvme_get_controller_health_info, SPDK_RPC_RUNTIME)
1601 
1602 struct rpc_bdev_nvme_start_discovery {
1603 	char *name;
1604 	char *trtype;
1605 	char *adrfam;
1606 	char *traddr;
1607 	char *trsvcid;
1608 	char *hostnqn;
1609 	struct spdk_nvme_ctrlr_opts opts;
1610 };
1611 
1612 static void
1613 free_rpc_bdev_nvme_start_discovery(struct rpc_bdev_nvme_start_discovery *req)
1614 {
1615 	free(req->name);
1616 	free(req->trtype);
1617 	free(req->adrfam);
1618 	free(req->traddr);
1619 	free(req->trsvcid);
1620 	free(req->hostnqn);
1621 }
1622 
1623 static const struct spdk_json_object_decoder rpc_bdev_nvme_start_discovery_decoders[] = {
1624 	{"name", offsetof(struct rpc_bdev_nvme_start_discovery, name), spdk_json_decode_string},
1625 	{"trtype", offsetof(struct rpc_bdev_nvme_start_discovery, trtype), spdk_json_decode_string},
1626 	{"traddr", offsetof(struct rpc_bdev_nvme_start_discovery, traddr), spdk_json_decode_string},
1627 	{"adrfam", offsetof(struct rpc_bdev_nvme_start_discovery, adrfam), spdk_json_decode_string, true},
1628 	{"trsvcid", offsetof(struct rpc_bdev_nvme_start_discovery, trsvcid), spdk_json_decode_string, true},
1629 	{"hostnqn", offsetof(struct rpc_bdev_nvme_start_discovery, hostnqn), spdk_json_decode_string, 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 *cb_ctx, int rc)
1639 {
1640 	struct rpc_bdev_nvme_start_discovery_ctx *ctx = cb_ctx;
1641 	struct spdk_jsonrpc_request *request = ctx->request;
1642 
1643 	if (rc < 0) {
1644 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1645 		free_rpc_bdev_nvme_start_discovery(&ctx->req);
1646 		free(ctx);
1647 		return;
1648 	}
1649 
1650 	spdk_jsonrpc_send_bool_response(ctx->request, rc == 0);
1651 
1652 	free_rpc_bdev_nvme_start_discovery(&ctx->req);
1653 	free(ctx);
1654 }
1655 
1656 static void
1657 rpc_bdev_nvme_start_discovery(struct spdk_jsonrpc_request *request,
1658 			      const struct spdk_json_val *params)
1659 {
1660 	struct rpc_bdev_nvme_start_discovery_ctx *ctx;
1661 	struct spdk_nvme_transport_id trid = {};
1662 	size_t len, maxlen;
1663 	int rc;
1664 
1665 	ctx = calloc(1, sizeof(*ctx));
1666 	if (!ctx) {
1667 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1668 		return;
1669 	}
1670 
1671 	spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->req.opts, sizeof(ctx->req.opts));
1672 
1673 	if (spdk_json_decode_object(params, rpc_bdev_nvme_start_discovery_decoders,
1674 				    SPDK_COUNTOF(rpc_bdev_nvme_start_discovery_decoders),
1675 				    &ctx->req)) {
1676 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1677 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1678 						 "spdk_json_decode_object failed");
1679 		goto cleanup;
1680 	}
1681 
1682 	/* Parse trstring */
1683 	rc = spdk_nvme_transport_id_populate_trstring(&trid, ctx->req.trtype);
1684 	if (rc < 0) {
1685 		SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype);
1686 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s",
1687 						     ctx->req.trtype);
1688 		goto cleanup;
1689 	}
1690 
1691 	/* Parse trtype */
1692 	rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype);
1693 	assert(rc == 0);
1694 
1695 	/* Parse traddr */
1696 	maxlen = sizeof(trid.traddr);
1697 	len = strnlen(ctx->req.traddr, maxlen);
1698 	if (len == maxlen) {
1699 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s",
1700 						     ctx->req.traddr);
1701 		goto cleanup;
1702 	}
1703 	memcpy(trid.traddr, ctx->req.traddr, len + 1);
1704 
1705 	/* Parse adrfam */
1706 	if (ctx->req.adrfam) {
1707 		rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam);
1708 		if (rc < 0) {
1709 			SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam);
1710 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s",
1711 							     ctx->req.adrfam);
1712 			goto cleanup;
1713 		}
1714 	}
1715 
1716 	/* Parse trsvcid */
1717 	if (ctx->req.trsvcid) {
1718 		maxlen = sizeof(trid.trsvcid);
1719 		len = strnlen(ctx->req.trsvcid, maxlen);
1720 		if (len == maxlen) {
1721 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s",
1722 							     ctx->req.trsvcid);
1723 			goto cleanup;
1724 		}
1725 		memcpy(trid.trsvcid, ctx->req.trsvcid, len + 1);
1726 	}
1727 
1728 	if (ctx->req.hostnqn) {
1729 		snprintf(ctx->req.opts.hostnqn, sizeof(ctx->req.opts.hostnqn), "%s",
1730 			 ctx->req.hostnqn);
1731 	}
1732 
1733 	ctx->request = request;
1734 	rc = bdev_nvme_start_discovery(&trid, ctx->req.name, &ctx->req.opts,
1735 				       rpc_bdev_nvme_start_discovery_done, ctx);
1736 	if (rc) {
1737 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
1738 		goto cleanup;
1739 	}
1740 
1741 	return;
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 enum error_injection_cmd_type {
1812 	NVME_ADMIN_CMD = 1,
1813 	NVME_IO_CMD,
1814 };
1815 
1816 struct rpc_add_error_injection {
1817 	char *name;
1818 	enum error_injection_cmd_type cmd_type;
1819 	uint8_t opc;
1820 	bool do_not_submit;
1821 	uint64_t timeout_in_us;
1822 	uint32_t err_count;
1823 	uint8_t sct;
1824 	uint8_t sc;
1825 };
1826 
1827 static void
1828 free_rpc_add_error_injection(struct rpc_add_error_injection *req)
1829 {
1830 	free(req->name);
1831 }
1832 
1833 static int
1834 rpc_error_injection_decode_cmd_type(const struct spdk_json_val *val, void *out)
1835 {
1836 	int *cmd_type = out;
1837 
1838 	if (spdk_json_strequal(val, "admin")) {
1839 		*cmd_type = NVME_ADMIN_CMD;
1840 	} else if (spdk_json_strequal(val, "io")) {
1841 		*cmd_type = NVME_IO_CMD;
1842 	} else {
1843 		SPDK_ERRLOG("Invalid parameter value: cmd_type\n");
1844 		return -EINVAL;
1845 	}
1846 
1847 	return 0;
1848 }
1849 
1850 static const struct spdk_json_object_decoder rpc_add_error_injection_decoders[] = {
1851 	{ "name", offsetof(struct rpc_add_error_injection, name), spdk_json_decode_string },
1852 	{ "cmd_type", offsetof(struct rpc_add_error_injection, cmd_type), rpc_error_injection_decode_cmd_type },
1853 	{ "opc", offsetof(struct rpc_add_error_injection, opc), spdk_json_decode_uint8 },
1854 	{ "do_not_submit", offsetof(struct rpc_add_error_injection, do_not_submit), spdk_json_decode_bool, true },
1855 	{ "timeout_in_us", offsetof(struct rpc_add_error_injection, timeout_in_us), spdk_json_decode_uint64, true },
1856 	{ "err_count", offsetof(struct rpc_add_error_injection, err_count), spdk_json_decode_uint32, true },
1857 	{ "sct", offsetof(struct rpc_add_error_injection, sct), spdk_json_decode_uint8, true},
1858 	{ "sc", offsetof(struct rpc_add_error_injection, sc), spdk_json_decode_uint8, true},
1859 };
1860 
1861 struct rpc_add_error_injection_ctx {
1862 	struct spdk_jsonrpc_request *request;
1863 	struct rpc_add_error_injection rpc;
1864 };
1865 
1866 static void
1867 rpc_add_error_injection_done(struct spdk_io_channel_iter *i, int status)
1868 {
1869 	struct rpc_add_error_injection_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1870 
1871 	if (status) {
1872 		spdk_jsonrpc_send_error_response(ctx->request, status,
1873 						 "Failed to add the error injection.");
1874 	} else {
1875 		spdk_jsonrpc_send_bool_response(ctx->request, true);
1876 	}
1877 
1878 	free_rpc_add_error_injection(&ctx->rpc);
1879 	free(ctx);
1880 }
1881 
1882 static void
1883 rpc_add_error_injection_per_channel(struct spdk_io_channel_iter *i)
1884 {
1885 	struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
1886 	struct rpc_add_error_injection_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1887 	struct nvme_ctrlr_channel *ctrlr_ch = spdk_io_channel_get_ctx(ch);
1888 	struct nvme_ctrlr *nvme_ctrlr = nvme_ctrlr_channel_get_ctrlr(ctrlr_ch);
1889 	struct spdk_nvme_qpair *qpair = ctrlr_ch->qpair;
1890 	struct spdk_nvme_ctrlr *ctrlr = nvme_ctrlr->ctrlr;
1891 	int rc = 0;
1892 
1893 	if (qpair != NULL) {
1894 		rc = spdk_nvme_qpair_add_cmd_error_injection(ctrlr, qpair, ctx->rpc.opc,
1895 				ctx->rpc.do_not_submit, ctx->rpc.timeout_in_us, ctx->rpc.err_count,
1896 				ctx->rpc.sct, ctx->rpc.sc);
1897 	}
1898 
1899 	spdk_for_each_channel_continue(i, rc);
1900 }
1901 
1902 static void
1903 rpc_bdev_nvme_add_error_injection(
1904 	struct spdk_jsonrpc_request *request,
1905 	const struct spdk_json_val *params)
1906 {
1907 	struct rpc_add_error_injection_ctx *ctx;
1908 	struct nvme_ctrlr *nvme_ctrlr;
1909 	int rc;
1910 
1911 	ctx = calloc(1, sizeof(*ctx));
1912 	if (!ctx) {
1913 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1914 		return;
1915 	}
1916 	ctx->rpc.err_count = 1;
1917 	ctx->request = request;
1918 
1919 	if (spdk_json_decode_object(params,
1920 				    rpc_add_error_injection_decoders,
1921 				    SPDK_COUNTOF(rpc_add_error_injection_decoders),
1922 				    &ctx->rpc)) {
1923 		spdk_jsonrpc_send_error_response(request, -EINVAL,
1924 						 "Failed to parse the request");
1925 		goto cleanup;
1926 	}
1927 
1928 	nvme_ctrlr = nvme_ctrlr_get_by_name(ctx->rpc.name);
1929 	if (nvme_ctrlr == NULL) {
1930 		SPDK_ERRLOG("No controller with specified name was found.\n");
1931 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1932 		goto cleanup;
1933 	}
1934 
1935 	if (ctx->rpc.cmd_type == NVME_IO_CMD) {
1936 		spdk_for_each_channel(nvme_ctrlr,
1937 				      rpc_add_error_injection_per_channel,
1938 				      ctx,
1939 				      rpc_add_error_injection_done);
1940 
1941 		return;
1942 	} else {
1943 		rc = spdk_nvme_qpair_add_cmd_error_injection(nvme_ctrlr->ctrlr, NULL, ctx->rpc.opc,
1944 				ctx->rpc.do_not_submit, ctx->rpc.timeout_in_us, ctx->rpc.err_count,
1945 				ctx->rpc.sct, ctx->rpc.sc);
1946 		if (rc) {
1947 			spdk_jsonrpc_send_error_response(request, -rc,
1948 							 "Failed to add the error injection");
1949 		} else {
1950 			spdk_jsonrpc_send_bool_response(ctx->request, true);
1951 		}
1952 	}
1953 
1954 cleanup:
1955 	free_rpc_add_error_injection(&ctx->rpc);
1956 	free(ctx);
1957 }
1958 SPDK_RPC_REGISTER("bdev_nvme_add_error_injection", rpc_bdev_nvme_add_error_injection,
1959 		  SPDK_RPC_RUNTIME)
1960 
1961 struct rpc_remove_error_injection {
1962 	char *name;
1963 	enum error_injection_cmd_type cmd_type;
1964 	uint8_t opc;
1965 };
1966 
1967 static void
1968 free_rpc_remove_error_injection(struct rpc_remove_error_injection *req)
1969 {
1970 	free(req->name);
1971 }
1972 
1973 static const struct spdk_json_object_decoder rpc_remove_error_injection_decoders[] = {
1974 	{ "name", offsetof(struct rpc_remove_error_injection, name), spdk_json_decode_string },
1975 	{ "cmd_type", offsetof(struct rpc_remove_error_injection, cmd_type), rpc_error_injection_decode_cmd_type },
1976 	{ "opc", offsetof(struct rpc_remove_error_injection, opc), spdk_json_decode_uint8 },
1977 };
1978 
1979 struct rpc_remove_error_injection_ctx {
1980 	struct spdk_jsonrpc_request *request;
1981 	struct rpc_remove_error_injection rpc;
1982 };
1983 
1984 static void
1985 rpc_remove_error_injection_done(struct spdk_io_channel_iter *i, int status)
1986 {
1987 	struct rpc_remove_error_injection_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1988 
1989 	if (status) {
1990 		spdk_jsonrpc_send_error_response(ctx->request, status,
1991 						 "Failed to remove the error injection.");
1992 	} else {
1993 		spdk_jsonrpc_send_bool_response(ctx->request, true);
1994 	}
1995 
1996 	free_rpc_remove_error_injection(&ctx->rpc);
1997 	free(ctx);
1998 }
1999 
2000 static void
2001 rpc_remove_error_injection_per_channel(struct spdk_io_channel_iter *i)
2002 {
2003 	struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
2004 	struct rpc_remove_error_injection_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2005 	struct nvme_ctrlr_channel *ctrlr_ch = spdk_io_channel_get_ctx(ch);
2006 	struct nvme_ctrlr *nvme_ctrlr = nvme_ctrlr_channel_get_ctrlr(ctrlr_ch);
2007 	struct spdk_nvme_qpair *qpair = ctrlr_ch->qpair;
2008 	struct spdk_nvme_ctrlr *ctrlr = nvme_ctrlr->ctrlr;
2009 
2010 	if (ctrlr_ch->qpair != NULL) {
2011 		spdk_nvme_qpair_remove_cmd_error_injection(ctrlr, qpair, ctx->rpc.opc);
2012 	}
2013 
2014 	spdk_for_each_channel_continue(i, 0);
2015 }
2016 
2017 static void
2018 rpc_bdev_nvme_remove_error_injection(struct spdk_jsonrpc_request *request,
2019 				     const struct spdk_json_val *params)
2020 {
2021 	struct rpc_remove_error_injection_ctx *ctx;
2022 	struct nvme_ctrlr *nvme_ctrlr;
2023 
2024 	ctx = calloc(1, sizeof(*ctx));
2025 	if (!ctx) {
2026 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
2027 		return;
2028 	}
2029 	ctx->request = request;
2030 
2031 	if (spdk_json_decode_object(params,
2032 				    rpc_remove_error_injection_decoders,
2033 				    SPDK_COUNTOF(rpc_remove_error_injection_decoders),
2034 				    &ctx->rpc)) {
2035 		spdk_jsonrpc_send_error_response(request, -EINVAL,
2036 						 "Failed to parse the request");
2037 		goto cleanup;
2038 	}
2039 
2040 	nvme_ctrlr = nvme_ctrlr_get_by_name(ctx->rpc.name);
2041 	if (nvme_ctrlr == NULL) {
2042 		SPDK_ERRLOG("No controller with specified name was found.\n");
2043 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
2044 		goto cleanup;
2045 	}
2046 
2047 	if (ctx->rpc.cmd_type == NVME_IO_CMD) {
2048 		spdk_for_each_channel(nvme_ctrlr,
2049 				      rpc_remove_error_injection_per_channel,
2050 				      ctx,
2051 				      rpc_remove_error_injection_done);
2052 		return;
2053 	} else {
2054 		spdk_nvme_qpair_remove_cmd_error_injection(nvme_ctrlr->ctrlr, NULL, ctx->rpc.opc);
2055 		spdk_jsonrpc_send_bool_response(ctx->request, true);
2056 	}
2057 
2058 cleanup:
2059 	free_rpc_remove_error_injection(&ctx->rpc);
2060 	free(ctx);
2061 }
2062 SPDK_RPC_REGISTER("bdev_nvme_remove_error_injection", rpc_bdev_nvme_remove_error_injection,
2063 		  SPDK_RPC_RUNTIME)
2064