xref: /spdk/module/bdev/nvme/bdev_nvme_rpc.c (revision 2f5c602574a98ede645991abe279a96e19c50196)
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  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "bdev_nvme.h"
37 #include "common.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, 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 };
93 
94 static void
95 rpc_bdev_nvme_set_options(struct spdk_jsonrpc_request *request,
96 			  const struct spdk_json_val *params)
97 {
98 	struct spdk_bdev_nvme_opts opts;
99 	int rc;
100 
101 	bdev_nvme_get_opts(&opts);
102 	if (params && spdk_json_decode_object(params, rpc_bdev_nvme_options_decoders,
103 					      SPDK_COUNTOF(rpc_bdev_nvme_options_decoders),
104 					      &opts)) {
105 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
106 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
107 						 "spdk_json_decode_object failed");
108 		return;
109 	}
110 
111 	rc = bdev_nvme_set_opts(&opts);
112 	if (rc) {
113 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
114 		return;
115 	}
116 
117 	spdk_jsonrpc_send_bool_response(request, true);
118 
119 	return;
120 }
121 SPDK_RPC_REGISTER("bdev_nvme_set_options", rpc_bdev_nvme_set_options,
122 		  SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME)
123 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_set_options, set_bdev_nvme_options)
124 
125 struct rpc_bdev_nvme_hotplug {
126 	bool enabled;
127 	uint64_t period_us;
128 };
129 
130 static const struct spdk_json_object_decoder rpc_bdev_nvme_hotplug_decoders[] = {
131 	{"enable", offsetof(struct rpc_bdev_nvme_hotplug, enabled), spdk_json_decode_bool, false},
132 	{"period_us", offsetof(struct rpc_bdev_nvme_hotplug, period_us), spdk_json_decode_uint64, true},
133 };
134 
135 static void
136 rpc_bdev_nvme_set_hotplug_done(void *ctx)
137 {
138 	struct spdk_jsonrpc_request *request = ctx;
139 
140 	spdk_jsonrpc_send_bool_response(request, true);
141 }
142 
143 static void
144 rpc_bdev_nvme_set_hotplug(struct spdk_jsonrpc_request *request,
145 			  const struct spdk_json_val *params)
146 {
147 	struct rpc_bdev_nvme_hotplug req = {false, 0};
148 	int rc;
149 
150 	if (spdk_json_decode_object(params, rpc_bdev_nvme_hotplug_decoders,
151 				    SPDK_COUNTOF(rpc_bdev_nvme_hotplug_decoders), &req)) {
152 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
153 		rc = -EINVAL;
154 		goto invalid;
155 	}
156 
157 	rc = bdev_nvme_set_hotplug(req.enabled, req.period_us, rpc_bdev_nvme_set_hotplug_done,
158 				   request);
159 	if (rc) {
160 		goto invalid;
161 	}
162 
163 	return;
164 invalid:
165 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc));
166 }
167 SPDK_RPC_REGISTER("bdev_nvme_set_hotplug", rpc_bdev_nvme_set_hotplug, SPDK_RPC_RUNTIME)
168 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_set_hotplug, set_bdev_nvme_hotplug)
169 
170 struct rpc_bdev_nvme_attach_controller {
171 	char *name;
172 	char *trtype;
173 	char *adrfam;
174 	char *traddr;
175 	char *trsvcid;
176 	char *priority;
177 	char *subnqn;
178 	char *hostnqn;
179 	char *hostaddr;
180 	char *hostsvcid;
181 	bool prchk_reftag;
182 	bool prchk_guard;
183 	uint64_t fabrics_connect_timeout_us;
184 	struct spdk_nvme_ctrlr_opts opts;
185 };
186 
187 static void
188 free_rpc_bdev_nvme_attach_controller(struct rpc_bdev_nvme_attach_controller *req)
189 {
190 	free(req->name);
191 	free(req->trtype);
192 	free(req->adrfam);
193 	free(req->traddr);
194 	free(req->trsvcid);
195 	free(req->priority);
196 	free(req->subnqn);
197 	free(req->hostnqn);
198 	free(req->hostaddr);
199 	free(req->hostsvcid);
200 }
201 
202 static const struct spdk_json_object_decoder rpc_bdev_nvme_attach_controller_decoders[] = {
203 	{"name", offsetof(struct rpc_bdev_nvme_attach_controller, name), spdk_json_decode_string},
204 	{"trtype", offsetof(struct rpc_bdev_nvme_attach_controller, trtype), spdk_json_decode_string},
205 	{"traddr", offsetof(struct rpc_bdev_nvme_attach_controller, traddr), spdk_json_decode_string},
206 
207 	{"adrfam", offsetof(struct rpc_bdev_nvme_attach_controller, adrfam), spdk_json_decode_string, true},
208 	{"trsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, trsvcid), spdk_json_decode_string, true},
209 	{"priority", offsetof(struct rpc_bdev_nvme_attach_controller, priority), spdk_json_decode_string, true},
210 	{"subnqn", offsetof(struct rpc_bdev_nvme_attach_controller, subnqn), spdk_json_decode_string, true},
211 	{"hostnqn", offsetof(struct rpc_bdev_nvme_attach_controller, hostnqn), spdk_json_decode_string, true},
212 	{"hostaddr", offsetof(struct rpc_bdev_nvme_attach_controller, hostaddr), spdk_json_decode_string, true},
213 	{"hostsvcid", offsetof(struct rpc_bdev_nvme_attach_controller, hostsvcid), spdk_json_decode_string, true},
214 
215 	{"prchk_reftag", offsetof(struct rpc_bdev_nvme_attach_controller, prchk_reftag), spdk_json_decode_bool, true},
216 	{"prchk_guard", offsetof(struct rpc_bdev_nvme_attach_controller, prchk_guard), spdk_json_decode_bool, true},
217 	{"hdgst", offsetof(struct rpc_bdev_nvme_attach_controller, opts.header_digest), spdk_json_decode_bool, true},
218 	{"ddgst", offsetof(struct rpc_bdev_nvme_attach_controller, opts.data_digest), spdk_json_decode_bool, true},
219 	{"fabrics_connect_timeout_us", offsetof(struct rpc_bdev_nvme_attach_controller, opts.fabrics_connect_timeout_us), spdk_json_decode_uint64, true},
220 };
221 
222 #define NVME_MAX_BDEVS_PER_RPC 128
223 
224 struct rpc_bdev_nvme_attach_controller_ctx {
225 	struct rpc_bdev_nvme_attach_controller req;
226 	uint32_t count;
227 	size_t bdev_count;
228 	const char *names[NVME_MAX_BDEVS_PER_RPC];
229 	struct spdk_jsonrpc_request *request;
230 };
231 
232 static void
233 rpc_bdev_nvme_attach_controller_examined(void *cb_ctx)
234 {
235 	struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx;
236 	struct spdk_jsonrpc_request *request = ctx->request;
237 	struct spdk_json_write_ctx *w;
238 	size_t i;
239 
240 	w = spdk_jsonrpc_begin_result(request);
241 	spdk_json_write_array_begin(w);
242 	for (i = 0; i < ctx->bdev_count; i++) {
243 		spdk_json_write_string(w, ctx->names[i]);
244 	}
245 	spdk_json_write_array_end(w);
246 	spdk_jsonrpc_end_result(request, w);
247 
248 	free_rpc_bdev_nvme_attach_controller(&ctx->req);
249 	free(ctx);
250 }
251 
252 static void
253 rpc_bdev_nvme_attach_controller_done(void *cb_ctx, size_t bdev_count, int rc)
254 {
255 	struct rpc_bdev_nvme_attach_controller_ctx *ctx = cb_ctx;
256 	struct spdk_jsonrpc_request *request = ctx->request;
257 
258 	if (rc < 0) {
259 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
260 		free_rpc_bdev_nvme_attach_controller(&ctx->req);
261 		free(ctx);
262 		return;
263 	}
264 
265 	ctx->bdev_count = bdev_count;
266 	spdk_bdev_wait_for_examine(rpc_bdev_nvme_attach_controller_examined, ctx);
267 }
268 
269 static void
270 rpc_bdev_nvme_attach_controller(struct spdk_jsonrpc_request *request,
271 				const struct spdk_json_val *params)
272 {
273 	struct rpc_bdev_nvme_attach_controller_ctx *ctx;
274 	struct spdk_nvme_transport_id trid = {};
275 	struct spdk_nvme_host_id hostid = {};
276 	uint32_t prchk_flags = 0;
277 	struct nvme_ctrlr *ctrlr = NULL;
278 	size_t len, maxlen;
279 	int rc;
280 
281 	ctx = calloc(1, sizeof(*ctx));
282 	if (!ctx) {
283 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
284 		return;
285 	}
286 
287 	spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctx->req.opts, sizeof(ctx->req.opts));
288 
289 	if (spdk_json_decode_object(params, rpc_bdev_nvme_attach_controller_decoders,
290 				    SPDK_COUNTOF(rpc_bdev_nvme_attach_controller_decoders),
291 				    &ctx->req)) {
292 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
293 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
294 						 "spdk_json_decode_object failed");
295 		goto cleanup;
296 	}
297 
298 	/* Parse trstring */
299 	rc = spdk_nvme_transport_id_populate_trstring(&trid, ctx->req.trtype);
300 	if (rc < 0) {
301 		SPDK_ERRLOG("Failed to parse trtype: %s\n", ctx->req.trtype);
302 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s",
303 						     ctx->req.trtype);
304 		goto cleanup;
305 	}
306 
307 	/* Parse trtype */
308 	rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, ctx->req.trtype);
309 	assert(rc == 0);
310 
311 	ctrlr = nvme_ctrlr_get_by_name(ctx->req.name);
312 
313 	/* Parse traddr */
314 	maxlen = sizeof(trid.traddr);
315 	len = strnlen(ctx->req.traddr, maxlen);
316 	if (len == maxlen) {
317 		spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s",
318 						     ctx->req.traddr);
319 		goto cleanup;
320 	}
321 	memcpy(trid.traddr, ctx->req.traddr, len + 1);
322 
323 	/* Parse adrfam */
324 	if (ctx->req.adrfam) {
325 		rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, ctx->req.adrfam);
326 		if (rc < 0) {
327 			SPDK_ERRLOG("Failed to parse adrfam: %s\n", ctx->req.adrfam);
328 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s",
329 							     ctx->req.adrfam);
330 			goto cleanup;
331 		}
332 	}
333 
334 	/* Parse trsvcid */
335 	if (ctx->req.trsvcid) {
336 		maxlen = sizeof(trid.trsvcid);
337 		len = strnlen(ctx->req.trsvcid, maxlen);
338 		if (len == maxlen) {
339 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s",
340 							     ctx->req.trsvcid);
341 			goto cleanup;
342 		}
343 		memcpy(trid.trsvcid, ctx->req.trsvcid, len + 1);
344 	}
345 
346 	/* Parse priority for the NVMe-oF transport connection */
347 	if (ctx->req.priority) {
348 		trid.priority = spdk_strtol(ctx->req.priority, 10);
349 	}
350 
351 	/* Parse subnqn */
352 	if (ctx->req.subnqn) {
353 		maxlen = sizeof(trid.subnqn);
354 		len = strnlen(ctx->req.subnqn, maxlen);
355 		if (len == maxlen) {
356 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s",
357 							     ctx->req.subnqn);
358 			goto cleanup;
359 		}
360 		memcpy(trid.subnqn, ctx->req.subnqn, len + 1);
361 	}
362 
363 	if (ctrlr && (ctx->req.hostaddr || ctx->req.hostnqn || ctx->req.hostsvcid || ctx->req.prchk_guard ||
364 		      ctx->req.prchk_reftag)) {
365 		goto conflicting_arguments;
366 	}
367 
368 	if (ctx->req.hostaddr) {
369 		maxlen = sizeof(hostid.hostaddr);
370 		len = strnlen(ctx->req.hostaddr, maxlen);
371 		if (len == maxlen) {
372 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostaddr too long: %s",
373 							     ctx->req.hostaddr);
374 			goto cleanup;
375 		}
376 		memcpy(hostid.hostaddr, ctx->req.hostaddr, len + 1);
377 	}
378 
379 	if (ctx->req.hostsvcid) {
380 		maxlen = sizeof(hostid.hostsvcid);
381 		len = strnlen(ctx->req.hostsvcid, maxlen);
382 		if (len == maxlen) {
383 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "hostsvcid too long: %s",
384 							     ctx->req.hostsvcid);
385 			goto cleanup;
386 		}
387 		memcpy(hostid.hostsvcid, ctx->req.hostsvcid, len + 1);
388 	}
389 
390 	if (ctx->req.prchk_reftag) {
391 		prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG;
392 	}
393 
394 	if (ctx->req.prchk_guard) {
395 		prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD;
396 	}
397 
398 	ctx->request = request;
399 	ctx->count = NVME_MAX_BDEVS_PER_RPC;
400 	rc = bdev_nvme_create(&trid, &hostid, ctx->req.name, ctx->names, ctx->count, ctx->req.hostnqn,
401 			      prchk_flags, rpc_bdev_nvme_attach_controller_done, ctx, &ctx->req.opts);
402 	if (rc) {
403 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
404 		goto cleanup;
405 	}
406 
407 	return;
408 
409 conflicting_arguments:
410 	spdk_jsonrpc_send_error_response_fmt(request, -EINVAL,
411 					     "Invalid agrgument list. Existing controller name cannot be combined with host information or PI options.\n");
412 cleanup:
413 	free_rpc_bdev_nvme_attach_controller(&ctx->req);
414 	free(ctx);
415 }
416 SPDK_RPC_REGISTER("bdev_nvme_attach_controller", rpc_bdev_nvme_attach_controller,
417 		  SPDK_RPC_RUNTIME)
418 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_attach_controller, construct_nvme_bdev)
419 
420 static void
421 rpc_dump_nvme_controller_info(struct nvme_ctrlr *nvme_ctrlr, void *ctx)
422 {
423 	struct spdk_json_write_ctx	*w = ctx;
424 	struct spdk_nvme_transport_id	*trid;
425 
426 	trid = nvme_ctrlr->connected_trid;
427 
428 	spdk_json_write_object_begin(w);
429 	spdk_json_write_named_string(w, "name", nvme_ctrlr->name);
430 
431 #ifdef SPDK_CONFIG_NVME_CUSE
432 	size_t cuse_name_size = 128;
433 	char cuse_name[cuse_name_size];
434 
435 	int rc = spdk_nvme_cuse_get_ctrlr_name(nvme_ctrlr->ctrlr, cuse_name, &cuse_name_size);
436 	if (rc == 0) {
437 		spdk_json_write_named_string(w, "cuse_device", cuse_name);
438 	}
439 #endif
440 
441 	spdk_json_write_named_object_begin(w, "trid");
442 	nvme_bdev_dump_trid_json(trid, w);
443 	spdk_json_write_object_end(w);
444 
445 	spdk_json_write_object_end(w);
446 }
447 
448 struct rpc_bdev_nvme_get_controllers {
449 	char *name;
450 };
451 
452 static void
453 free_rpc_bdev_nvme_get_controllers(struct rpc_bdev_nvme_get_controllers *r)
454 {
455 	free(r->name);
456 }
457 
458 static const struct spdk_json_object_decoder rpc_bdev_nvme_get_controllers_decoders[] = {
459 	{"name", offsetof(struct rpc_bdev_nvme_get_controllers, name), spdk_json_decode_string, true},
460 };
461 
462 static void
463 rpc_bdev_nvme_get_controllers(struct spdk_jsonrpc_request *request,
464 			      const struct spdk_json_val *params)
465 {
466 	struct rpc_bdev_nvme_get_controllers req = {};
467 	struct spdk_json_write_ctx *w;
468 	struct nvme_ctrlr *ctrlr = NULL;
469 
470 	if (params && spdk_json_decode_object(params, rpc_bdev_nvme_get_controllers_decoders,
471 					      SPDK_COUNTOF(rpc_bdev_nvme_get_controllers_decoders),
472 					      &req)) {
473 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
474 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
475 						 "spdk_json_decode_object failed");
476 		goto cleanup;
477 	}
478 
479 	if (req.name) {
480 		ctrlr = nvme_ctrlr_get_by_name(req.name);
481 		if (ctrlr == NULL) {
482 			SPDK_ERRLOG("ctrlr '%s' does not exist\n", req.name);
483 			spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Controller %s does not exist", req.name);
484 			goto cleanup;
485 		}
486 	}
487 
488 	w = spdk_jsonrpc_begin_result(request);
489 	spdk_json_write_array_begin(w);
490 
491 	if (ctrlr != NULL) {
492 		rpc_dump_nvme_controller_info(ctrlr, w);
493 	} else {
494 		nvme_ctrlr_for_each(rpc_dump_nvme_controller_info, w);
495 	}
496 
497 	spdk_json_write_array_end(w);
498 
499 	spdk_jsonrpc_end_result(request, w);
500 
501 cleanup:
502 	free_rpc_bdev_nvme_get_controllers(&req);
503 }
504 SPDK_RPC_REGISTER("bdev_nvme_get_controllers", rpc_bdev_nvme_get_controllers, SPDK_RPC_RUNTIME)
505 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_get_controllers, get_nvme_controllers)
506 
507 struct rpc_bdev_nvme_detach_controller {
508 	char *name;
509 	char *trtype;
510 	char *adrfam;
511 	char *traddr;
512 	char *trsvcid;
513 	char *subnqn;
514 };
515 
516 static void
517 free_rpc_bdev_nvme_detach_controller(struct rpc_bdev_nvme_detach_controller *req)
518 {
519 	free(req->name);
520 	free(req->trtype);
521 	free(req->adrfam);
522 	free(req->traddr);
523 	free(req->trsvcid);
524 	free(req->subnqn);
525 }
526 
527 static const struct spdk_json_object_decoder rpc_bdev_nvme_detach_controller_decoders[] = {
528 	{"name", offsetof(struct rpc_bdev_nvme_detach_controller, name), spdk_json_decode_string},
529 	{"trtype", offsetof(struct rpc_bdev_nvme_detach_controller, trtype), spdk_json_decode_string, true},
530 	{"traddr", offsetof(struct rpc_bdev_nvme_detach_controller, traddr), spdk_json_decode_string, true},
531 	{"adrfam", offsetof(struct rpc_bdev_nvme_detach_controller, adrfam), spdk_json_decode_string, true},
532 	{"trsvcid", offsetof(struct rpc_bdev_nvme_detach_controller, trsvcid), spdk_json_decode_string, true},
533 	{"subnqn", offsetof(struct rpc_bdev_nvme_detach_controller, subnqn), spdk_json_decode_string, true},
534 };
535 
536 static void
537 rpc_bdev_nvme_detach_controller(struct spdk_jsonrpc_request *request,
538 				const struct spdk_json_val *params)
539 {
540 	struct rpc_bdev_nvme_detach_controller req = {NULL};
541 	struct spdk_nvme_transport_id trid = {};
542 	size_t len, maxlen;
543 	int rc = 0;
544 	bool all_trid_entries, one_trid_entry;
545 
546 	if (spdk_json_decode_object(params, rpc_bdev_nvme_detach_controller_decoders,
547 				    SPDK_COUNTOF(rpc_bdev_nvme_detach_controller_decoders),
548 				    &req)) {
549 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
550 						 "spdk_json_decode_object failed");
551 		goto cleanup;
552 	}
553 
554 	all_trid_entries = req.trtype && req.traddr && req.adrfam && req.trsvcid && req.subnqn;
555 	one_trid_entry = req.trtype || req.traddr || req.adrfam || req.trsvcid || req.subnqn;
556 
557 	if (all_trid_entries ^ one_trid_entry) {
558 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
559 						 "trtype, traddr, adrfam, trsvcid, subnqn must all be provided together or not at all.");
560 		goto cleanup;
561 	}
562 
563 	if (all_trid_entries) {
564 		/* Parse trtype */
565 		rc = spdk_nvme_transport_id_parse_trtype(&trid.trtype, req.trtype);
566 		if (rc < 0) {
567 			SPDK_ERRLOG("Failed to parse trtype: %s\n", req.trtype);
568 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse trtype: %s",
569 							     req.trtype);
570 			goto cleanup;
571 		}
572 
573 		/* Parse traddr */
574 		maxlen = sizeof(trid.traddr);
575 		len = strnlen(req.traddr, maxlen);
576 		if (len == maxlen) {
577 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "traddr too long: %s",
578 							     req.traddr);
579 			goto cleanup;
580 		}
581 		memcpy(trid.traddr, req.traddr, len + 1);
582 
583 		rc = spdk_nvme_transport_id_parse_adrfam(&trid.adrfam, req.adrfam);
584 		if (rc < 0) {
585 			SPDK_ERRLOG("Failed to parse adrfam: %s\n", req.adrfam);
586 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "Failed to parse adrfam: %s",
587 							     req.adrfam);
588 			goto cleanup;
589 		}
590 
591 		maxlen = sizeof(trid.trsvcid);
592 		len = strnlen(req.trsvcid, maxlen);
593 		if (len == maxlen) {
594 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "trsvcid too long: %s",
595 							     req.trsvcid);
596 			goto cleanup;
597 		}
598 		memcpy(trid.trsvcid, req.trsvcid, len + 1);
599 
600 		maxlen = sizeof(trid.subnqn);
601 		len = strnlen(req.subnqn, maxlen);
602 		if (len == maxlen) {
603 			spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, "subnqn too long: %s",
604 							     req.subnqn);
605 			goto cleanup;
606 		}
607 		memcpy(trid.subnqn, req.subnqn, len + 1);
608 		rc = bdev_nvme_delete(req.name, &trid);
609 	} else {
610 		rc = bdev_nvme_delete(req.name, NULL);
611 	}
612 
613 	if (rc != 0) {
614 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
615 		goto cleanup;
616 	}
617 
618 	spdk_jsonrpc_send_bool_response(request, true);
619 
620 cleanup:
621 	free_rpc_bdev_nvme_detach_controller(&req);
622 }
623 SPDK_RPC_REGISTER("bdev_nvme_detach_controller", rpc_bdev_nvme_detach_controller,
624 		  SPDK_RPC_RUNTIME)
625 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_detach_controller, delete_nvme_controller)
626 
627 struct rpc_apply_firmware {
628 	char *filename;
629 	char *bdev_name;
630 };
631 
632 static void
633 free_rpc_apply_firmware(struct rpc_apply_firmware *req)
634 {
635 	free(req->filename);
636 	free(req->bdev_name);
637 }
638 
639 static const struct spdk_json_object_decoder rpc_apply_firmware_decoders[] = {
640 	{"filename", offsetof(struct rpc_apply_firmware, filename), spdk_json_decode_string},
641 	{"bdev_name", offsetof(struct rpc_apply_firmware, bdev_name), spdk_json_decode_string},
642 };
643 
644 struct firmware_update_info {
645 	void				*fw_image;
646 	void				*p;
647 	unsigned int			size;
648 	unsigned int			size_remaining;
649 	unsigned int			offset;
650 	unsigned int			transfer;
651 
652 	void				*desc;
653 	struct spdk_io_channel		*ch;
654 	struct spdk_jsonrpc_request	*request;
655 	struct spdk_nvme_ctrlr		*ctrlr;
656 	open_descriptors_t		desc_head;
657 	struct rpc_apply_firmware	*req;
658 };
659 
660 static void
661 _apply_firmware_cleanup(void *ctx)
662 {
663 	struct spdk_bdev_desc *desc = ctx;
664 
665 	spdk_bdev_close(desc);
666 }
667 
668 static void
669 apply_firmware_cleanup(void *cb_arg)
670 {
671 	struct open_descriptors			*opt, *tmp;
672 	struct firmware_update_info *firm_ctx = cb_arg;
673 
674 	if (!firm_ctx) {
675 		return;
676 	}
677 
678 	if (firm_ctx->fw_image) {
679 		spdk_free(firm_ctx->fw_image);
680 	}
681 
682 	if (firm_ctx->req) {
683 		free_rpc_apply_firmware(firm_ctx->req);
684 		free(firm_ctx->req);
685 	}
686 
687 	if (firm_ctx->ch) {
688 		spdk_put_io_channel(firm_ctx->ch);
689 	}
690 
691 	TAILQ_FOREACH_SAFE(opt, &firm_ctx->desc_head, tqlst, tmp) {
692 		TAILQ_REMOVE(&firm_ctx->desc_head, opt, tqlst);
693 		/* Close the underlying bdev on its same opened thread. */
694 		if (opt->thread && opt->thread != spdk_get_thread()) {
695 			spdk_thread_send_msg(opt->thread, _apply_firmware_cleanup, opt->desc);
696 		} else {
697 			spdk_bdev_close(opt->desc);
698 		}
699 		free(opt);
700 	}
701 	free(firm_ctx);
702 }
703 
704 static void
705 apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
706 {
707 	struct spdk_json_write_ctx		*w;
708 	struct firmware_update_info *firm_ctx = cb_arg;
709 
710 	spdk_bdev_free_io(bdev_io);
711 
712 	if (!success) {
713 		spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
714 						 "firmware commit failed.");
715 		apply_firmware_cleanup(firm_ctx);
716 		return;
717 	}
718 
719 	if (spdk_nvme_ctrlr_reset(firm_ctx->ctrlr) != 0) {
720 		spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
721 						 "Controller reset failed.");
722 		apply_firmware_cleanup(firm_ctx);
723 		return;
724 	}
725 
726 	w = spdk_jsonrpc_begin_result(firm_ctx->request);
727 	spdk_json_write_string(w, "firmware commit succeeded. Controller reset in progress.");
728 	spdk_jsonrpc_end_result(firm_ctx->request, w);
729 	apply_firmware_cleanup(firm_ctx);
730 }
731 
732 static void
733 apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
734 {
735 	struct spdk_nvme_cmd			cmd = {};
736 	struct spdk_nvme_fw_commit		fw_commit;
737 	int					slot = 0;
738 	int					rc;
739 	struct firmware_update_info *firm_ctx = cb_arg;
740 	enum spdk_nvme_fw_commit_action commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG;
741 
742 	if (!success) {
743 		spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
744 						 "firmware download failed .");
745 		spdk_bdev_free_io(bdev_io);
746 		apply_firmware_cleanup(firm_ctx);
747 		return;
748 	}
749 
750 	firm_ctx->p += firm_ctx->transfer;
751 	firm_ctx->offset += firm_ctx->transfer;
752 	firm_ctx->size_remaining -= firm_ctx->transfer;
753 
754 	switch (firm_ctx->size_remaining) {
755 	case 0:
756 		/* firmware download completed. Commit firmware */
757 		memset(&fw_commit, 0, sizeof(struct spdk_nvme_fw_commit));
758 		fw_commit.fs = slot;
759 		fw_commit.ca = commit_action;
760 
761 		cmd.opc = SPDK_NVME_OPC_FIRMWARE_COMMIT;
762 		memcpy(&cmd.cdw10, &fw_commit, sizeof(uint32_t));
763 		rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, NULL, 0,
764 						   apply_firmware_complete_reset, firm_ctx);
765 		if (rc) {
766 			spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
767 							 "firmware commit failed.");
768 			spdk_bdev_free_io(bdev_io);
769 			apply_firmware_cleanup(firm_ctx);
770 			return;
771 		}
772 		break;
773 	default:
774 		firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096);
775 		cmd.opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD;
776 
777 		cmd.cdw10 = spdk_nvme_bytes_to_numd(firm_ctx->transfer);
778 		cmd.cdw11 = firm_ctx->offset >> 2;
779 		rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, &cmd, firm_ctx->p,
780 						   firm_ctx->transfer, apply_firmware_complete, firm_ctx);
781 		if (rc) {
782 			spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
783 							 "firmware download failed.");
784 			spdk_bdev_free_io(bdev_io);
785 			apply_firmware_cleanup(firm_ctx);
786 			return;
787 		}
788 		break;
789 	}
790 }
791 
792 static void
793 apply_firmware_open_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx)
794 {
795 }
796 
797 static void
798 rpc_bdev_nvme_apply_firmware(struct spdk_jsonrpc_request *request,
799 			     const struct spdk_json_val *params)
800 {
801 	int					rc;
802 	int					fd = -1;
803 	struct stat				fw_stat;
804 	struct spdk_nvme_ctrlr			*ctrlr;
805 	char					msg[1024];
806 	struct spdk_bdev			*bdev;
807 	struct spdk_bdev			*bdev2;
808 	struct open_descriptors			*opt;
809 	struct spdk_bdev_desc			*desc;
810 	struct spdk_nvme_cmd			*cmd;
811 	struct firmware_update_info		*firm_ctx;
812 
813 	firm_ctx = calloc(1, sizeof(struct firmware_update_info));
814 	if (!firm_ctx) {
815 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
816 						 "Memory allocation error.");
817 		return;
818 	}
819 	firm_ctx->fw_image = NULL;
820 	TAILQ_INIT(&firm_ctx->desc_head);
821 	firm_ctx->request = request;
822 
823 	firm_ctx->req = calloc(1, sizeof(struct rpc_apply_firmware));
824 	if (!firm_ctx->req) {
825 		snprintf(msg, sizeof(msg), "Memory allocation error.");
826 		goto err;
827 	}
828 
829 	if (spdk_json_decode_object(params, rpc_apply_firmware_decoders,
830 				    SPDK_COUNTOF(rpc_apply_firmware_decoders), firm_ctx->req)) {
831 		snprintf(msg, sizeof(msg), "spdk_json_decode_object failed.");
832 		goto err;
833 	}
834 
835 	if ((bdev = spdk_bdev_get_by_name(firm_ctx->req->bdev_name)) == NULL) {
836 		snprintf(msg, sizeof(msg), "bdev %s were not found", firm_ctx->req->bdev_name);
837 		goto err;
838 	}
839 
840 	if ((ctrlr = bdev_nvme_get_ctrlr(bdev)) == NULL) {
841 		snprintf(msg, sizeof(msg), "Controller information for %s were not found.",
842 			 firm_ctx->req->bdev_name);
843 		goto err;
844 	}
845 	firm_ctx->ctrlr = ctrlr;
846 
847 	for (bdev2 = spdk_bdev_first(); bdev2; bdev2 = spdk_bdev_next(bdev2)) {
848 
849 		if (bdev_nvme_get_ctrlr(bdev2) != ctrlr) {
850 			continue;
851 		}
852 
853 		if (!(opt = malloc(sizeof(struct open_descriptors)))) {
854 			snprintf(msg, sizeof(msg), "Memory allocation error.");
855 			goto err;
856 		}
857 
858 		if (spdk_bdev_open_ext(spdk_bdev_get_name(bdev2), true, apply_firmware_open_cb, NULL, &desc) != 0) {
859 			snprintf(msg, sizeof(msg), "Device %s is in use.", firm_ctx->req->bdev_name);
860 			free(opt);
861 			goto err;
862 		}
863 
864 		/* Save the thread where the base device is opened */
865 		opt->thread = spdk_get_thread();
866 
867 		opt->desc = desc;
868 		opt->bdev = bdev;
869 		TAILQ_INSERT_TAIL(&firm_ctx->desc_head, opt, tqlst);
870 	}
871 
872 	/*
873 	 * find a descriptor associated with our bdev
874 	 */
875 	firm_ctx->desc = NULL;
876 	TAILQ_FOREACH(opt, &firm_ctx->desc_head, tqlst) {
877 		if (opt->bdev == bdev) {
878 			firm_ctx->desc = opt->desc;
879 			break;
880 		}
881 	}
882 
883 	if (!firm_ctx->desc) {
884 		snprintf(msg, sizeof(msg), "No descriptor were found.");
885 		goto err;
886 	}
887 
888 	firm_ctx->ch = spdk_bdev_get_io_channel(firm_ctx->desc);
889 	if (!firm_ctx->ch) {
890 		snprintf(msg, sizeof(msg), "No channels were found.");
891 		goto err;
892 	}
893 
894 	fd = open(firm_ctx->req->filename, O_RDONLY);
895 	if (fd < 0) {
896 		snprintf(msg, sizeof(msg), "open file failed.");
897 		goto err;
898 	}
899 
900 	rc = fstat(fd, &fw_stat);
901 	if (rc < 0) {
902 		close(fd);
903 		snprintf(msg, sizeof(msg), "fstat failed.");
904 		goto err;
905 	}
906 
907 	firm_ctx->size = fw_stat.st_size;
908 	if (fw_stat.st_size % 4) {
909 		close(fd);
910 		snprintf(msg, sizeof(msg), "Firmware image size is not multiple of 4.");
911 		goto err;
912 	}
913 
914 	firm_ctx->fw_image = spdk_zmalloc(firm_ctx->size, 4096, NULL,
915 					  SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
916 	if (!firm_ctx->fw_image) {
917 		close(fd);
918 		snprintf(msg, sizeof(msg), "Memory allocation error.");
919 		goto err;
920 	}
921 	firm_ctx->p = firm_ctx->fw_image;
922 
923 	if (read(fd, firm_ctx->p, firm_ctx->size) != ((ssize_t)(firm_ctx->size))) {
924 		close(fd);
925 		snprintf(msg, sizeof(msg), "Read firmware image failed!");
926 		goto err;
927 	}
928 	close(fd);
929 
930 	firm_ctx->offset = 0;
931 	firm_ctx->size_remaining = firm_ctx->size;
932 	firm_ctx->transfer = spdk_min(firm_ctx->size_remaining, 4096);
933 
934 	cmd = malloc(sizeof(struct spdk_nvme_cmd));
935 	if (!cmd) {
936 		snprintf(msg, sizeof(msg), "Memory allocation error.");
937 		goto err;
938 	}
939 	memset(cmd, 0, sizeof(struct spdk_nvme_cmd));
940 	cmd->opc = SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD;
941 
942 	cmd->cdw10 = spdk_nvme_bytes_to_numd(firm_ctx->transfer);
943 	cmd->cdw11 = firm_ctx->offset >> 2;
944 
945 	rc = spdk_bdev_nvme_admin_passthru(firm_ctx->desc, firm_ctx->ch, cmd, firm_ctx->p,
946 					   firm_ctx->transfer, apply_firmware_complete, firm_ctx);
947 	if (rc == 0) {
948 		/* normal return here. */
949 		return;
950 	}
951 
952 	free(cmd);
953 	snprintf(msg, sizeof(msg), "Read firmware image failed!");
954 err:
955 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, msg);
956 	apply_firmware_cleanup(firm_ctx);
957 }
958 SPDK_RPC_REGISTER("bdev_nvme_apply_firmware", rpc_bdev_nvme_apply_firmware, SPDK_RPC_RUNTIME)
959 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_nvme_apply_firmware, apply_nvme_firmware)
960 
961 struct rpc_bdev_nvme_transport_stat_ctx {
962 	struct spdk_jsonrpc_request *request;
963 	struct spdk_json_write_ctx *w;
964 };
965 
966 static void
967 rpc_bdev_nvme_rdma_stats(struct spdk_json_write_ctx *w,
968 			 struct spdk_nvme_transport_poll_group_stat *stat)
969 {
970 	struct spdk_nvme_rdma_device_stat *device_stats;
971 	uint32_t i;
972 
973 	spdk_json_write_named_array_begin(w, "devices");
974 
975 	for (i = 0; i < stat->rdma.num_devices; i++) {
976 		device_stats = &stat->rdma.device_stats[i];
977 		spdk_json_write_object_begin(w);
978 		spdk_json_write_named_string(w, "dev_name", device_stats->name);
979 		spdk_json_write_named_uint64(w, "polls", device_stats->polls);
980 		spdk_json_write_named_uint64(w, "idle_polls", device_stats->idle_polls);
981 		spdk_json_write_named_uint64(w, "completions", device_stats->completions);
982 		spdk_json_write_named_uint64(w, "queued_requests", device_stats->queued_requests);
983 		spdk_json_write_named_uint64(w, "total_send_wrs", device_stats->total_send_wrs);
984 		spdk_json_write_named_uint64(w, "send_doorbell_updates", device_stats->send_doorbell_updates);
985 		spdk_json_write_named_uint64(w, "total_recv_wrs", device_stats->total_recv_wrs);
986 		spdk_json_write_named_uint64(w, "recv_doorbell_updates", device_stats->recv_doorbell_updates);
987 		spdk_json_write_object_end(w);
988 	}
989 	spdk_json_write_array_end(w);
990 }
991 
992 static void
993 rpc_bdev_nvme_pcie_stats(struct spdk_json_write_ctx *w,
994 			 struct spdk_nvme_transport_poll_group_stat *stat)
995 {
996 	spdk_json_write_named_uint64(w, "polls", stat->pcie.polls);
997 	spdk_json_write_named_uint64(w, "idle_polls", stat->pcie.idle_polls);
998 	spdk_json_write_named_uint64(w, "completions", stat->pcie.completions);
999 	spdk_json_write_named_uint64(w, "cq_doorbell_updates", stat->pcie.cq_doorbell_updates);
1000 	spdk_json_write_named_uint64(w, "queued_requests", stat->pcie.queued_requests);
1001 	spdk_json_write_named_uint64(w, "submitted_requests", stat->pcie.submitted_requests);
1002 	spdk_json_write_named_uint64(w, "sq_doobell_updates", stat->pcie.sq_doobell_updates);
1003 }
1004 
1005 static void
1006 rpc_bdev_nvme_stats_per_channel(struct spdk_io_channel_iter *i)
1007 {
1008 	struct rpc_bdev_nvme_transport_stat_ctx *ctx;
1009 	struct spdk_io_channel *ch;
1010 	struct nvme_poll_group *group;
1011 	struct spdk_nvme_poll_group_stat *stat;
1012 	struct spdk_nvme_transport_poll_group_stat *tr_stat;
1013 	uint32_t j;
1014 	int rc;
1015 
1016 	ctx = spdk_io_channel_iter_get_ctx(i);
1017 	ch = spdk_io_channel_iter_get_channel(i);
1018 	group = spdk_io_channel_get_ctx(ch);
1019 
1020 	rc = spdk_nvme_poll_group_get_stats(group->group, &stat);
1021 	if (rc) {
1022 		spdk_for_each_channel_continue(i, rc);
1023 		return;
1024 	}
1025 
1026 	spdk_json_write_object_begin(ctx->w);
1027 	spdk_json_write_named_string(ctx->w, "thread", spdk_thread_get_name(spdk_get_thread()));
1028 	spdk_json_write_named_array_begin(ctx->w, "transports");
1029 
1030 	for (j = 0; j < stat->num_transports; j++) {
1031 		tr_stat = stat->transport_stat[j];
1032 		spdk_json_write_object_begin(ctx->w);
1033 		spdk_json_write_named_string(ctx->w, "trname", spdk_nvme_transport_id_trtype_str(tr_stat->trtype));
1034 
1035 		switch (stat->transport_stat[j]->trtype) {
1036 		case SPDK_NVME_TRANSPORT_RDMA:
1037 			rpc_bdev_nvme_rdma_stats(ctx->w, tr_stat);
1038 			break;
1039 		case SPDK_NVME_TRANSPORT_PCIE:
1040 			rpc_bdev_nvme_pcie_stats(ctx->w, tr_stat);
1041 			break;
1042 		default:
1043 			SPDK_WARNLOG("Can't handle trtype %d %s\n", tr_stat->trtype,
1044 				     spdk_nvme_transport_id_trtype_str(tr_stat->trtype));
1045 		}
1046 		spdk_json_write_object_end(ctx->w);
1047 	}
1048 	/* transports array */
1049 	spdk_json_write_array_end(ctx->w);
1050 	spdk_json_write_object_end(ctx->w);
1051 
1052 	spdk_nvme_poll_group_free_stats(group->group, stat);
1053 	spdk_for_each_channel_continue(i, 0);
1054 }
1055 
1056 static void
1057 rpc_bdev_nvme_stats_done(struct spdk_io_channel_iter *i, int status)
1058 {
1059 	struct rpc_bdev_nvme_transport_stat_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1060 
1061 	spdk_json_write_array_end(ctx->w);
1062 	spdk_json_write_object_end(ctx->w);
1063 	spdk_jsonrpc_end_result(ctx->request, ctx->w);
1064 	free(ctx);
1065 }
1066 
1067 static void
1068 rpc_bdev_nvme_get_transport_statistics(struct spdk_jsonrpc_request *request,
1069 				       const struct spdk_json_val *params)
1070 {
1071 	struct rpc_bdev_nvme_transport_stat_ctx *ctx;
1072 
1073 	if (params) {
1074 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1075 						 "'bdev_nvme_get_transport_statistics' requires no arguments");
1076 		return;
1077 	}
1078 
1079 	ctx = calloc(1, sizeof(*ctx));
1080 	if (!ctx) {
1081 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1082 						 "Memory allocation error");
1083 		return;
1084 	}
1085 	ctx->request = request;
1086 	ctx->w = spdk_jsonrpc_begin_result(ctx->request);
1087 	spdk_json_write_object_begin(ctx->w);
1088 	spdk_json_write_named_array_begin(ctx->w, "poll_groups");
1089 
1090 	spdk_for_each_channel(&g_nvme_ctrlrs,
1091 			      rpc_bdev_nvme_stats_per_channel,
1092 			      ctx,
1093 			      rpc_bdev_nvme_stats_done);
1094 }
1095 SPDK_RPC_REGISTER("bdev_nvme_get_transport_statistics", rpc_bdev_nvme_get_transport_statistics,
1096 		  SPDK_RPC_RUNTIME)
1097 
1098 struct rpc_bdev_nvme_reset_controller_req {
1099 	char *name;
1100 };
1101 
1102 static void
1103 free_rpc_bdev_nvme_reset_controller_req(struct rpc_bdev_nvme_reset_controller_req *r)
1104 {
1105 	free(r->name);
1106 }
1107 
1108 static const struct spdk_json_object_decoder rpc_bdev_nvme_reset_controller_req_decoders[] = {
1109 	{"name", offsetof(struct rpc_bdev_nvme_reset_controller_req, name), spdk_json_decode_string},
1110 };
1111 
1112 static void
1113 _rpc_bdev_nvme_reset_controller_cb(void *cb_arg, int rc)
1114 {
1115 	struct spdk_jsonrpc_request *request = cb_arg;
1116 
1117 	spdk_jsonrpc_send_bool_response(request, rc == 0);
1118 }
1119 
1120 static void
1121 rpc_bdev_nvme_reset_controller(struct spdk_jsonrpc_request *request,
1122 			       const struct spdk_json_val *params)
1123 {
1124 	struct rpc_bdev_nvme_reset_controller_req req = {NULL};
1125 	struct nvme_ctrlr *nvme_ctrlr;
1126 	int rc;
1127 
1128 	if (spdk_json_decode_object(params, rpc_bdev_nvme_reset_controller_req_decoders,
1129 				    SPDK_COUNTOF(rpc_bdev_nvme_reset_controller_req_decoders),
1130 				    &req)) {
1131 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1132 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(EINVAL));
1133 		goto cleanup;
1134 	}
1135 
1136 	nvme_ctrlr = nvme_ctrlr_get_by_name(req.name);
1137 	if (nvme_ctrlr == NULL) {
1138 		SPDK_ERRLOG("Failed at device lookup\n");
1139 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
1140 		goto cleanup;
1141 	}
1142 
1143 	rc = bdev_nvme_reset_rpc(nvme_ctrlr, _rpc_bdev_nvme_reset_controller_cb, request);
1144 	if (rc != 0) {
1145 		SPDK_NOTICELOG("Failed at bdev_nvme_reset_rpc\n");
1146 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc));
1147 	}
1148 
1149 cleanup:
1150 	free_rpc_bdev_nvme_reset_controller_req(&req);
1151 }
1152 SPDK_RPC_REGISTER("bdev_nvme_reset_controller", rpc_bdev_nvme_reset_controller, SPDK_RPC_RUNTIME)
1153 
1154 struct rpc_get_controller_health_info {
1155 	char *name;
1156 };
1157 
1158 struct spdk_nvme_health_info_context {
1159 	struct spdk_jsonrpc_request *request;
1160 	struct spdk_nvme_ctrlr *ctrlr;
1161 	struct spdk_nvme_health_information_page health_page;
1162 };
1163 
1164 static void
1165 free_rpc_get_controller_health_info(struct rpc_get_controller_health_info *r)
1166 {
1167 	free(r->name);
1168 }
1169 
1170 static const struct spdk_json_object_decoder rpc_get_controller_health_info_decoders[] = {
1171 	{"name", offsetof(struct rpc_get_controller_health_info, name), spdk_json_decode_string, true},
1172 };
1173 
1174 static void nvme_health_info_cleanup(struct spdk_nvme_health_info_context *context, bool response)
1175 {
1176 	if (response == true) {
1177 		spdk_jsonrpc_send_error_response(context->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1178 						 "Internal error.");
1179 	}
1180 
1181 	free(context);
1182 }
1183 
1184 static void
1185 get_health_log_page_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
1186 {
1187 	int i;
1188 	char buf[128];
1189 	struct spdk_nvme_health_info_context *context = cb_arg;
1190 	struct spdk_jsonrpc_request *request = context->request;
1191 	struct spdk_json_write_ctx *w;
1192 	struct spdk_nvme_ctrlr *ctrlr = context->ctrlr;
1193 	const struct spdk_nvme_transport_id *trid = NULL;
1194 	const struct spdk_nvme_ctrlr_data *cdata = NULL;
1195 	struct spdk_nvme_health_information_page *health_page = NULL;
1196 
1197 	if (spdk_nvme_cpl_is_error(cpl)) {
1198 		nvme_health_info_cleanup(context, true);
1199 		SPDK_ERRLOG("get log page failed\n");
1200 		return;
1201 	}
1202 
1203 	if (ctrlr == NULL) {
1204 		nvme_health_info_cleanup(context, true);
1205 		SPDK_ERRLOG("ctrlr is NULL\n");
1206 		return;
1207 	} else {
1208 		trid = spdk_nvme_ctrlr_get_transport_id(ctrlr);
1209 		cdata = spdk_nvme_ctrlr_get_data(ctrlr);
1210 		health_page = &(context->health_page);
1211 	}
1212 
1213 	w = spdk_jsonrpc_begin_result(request);
1214 
1215 	spdk_json_write_object_begin(w);
1216 	snprintf(buf, sizeof(cdata->mn) + 1, "%s", cdata->mn);
1217 	spdk_str_trim(buf);
1218 	spdk_json_write_named_string(w, "model_number", buf);
1219 	snprintf(buf, sizeof(cdata->sn) + 1, "%s", cdata->sn);
1220 	spdk_str_trim(buf);
1221 	spdk_json_write_named_string(w, "serial_number", buf);
1222 	snprintf(buf, sizeof(cdata->fr) + 1, "%s", cdata->fr);
1223 	spdk_str_trim(buf);
1224 	spdk_json_write_named_string(w, "firmware_revision", buf);
1225 	spdk_json_write_named_string(w, "traddr", trid->traddr);
1226 	spdk_json_write_named_uint64(w, "temperature_celsius", health_page->temperature - 273);
1227 	spdk_json_write_named_uint64(w, "available_spare_percentage", health_page->available_spare);
1228 	spdk_json_write_named_uint64(w, "available_spare_threshold_percentage",
1229 				     health_page->available_spare_threshold);
1230 	spdk_json_write_named_uint64(w, "percentage_used", health_page->percentage_used);
1231 	spdk_json_write_named_uint128(w, "data_units_read",
1232 				      health_page->data_units_read[0], health_page->data_units_read[1]);
1233 	spdk_json_write_named_uint128(w, "data_units_written",
1234 				      health_page->data_units_written[0], health_page->data_units_written[1]);
1235 	spdk_json_write_named_uint128(w, "host_read_commands",
1236 				      health_page->host_read_commands[0], health_page->host_read_commands[1]);
1237 	spdk_json_write_named_uint128(w, "host_write_commands",
1238 				      health_page->host_write_commands[0], health_page->host_write_commands[1]);
1239 	spdk_json_write_named_uint128(w, "controller_busy_time",
1240 				      health_page->controller_busy_time[0], health_page->controller_busy_time[1]);
1241 	spdk_json_write_named_uint128(w, "power_cycles",
1242 				      health_page->power_cycles[0], health_page->power_cycles[1]);
1243 	spdk_json_write_named_uint128(w, "power_on_hours",
1244 				      health_page->power_on_hours[0], health_page->power_on_hours[1]);
1245 	spdk_json_write_named_uint128(w, "unsafe_shutdowns",
1246 				      health_page->unsafe_shutdowns[0], health_page->unsafe_shutdowns[1]);
1247 	spdk_json_write_named_uint128(w, "media_errors",
1248 				      health_page->media_errors[0], health_page->media_errors[1]);
1249 	spdk_json_write_named_uint128(w, "num_err_log_entries",
1250 				      health_page->num_error_info_log_entries[0], health_page->num_error_info_log_entries[1]);
1251 	spdk_json_write_named_uint64(w, "warning_temperature_time_minutes", health_page->warning_temp_time);
1252 	spdk_json_write_named_uint64(w, "critical_composite_temperature_time_minutes",
1253 				     health_page->critical_temp_time);
1254 	for (i = 0; i < 8; i++) {
1255 		if (health_page->temp_sensor[i] != 0) {
1256 			spdk_json_write_named_uint64(w, "temperature_sensor_celsius", health_page->temp_sensor[i] - 273);
1257 		}
1258 	}
1259 	spdk_json_write_object_end(w);
1260 
1261 	spdk_jsonrpc_end_result(request, w);
1262 	nvme_health_info_cleanup(context, false);
1263 }
1264 
1265 static void
1266 get_health_log_page(struct spdk_nvme_health_info_context *context)
1267 {
1268 	struct spdk_nvme_ctrlr *ctrlr = context->ctrlr;
1269 
1270 	if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_HEALTH_INFORMATION,
1271 					     SPDK_NVME_GLOBAL_NS_TAG,
1272 					     &(context->health_page), sizeof(context->health_page), 0,
1273 					     get_health_log_page_completion, context)) {
1274 		nvme_health_info_cleanup(context, true);
1275 		SPDK_ERRLOG("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
1276 	}
1277 }
1278 
1279 static void
1280 get_temperature_threshold_feature_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
1281 {
1282 	struct spdk_nvme_health_info_context *context = cb_arg;
1283 
1284 	if (spdk_nvme_cpl_is_error(cpl)) {
1285 		nvme_health_info_cleanup(context, true);
1286 		SPDK_ERRLOG("feature SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD failed in completion\n");
1287 	} else {
1288 		get_health_log_page(context);
1289 	}
1290 }
1291 
1292 static int
1293 get_temperature_threshold_feature(struct spdk_nvme_health_info_context *context)
1294 {
1295 	struct spdk_nvme_cmd cmd = {};
1296 
1297 	cmd.opc = SPDK_NVME_OPC_GET_FEATURES;
1298 	cmd.cdw10 = SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD;
1299 
1300 	return spdk_nvme_ctrlr_cmd_admin_raw(context->ctrlr, &cmd, NULL, 0,
1301 					     get_temperature_threshold_feature_completion, context);
1302 }
1303 
1304 static void
1305 get_controller_health_info(struct spdk_jsonrpc_request *request, struct spdk_nvme_ctrlr *ctrlr)
1306 {
1307 	struct spdk_nvme_health_info_context *context;
1308 
1309 	context = calloc(1, sizeof(struct spdk_nvme_health_info_context));
1310 	if (!context) {
1311 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1312 						 "Memory allocation error.");
1313 		return;
1314 	}
1315 
1316 	context->request = request;
1317 	context->ctrlr = ctrlr;
1318 
1319 	if (get_temperature_threshold_feature(context)) {
1320 		nvme_health_info_cleanup(context, true);
1321 		SPDK_ERRLOG("feature SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD failed to submit\n");
1322 	}
1323 
1324 	return;
1325 }
1326 
1327 static void
1328 rpc_bdev_nvme_get_controller_health_info(struct spdk_jsonrpc_request *request,
1329 		const struct spdk_json_val *params)
1330 {
1331 	struct rpc_get_controller_health_info req = {};
1332 	struct nvme_ctrlr *nvme_ctrlr = NULL;
1333 
1334 	if (!params) {
1335 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1336 						 "Missing device name");
1337 
1338 		return;
1339 	}
1340 	if (spdk_json_decode_object(params, rpc_get_controller_health_info_decoders,
1341 				    SPDK_COUNTOF(rpc_get_controller_health_info_decoders), &req)) {
1342 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1343 		free_rpc_get_controller_health_info(&req);
1344 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1345 						 "Invalid parameters");
1346 
1347 		return;
1348 	}
1349 
1350 	nvme_ctrlr = nvme_ctrlr_get_by_name(req.name);
1351 
1352 	if (!nvme_ctrlr) {
1353 		SPDK_ERRLOG("nvme ctrlr name '%s' does not exist\n", req.name);
1354 		free_rpc_get_controller_health_info(&req);
1355 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1356 						 "Device not found");
1357 		return;
1358 	}
1359 
1360 	get_controller_health_info(request, nvme_ctrlr->ctrlr);
1361 	free_rpc_get_controller_health_info(&req);
1362 
1363 	return;
1364 }
1365 SPDK_RPC_REGISTER("bdev_nvme_get_controller_health_info",
1366 		  rpc_bdev_nvme_get_controller_health_info, SPDK_RPC_RUNTIME)
1367