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