xref: /spdk/lib/vhost/vhost_rpc.c (revision b119facb65247c714030aa19f3f0528bcd28a834)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) Intel Corporation. All rights reserved.
5  *   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 "spdk_internal/log.h"
37 #include "spdk/rpc.h"
38 #include "spdk/util.h"
39 #include "spdk/string.h"
40 #include "spdk/env.h"
41 
42 #include "spdk/scsi.h"
43 #include "spdk/vhost.h"
44 #include "vhost_internal.h"
45 #include "spdk/bdev.h"
46 
47 struct rpc_vhost_scsi_ctrlr {
48 	char *ctrlr;
49 	char *cpumask;
50 };
51 
52 static void
53 free_rpc_vhost_scsi_ctrlr(struct rpc_vhost_scsi_ctrlr *req)
54 {
55 	free(req->ctrlr);
56 	free(req->cpumask);
57 }
58 
59 static const struct spdk_json_object_decoder rpc_construct_vhost_ctrlr[] = {
60 	{"ctrlr", offsetof(struct rpc_vhost_scsi_ctrlr, ctrlr), spdk_json_decode_string },
61 	{"cpumask", offsetof(struct rpc_vhost_scsi_ctrlr, cpumask), spdk_json_decode_string, true},
62 };
63 
64 static void
65 spdk_rpc_construct_vhost_scsi_controller(struct spdk_jsonrpc_request *request,
66 		const struct spdk_json_val *params)
67 {
68 	struct rpc_vhost_scsi_ctrlr req = {0};
69 	struct spdk_json_write_ctx *w;
70 	int rc;
71 
72 	if (spdk_json_decode_object(params, rpc_construct_vhost_ctrlr,
73 				    SPDK_COUNTOF(rpc_construct_vhost_ctrlr),
74 				    &req)) {
75 		SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n");
76 		rc = -EINVAL;
77 		goto invalid;
78 	}
79 
80 	rc = spdk_vhost_scsi_dev_construct(req.ctrlr, req.cpumask);
81 	if (rc < 0) {
82 		goto invalid;
83 	}
84 
85 	free_rpc_vhost_scsi_ctrlr(&req);
86 
87 	w = spdk_jsonrpc_begin_result(request);
88 	if (w == NULL) {
89 		return;
90 	}
91 
92 	spdk_json_write_bool(w, true);
93 	spdk_jsonrpc_end_result(request, w);
94 	return;
95 
96 invalid:
97 	free_rpc_vhost_scsi_ctrlr(&req);
98 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
99 					 spdk_strerror(-rc));
100 }
101 SPDK_RPC_REGISTER("construct_vhost_scsi_controller", spdk_rpc_construct_vhost_scsi_controller)
102 
103 struct rpc_add_vhost_scsi_ctrlr_lun {
104 	char *ctrlr;
105 	uint32_t scsi_target_num;
106 	char *bdev_name;
107 
108 	struct spdk_jsonrpc_request *request;
109 };
110 
111 static void
112 free_rpc_add_vhost_scsi_ctrlr_lun(struct rpc_add_vhost_scsi_ctrlr_lun *req)
113 {
114 	free(req->ctrlr);
115 	free(req->bdev_name);
116 	free(req);
117 }
118 
119 static const struct spdk_json_object_decoder rpc_vhost_add_lun[] = {
120 	{"ctrlr", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, ctrlr), spdk_json_decode_string },
121 	{"scsi_target_num", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, scsi_target_num), spdk_json_decode_uint32},
122 	{"bdev_name", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, bdev_name), spdk_json_decode_string },
123 };
124 
125 static int
126 spdk_rpc_add_vhost_scsi_lun_cb(struct spdk_vhost_dev *vdev, void *arg)
127 {
128 	struct rpc_add_vhost_scsi_ctrlr_lun *rpc = arg;
129 	struct spdk_jsonrpc_request *request = rpc->request;
130 	struct spdk_json_write_ctx *w;
131 	int rc;
132 
133 	if (vdev == NULL) {
134 		rc = -ENODEV;
135 		goto invalid;
136 	}
137 
138 	rc = spdk_vhost_scsi_dev_add_tgt(vdev, rpc->scsi_target_num, rpc->bdev_name);
139 	if (rc < 0) {
140 		goto invalid;
141 	}
142 
143 	free_rpc_add_vhost_scsi_ctrlr_lun(rpc);
144 
145 	w = spdk_jsonrpc_begin_result(request);
146 	if (w == NULL) {
147 		return -1;
148 	}
149 
150 	spdk_json_write_bool(w, true);
151 	spdk_jsonrpc_end_result(request, w);
152 	return 0;
153 
154 invalid:
155 	free_rpc_add_vhost_scsi_ctrlr_lun(rpc);
156 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
157 					 spdk_strerror(-rc));
158 	return rc;
159 }
160 
161 static void
162 spdk_rpc_add_vhost_scsi_lun(struct spdk_jsonrpc_request *request,
163 			    const struct spdk_json_val *params)
164 {
165 	struct rpc_add_vhost_scsi_ctrlr_lun *req;
166 	int rc;
167 
168 	req = calloc(1, sizeof(*req));
169 	if (req == NULL) {
170 		rc = -ENOMEM;
171 		goto invalid;
172 	}
173 
174 	req->request = request;
175 	if (spdk_json_decode_object(params, rpc_vhost_add_lun,
176 				    SPDK_COUNTOF(rpc_vhost_add_lun),
177 				    req)) {
178 		SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n");
179 		rc = -EINVAL;
180 		goto invalid;
181 	}
182 
183 	if (req->ctrlr == NULL) {
184 		SPDK_ERRLOG("No controller name\n");
185 		rc = -EINVAL;
186 		goto invalid;
187 	}
188 
189 	spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_add_vhost_scsi_lun_cb, req);
190 
191 	return;
192 
193 invalid:
194 	if (req) {
195 		free_rpc_add_vhost_scsi_ctrlr_lun(req);
196 	}
197 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
198 					 spdk_strerror(-rc));
199 }
200 SPDK_RPC_REGISTER("add_vhost_scsi_lun", spdk_rpc_add_vhost_scsi_lun)
201 
202 struct rpc_remove_vhost_scsi_ctrlr_target {
203 	char *ctrlr;
204 	uint32_t scsi_target_num;
205 
206 	struct spdk_jsonrpc_request *request;
207 };
208 
209 static void
210 free_rpc_remove_vhost_scsi_ctrlr_target(struct rpc_remove_vhost_scsi_ctrlr_target *req)
211 {
212 	free(req->ctrlr);
213 	free(req);
214 }
215 
216 static const struct spdk_json_object_decoder rpc_vhost_remove_target[] = {
217 	{"ctrlr", offsetof(struct rpc_remove_vhost_scsi_ctrlr_target, ctrlr), spdk_json_decode_string },
218 	{"scsi_target_num", offsetof(struct rpc_remove_vhost_scsi_ctrlr_target, scsi_target_num), spdk_json_decode_uint32},
219 };
220 
221 static int
222 spdk_rpc_remove_vhost_scsi_target_finish_cb(struct spdk_vhost_dev *vdev, void *arg)
223 {
224 	struct rpc_remove_vhost_scsi_ctrlr_target *rpc = arg;
225 	struct spdk_jsonrpc_request *request = rpc->request;
226 	struct spdk_json_write_ctx *w;
227 
228 	free_rpc_remove_vhost_scsi_ctrlr_target(rpc);
229 
230 	w = spdk_jsonrpc_begin_result(request);
231 	if (w == NULL) {
232 		return -1;
233 	}
234 
235 	spdk_json_write_bool(w, true);
236 	spdk_jsonrpc_end_result(request, w);
237 	return 0;
238 }
239 
240 static int
241 spdk_rpc_remove_vhost_scsi_target_cb(struct spdk_vhost_dev *vdev, void *arg)
242 {
243 	struct rpc_remove_vhost_scsi_ctrlr_target *rpc = arg;
244 	struct spdk_jsonrpc_request *request = rpc->request;
245 	int rc;
246 
247 	if (vdev == NULL) {
248 		rc = -ENODEV;
249 		goto invalid;
250 	}
251 
252 	rc = spdk_vhost_scsi_dev_remove_tgt(vdev, rpc->scsi_target_num,
253 					    spdk_rpc_remove_vhost_scsi_target_finish_cb, rpc);
254 	if (rc < 0) {
255 		goto invalid;
256 	}
257 
258 	return 0;
259 
260 invalid:
261 	free_rpc_remove_vhost_scsi_ctrlr_target(rpc);
262 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc));
263 	return rc;
264 }
265 
266 static void
267 spdk_rpc_remove_vhost_scsi_target(struct spdk_jsonrpc_request *request,
268 				  const struct spdk_json_val *params)
269 {
270 	struct rpc_remove_vhost_scsi_ctrlr_target *req;
271 	int rc;
272 
273 	req = calloc(1, sizeof(*req));
274 	if (req == NULL) {
275 		rc = -ENOMEM;
276 		goto invalid;
277 	}
278 
279 	req->request = request;
280 	if (spdk_json_decode_object(params, rpc_vhost_remove_target,
281 				    SPDK_COUNTOF(rpc_vhost_remove_target),
282 				    req)) {
283 		SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n");
284 		rc = -EINVAL;
285 		goto invalid;
286 	}
287 
288 	spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_remove_vhost_scsi_target_cb, req);
289 
290 	return;
291 
292 invalid:
293 	if (req) {
294 		free_rpc_remove_vhost_scsi_ctrlr_target(req);
295 	}
296 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
297 					 spdk_strerror(-rc));
298 }
299 
300 SPDK_RPC_REGISTER("remove_vhost_scsi_target", spdk_rpc_remove_vhost_scsi_target)
301 
302 struct rpc_vhost_blk_ctrlr {
303 	char *ctrlr;
304 	char *dev_name;
305 	char *cpumask;
306 	bool readonly;
307 };
308 
309 static const struct spdk_json_object_decoder rpc_construct_vhost_blk_ctrlr[] = {
310 	{"ctrlr", offsetof(struct rpc_vhost_blk_ctrlr, ctrlr), spdk_json_decode_string },
311 	{"dev_name", offsetof(struct rpc_vhost_blk_ctrlr, dev_name), spdk_json_decode_string },
312 	{"cpumask", offsetof(struct rpc_vhost_blk_ctrlr, cpumask), spdk_json_decode_string, true},
313 	{"readonly", offsetof(struct rpc_vhost_blk_ctrlr, readonly), spdk_json_decode_bool, true},
314 };
315 
316 static void
317 free_rpc_vhost_blk_ctrlr(struct rpc_vhost_blk_ctrlr *req)
318 {
319 	free(req->ctrlr);
320 	free(req->dev_name);
321 	free(req->cpumask);
322 }
323 
324 static void
325 spdk_rpc_construct_vhost_blk_controller(struct spdk_jsonrpc_request *request,
326 					const struct spdk_json_val *params)
327 {
328 	struct rpc_vhost_blk_ctrlr req = {0};
329 	struct spdk_json_write_ctx *w;
330 	int rc;
331 
332 	if (spdk_json_decode_object(params, rpc_construct_vhost_blk_ctrlr,
333 				    SPDK_COUNTOF(rpc_construct_vhost_blk_ctrlr),
334 				    &req)) {
335 		SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n");
336 		rc = -EINVAL;
337 		goto invalid;
338 	}
339 
340 	rc = spdk_vhost_blk_construct(req.ctrlr, req.cpumask, req.dev_name, req.readonly);
341 	if (rc < 0) {
342 		goto invalid;
343 	}
344 
345 	free_rpc_vhost_blk_ctrlr(&req);
346 
347 	w = spdk_jsonrpc_begin_result(request);
348 	if (w == NULL) {
349 		return;
350 	}
351 
352 	spdk_json_write_bool(w, true);
353 	spdk_jsonrpc_end_result(request, w);
354 	return;
355 
356 invalid:
357 	free_rpc_vhost_blk_ctrlr(&req);
358 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
359 					 spdk_strerror(-rc));
360 
361 }
362 SPDK_RPC_REGISTER("construct_vhost_blk_controller", spdk_rpc_construct_vhost_blk_controller)
363 
364 struct rpc_remove_vhost_ctrlr {
365 	char *ctrlr;
366 
367 	struct spdk_jsonrpc_request *request;
368 };
369 
370 static const struct spdk_json_object_decoder rpc_remove_vhost_ctrlr[] = {
371 	{"ctrlr", offsetof(struct rpc_remove_vhost_ctrlr, ctrlr), spdk_json_decode_string },
372 };
373 
374 static void
375 free_rpc_remove_vhost_ctrlr(struct rpc_remove_vhost_ctrlr *req)
376 {
377 	free(req->ctrlr);
378 	free(req);
379 }
380 
381 static int
382 spdk_rpc_remove_vhost_controller_cb(struct spdk_vhost_dev *vdev, void *arg)
383 {
384 	struct rpc_remove_vhost_ctrlr *ctx = arg;
385 	struct spdk_jsonrpc_request *request = ctx->request;
386 	struct spdk_json_write_ctx *w;
387 	int rc;
388 
389 	if (vdev == NULL) {
390 		rc = -ENODEV;
391 		goto invalid;
392 	}
393 
394 	rc = spdk_vhost_dev_remove(vdev);
395 	if (rc < 0) {
396 		goto invalid;
397 	}
398 
399 	free_rpc_remove_vhost_ctrlr(ctx);
400 
401 	w = spdk_jsonrpc_begin_result(request);
402 	if (w == NULL) {
403 		return 0;
404 	}
405 
406 	spdk_json_write_bool(w, true);
407 	spdk_jsonrpc_end_result(request, w);
408 	return 0;
409 
410 invalid:
411 	free_rpc_remove_vhost_ctrlr(ctx);
412 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
413 					 spdk_strerror(-rc));
414 	return -1;
415 }
416 
417 static void
418 spdk_rpc_remove_vhost_controller(struct spdk_jsonrpc_request *request,
419 				 const struct spdk_json_val *params)
420 {
421 	struct rpc_remove_vhost_ctrlr *req;
422 	int rc;
423 
424 	req = calloc(1, sizeof(*req));
425 	if (req == NULL) {
426 		rc = -ENOMEM;
427 		goto invalid;
428 	}
429 
430 	req->request = request;
431 	if (spdk_json_decode_object(params, rpc_remove_vhost_ctrlr,
432 				    SPDK_COUNTOF(rpc_remove_vhost_ctrlr), req)) {
433 		SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n");
434 		rc = -EINVAL;
435 		goto invalid;
436 	}
437 
438 	spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_remove_vhost_controller_cb, req);
439 	return;
440 
441 invalid:
442 	if (req) {
443 		free_rpc_remove_vhost_ctrlr(req);
444 	}
445 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
446 					 spdk_strerror(-rc));
447 
448 }
449 SPDK_RPC_REGISTER("remove_vhost_controller", spdk_rpc_remove_vhost_controller)
450 
451 struct rpc_get_vhost_ctrlrs {
452 	struct spdk_json_write_ctx *w;
453 	struct spdk_jsonrpc_request *request;
454 };
455 
456 static int
457 spdk_rpc_get_vhost_controllers_cb(struct spdk_vhost_dev *vdev, void *arg)
458 {
459 	struct rpc_get_vhost_ctrlrs *ctx = arg;
460 
461 	if (vdev == NULL) {
462 		spdk_json_write_array_end(ctx->w);
463 		spdk_jsonrpc_end_result(ctx->request, ctx->w);
464 		free(ctx);
465 		return 0;
466 	}
467 
468 	spdk_json_write_object_begin(ctx->w);
469 
470 	spdk_json_write_name(ctx->w, "ctrlr");
471 	spdk_json_write_string(ctx->w, spdk_vhost_dev_get_name(vdev));
472 
473 	spdk_json_write_name(ctx->w, "cpumask");
474 	spdk_json_write_string_fmt(ctx->w, "0x%s", spdk_cpuset_fmt(vdev->cpumask));
475 
476 	spdk_json_write_name(ctx->w, "backend_specific");
477 
478 	spdk_json_write_object_begin(ctx->w);
479 	spdk_vhost_dump_config_json(vdev, ctx->w);
480 	spdk_json_write_object_end(ctx->w);
481 
482 	spdk_json_write_object_end(ctx->w); // ctrl
483 
484 	return 0;
485 }
486 
487 
488 static void
489 spdk_rpc_get_vhost_controllers(struct spdk_jsonrpc_request *request,
490 			       const struct spdk_json_val *params)
491 {
492 	struct rpc_get_vhost_ctrlrs *ctx;
493 	struct spdk_json_write_ctx *w;
494 
495 	if (params != NULL) {
496 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
497 						 "get_vhost_controllers requires no parameters");
498 		return;
499 	}
500 
501 	w = spdk_jsonrpc_begin_result(request);
502 	if (w == NULL) {
503 		return;
504 	}
505 
506 	spdk_json_write_array_begin(w);
507 
508 	ctx = calloc(1, sizeof(*ctx));
509 	if (ctx == NULL) {
510 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
511 						 spdk_strerror(ENOMEM));
512 		return;
513 	}
514 
515 	ctx->w = w;
516 	ctx->request = request;
517 	spdk_vhost_call_external_event_foreach(spdk_rpc_get_vhost_controllers_cb, ctx);
518 }
519 SPDK_RPC_REGISTER("get_vhost_controllers", spdk_rpc_get_vhost_controllers)
520 
521 
522 struct rpc_vhost_ctrlr_coalescing {
523 	char *ctrlr;
524 	uint32_t delay_base_us;
525 	uint32_t iops_threshold;
526 	struct spdk_jsonrpc_request *request;
527 };
528 
529 static const struct spdk_json_object_decoder rpc_set_vhost_ctrlr_coalescing[] = {
530 	{"ctrlr", offsetof(struct rpc_vhost_ctrlr_coalescing, ctrlr), spdk_json_decode_string },
531 	{"delay_base_us", offsetof(struct rpc_vhost_ctrlr_coalescing, delay_base_us), spdk_json_decode_uint32},
532 	{"iops_threshold", offsetof(struct rpc_vhost_ctrlr_coalescing, iops_threshold), spdk_json_decode_uint32},
533 };
534 
535 static void
536 free_rpc_set_vhost_controllers_event_coalescing(struct rpc_vhost_ctrlr_coalescing *req)
537 {
538 	if (!req) {
539 		return;
540 	}
541 
542 	free(req->ctrlr);
543 	free(req);
544 }
545 
546 static int
547 spdk_rpc_set_vhost_controller_coalescing_cb(struct spdk_vhost_dev *vdev, void *arg)
548 {
549 	struct rpc_vhost_ctrlr_coalescing *req = arg;
550 	struct spdk_json_write_ctx *w;
551 	int rc;
552 
553 	if (vdev == NULL) {
554 		rc = -ENODEV;
555 		goto invalid;
556 	}
557 
558 	rc = spdk_vhost_set_coalescing(vdev, req->delay_base_us, req->iops_threshold);
559 	if (rc) {
560 		goto invalid;
561 	}
562 
563 	w = spdk_jsonrpc_begin_result(req->request);
564 	if (w != NULL) {
565 		spdk_json_write_bool(w, true);
566 		spdk_jsonrpc_end_result(req->request, w);
567 	}
568 
569 	free_rpc_set_vhost_controllers_event_coalescing(req);
570 	return 0;
571 
572 invalid:
573 	spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
574 					 spdk_strerror(-rc));
575 	free_rpc_set_vhost_controllers_event_coalescing(req);
576 	return 0;
577 }
578 
579 static void
580 spdk_rpc_set_vhost_controller_coalescing(struct spdk_jsonrpc_request *request,
581 		const struct spdk_json_val *params)
582 {
583 	struct rpc_vhost_ctrlr_coalescing *req;
584 	int rc;
585 
586 	req = calloc(1, sizeof(struct rpc_vhost_ctrlr_coalescing));
587 	if (!req) {
588 		rc = -ENOMEM;
589 		goto invalid;
590 	}
591 
592 	if (spdk_json_decode_object(params, rpc_set_vhost_ctrlr_coalescing,
593 				    SPDK_COUNTOF(rpc_set_vhost_ctrlr_coalescing), req)) {
594 		SPDK_DEBUGLOG(SPDK_LOG_VHOST_RPC, "spdk_json_decode_object failed\n");
595 		rc = -EINVAL;
596 		goto invalid;
597 	}
598 
599 	req->request = request;
600 	spdk_vhost_call_external_event(req->ctrlr, spdk_rpc_set_vhost_controller_coalescing_cb, req);
601 	return;
602 
603 invalid:
604 	free_rpc_set_vhost_controllers_event_coalescing(req);
605 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
606 					 spdk_strerror(-rc));
607 }
608 SPDK_RPC_REGISTER("set_vhost_controller_coalescing", spdk_rpc_set_vhost_controller_coalescing)
609 
610 
611 SPDK_LOG_REGISTER_COMPONENT("vhost_rpc", SPDK_LOG_VHOST_RPC)
612