Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2017 Intel Corporation. All rights reserved.
3 : * All rights reserved.
4 : */
5 :
6 : #include "spdk/stdinc.h"
7 :
8 : #include "spdk/log.h"
9 : #include "spdk/rpc.h"
10 : #include "spdk/util.h"
11 : #include "spdk/string.h"
12 : #include "spdk/env.h"
13 : #include "spdk/log.h"
14 : #include "spdk/scsi.h"
15 : #include "spdk/vhost.h"
16 : #include "vhost_internal.h"
17 : #include "spdk/bdev.h"
18 :
19 : struct rpc_vhost_scsi_ctrlr {
20 : char *ctrlr;
21 : char *cpumask;
22 : bool delay;
23 : };
24 :
25 : static void
26 0 : free_rpc_vhost_scsi_ctrlr(struct rpc_vhost_scsi_ctrlr *req)
27 : {
28 0 : free(req->ctrlr);
29 0 : free(req->cpumask);
30 0 : }
31 :
32 : static const struct spdk_json_object_decoder rpc_vhost_create_scsi_ctrlr[] = {
33 : {"ctrlr", offsetof(struct rpc_vhost_scsi_ctrlr, ctrlr), spdk_json_decode_string },
34 : {"cpumask", offsetof(struct rpc_vhost_scsi_ctrlr, cpumask), spdk_json_decode_string, true},
35 : {"delay", offsetof(struct rpc_vhost_scsi_ctrlr, delay), spdk_json_decode_bool, true},
36 : };
37 :
38 : static void
39 0 : rpc_vhost_create_scsi_controller(struct spdk_jsonrpc_request *request,
40 : const struct spdk_json_val *params)
41 : {
42 0 : struct rpc_vhost_scsi_ctrlr req = {0};
43 : int rc;
44 :
45 0 : if (spdk_json_decode_object(params, rpc_vhost_create_scsi_ctrlr,
46 : SPDK_COUNTOF(rpc_vhost_create_scsi_ctrlr),
47 : &req)) {
48 0 : SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n");
49 0 : rc = -EINVAL;
50 0 : goto invalid;
51 : }
52 :
53 0 : if (req.delay) {
54 0 : rc = spdk_vhost_scsi_dev_construct_no_start(req.ctrlr, req.cpumask);
55 : } else {
56 0 : rc = spdk_vhost_scsi_dev_construct(req.ctrlr, req.cpumask);
57 : }
58 0 : if (rc < 0) {
59 0 : goto invalid;
60 : }
61 :
62 0 : free_rpc_vhost_scsi_ctrlr(&req);
63 :
64 0 : spdk_jsonrpc_send_bool_response(request, true);
65 0 : return;
66 :
67 0 : invalid:
68 0 : free_rpc_vhost_scsi_ctrlr(&req);
69 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
70 : spdk_strerror(-rc));
71 : }
72 0 : SPDK_RPC_REGISTER("vhost_create_scsi_controller", rpc_vhost_create_scsi_controller,
73 : SPDK_RPC_RUNTIME)
74 :
75 : struct rpc_start_vhost_scsi_ctrlr {
76 : char *ctrlr;
77 : };
78 :
79 : static void
80 0 : free_rpc_start_vhost_scsi_ctrlr(struct rpc_start_vhost_scsi_ctrlr *req)
81 : {
82 0 : free(req->ctrlr);
83 0 : }
84 :
85 : static const struct spdk_json_object_decoder rpc_start_vhost_scsi_ctrlr_decoder[] = {
86 : {"ctrlr", offsetof(struct rpc_start_vhost_scsi_ctrlr, ctrlr), spdk_json_decode_string },
87 : };
88 :
89 : static void
90 0 : rpc_vhost_start_scsi_controller(struct spdk_jsonrpc_request *request,
91 : const struct spdk_json_val *params)
92 : {
93 0 : struct rpc_start_vhost_scsi_ctrlr req = {0};
94 : int rc;
95 :
96 0 : if (spdk_json_decode_object(params, rpc_start_vhost_scsi_ctrlr_decoder,
97 : SPDK_COUNTOF(rpc_start_vhost_scsi_ctrlr_decoder),
98 : &req)) {
99 0 : SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n");
100 0 : rc = -EINVAL;
101 0 : goto invalid;
102 : }
103 :
104 0 : rc = vhost_scsi_controller_start(req.ctrlr);
105 0 : if (rc < 0) {
106 0 : goto invalid;
107 : }
108 :
109 0 : free_rpc_start_vhost_scsi_ctrlr(&req);
110 :
111 0 : spdk_jsonrpc_send_bool_response(request, true);
112 0 : return;
113 :
114 0 : invalid:
115 0 : free_rpc_start_vhost_scsi_ctrlr(&req);
116 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
117 : spdk_strerror(-rc));
118 : }
119 0 : SPDK_RPC_REGISTER("vhost_start_scsi_controller", rpc_vhost_start_scsi_controller,
120 : SPDK_RPC_RUNTIME)
121 :
122 : struct rpc_vhost_scsi_ctrlr_add_target {
123 : char *ctrlr;
124 : int32_t scsi_target_num;
125 : char *bdev_name;
126 : };
127 :
128 : static void
129 0 : free_rpc_vhost_scsi_ctrlr_add_target(struct rpc_vhost_scsi_ctrlr_add_target *req)
130 : {
131 0 : free(req->ctrlr);
132 0 : free(req->bdev_name);
133 0 : }
134 :
135 : static const struct spdk_json_object_decoder rpc_vhost_scsi_ctrlr_add_target[] = {
136 : {"ctrlr", offsetof(struct rpc_vhost_scsi_ctrlr_add_target, ctrlr), spdk_json_decode_string },
137 : {"scsi_target_num", offsetof(struct rpc_vhost_scsi_ctrlr_add_target, scsi_target_num), spdk_json_decode_int32},
138 : {"bdev_name", offsetof(struct rpc_vhost_scsi_ctrlr_add_target, bdev_name), spdk_json_decode_string },
139 : };
140 :
141 : static void
142 0 : rpc_vhost_scsi_controller_add_target(struct spdk_jsonrpc_request *request,
143 : const struct spdk_json_val *params)
144 : {
145 0 : struct rpc_vhost_scsi_ctrlr_add_target req = {0};
146 : struct spdk_json_write_ctx *w;
147 : struct spdk_vhost_dev *vdev;
148 : int rc;
149 :
150 0 : if (spdk_json_decode_object(params, rpc_vhost_scsi_ctrlr_add_target,
151 : SPDK_COUNTOF(rpc_vhost_scsi_ctrlr_add_target),
152 : &req)) {
153 0 : SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n");
154 0 : rc = -EINVAL;
155 0 : goto invalid;
156 : }
157 :
158 0 : spdk_vhost_lock();
159 0 : vdev = spdk_vhost_dev_find(req.ctrlr);
160 0 : if (vdev == NULL) {
161 0 : spdk_vhost_unlock();
162 0 : rc = -ENODEV;
163 0 : goto invalid;
164 : }
165 :
166 0 : rc = spdk_vhost_scsi_dev_add_tgt(vdev, req.scsi_target_num, req.bdev_name);
167 0 : spdk_vhost_unlock();
168 0 : if (rc < 0) {
169 0 : goto invalid;
170 : }
171 :
172 0 : free_rpc_vhost_scsi_ctrlr_add_target(&req);
173 :
174 0 : w = spdk_jsonrpc_begin_result(request);
175 0 : spdk_json_write_int32(w, rc);
176 0 : spdk_jsonrpc_end_result(request, w);
177 0 : return;
178 :
179 0 : invalid:
180 0 : free_rpc_vhost_scsi_ctrlr_add_target(&req);
181 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
182 : spdk_strerror(-rc));
183 : }
184 0 : SPDK_RPC_REGISTER("vhost_scsi_controller_add_target", rpc_vhost_scsi_controller_add_target,
185 : SPDK_RPC_RUNTIME)
186 :
187 : struct rpc_remove_vhost_scsi_ctrlr_target {
188 : char *ctrlr;
189 : uint32_t scsi_target_num;
190 : };
191 :
192 : static void
193 0 : free_rpc_remove_vhost_scsi_ctrlr_target(struct rpc_remove_vhost_scsi_ctrlr_target *req)
194 : {
195 0 : free(req->ctrlr);
196 0 : }
197 :
198 : static const struct spdk_json_object_decoder rpc_vhost_remove_target[] = {
199 : {"ctrlr", offsetof(struct rpc_remove_vhost_scsi_ctrlr_target, ctrlr), spdk_json_decode_string },
200 : {"scsi_target_num", offsetof(struct rpc_remove_vhost_scsi_ctrlr_target, scsi_target_num), spdk_json_decode_uint32},
201 : };
202 :
203 : static int
204 0 : rpc_vhost_scsi_controller_remove_target_finish_cb(struct spdk_vhost_dev *vdev, void *arg)
205 : {
206 0 : struct spdk_jsonrpc_request *request = arg;
207 :
208 0 : spdk_jsonrpc_send_bool_response(request, true);
209 0 : return 0;
210 : }
211 :
212 : static void
213 0 : rpc_vhost_scsi_controller_remove_target(struct spdk_jsonrpc_request *request,
214 : const struct spdk_json_val *params)
215 : {
216 0 : struct rpc_remove_vhost_scsi_ctrlr_target req = {0};
217 : struct spdk_vhost_dev *vdev;
218 : int rc;
219 :
220 0 : if (spdk_json_decode_object(params, rpc_vhost_remove_target,
221 : SPDK_COUNTOF(rpc_vhost_remove_target),
222 : &req)) {
223 0 : SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n");
224 0 : rc = -EINVAL;
225 0 : goto invalid;
226 : }
227 :
228 0 : spdk_vhost_lock();
229 0 : vdev = spdk_vhost_dev_find(req.ctrlr);
230 0 : if (vdev == NULL) {
231 0 : spdk_vhost_unlock();
232 0 : rc = -ENODEV;
233 0 : goto invalid;
234 : }
235 :
236 0 : rc = spdk_vhost_scsi_dev_remove_tgt(vdev, req.scsi_target_num,
237 : rpc_vhost_scsi_controller_remove_target_finish_cb,
238 : request);
239 0 : spdk_vhost_unlock();
240 0 : if (rc < 0) {
241 0 : goto invalid;
242 : }
243 :
244 0 : free_rpc_remove_vhost_scsi_ctrlr_target(&req);
245 0 : return;
246 :
247 0 : invalid:
248 0 : free_rpc_remove_vhost_scsi_ctrlr_target(&req);
249 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
250 : spdk_strerror(-rc));
251 : }
252 :
253 0 : SPDK_RPC_REGISTER("vhost_scsi_controller_remove_target",
254 : rpc_vhost_scsi_controller_remove_target, SPDK_RPC_RUNTIME)
255 :
256 : struct rpc_vhost_blk_ctrlr {
257 : char *ctrlr;
258 : char *dev_name;
259 : char *cpumask;
260 : char *transport;
261 : };
262 :
263 : static const struct spdk_json_object_decoder rpc_construct_vhost_blk_ctrlr[] = {
264 : {"ctrlr", offsetof(struct rpc_vhost_blk_ctrlr, ctrlr), spdk_json_decode_string },
265 : {"dev_name", offsetof(struct rpc_vhost_blk_ctrlr, dev_name), spdk_json_decode_string },
266 : {"cpumask", offsetof(struct rpc_vhost_blk_ctrlr, cpumask), spdk_json_decode_string, true},
267 : {"transport", offsetof(struct rpc_vhost_blk_ctrlr, transport), spdk_json_decode_string, true},
268 : };
269 :
270 : static void
271 0 : free_rpc_vhost_blk_ctrlr(struct rpc_vhost_blk_ctrlr *req)
272 : {
273 0 : free(req->ctrlr);
274 0 : free(req->dev_name);
275 0 : free(req->cpumask);
276 0 : free(req->transport);
277 0 : }
278 :
279 : static void
280 0 : rpc_vhost_create_blk_controller(struct spdk_jsonrpc_request *request,
281 : const struct spdk_json_val *params)
282 : {
283 0 : struct rpc_vhost_blk_ctrlr req = {0};
284 : int rc;
285 :
286 0 : if (spdk_json_decode_object_relaxed(params, rpc_construct_vhost_blk_ctrlr,
287 : SPDK_COUNTOF(rpc_construct_vhost_blk_ctrlr),
288 : &req)) {
289 0 : SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n");
290 0 : rc = -EINVAL;
291 0 : goto invalid;
292 : }
293 :
294 0 : rc = spdk_vhost_blk_construct(req.ctrlr, req.cpumask, req.dev_name, req.transport, params);
295 0 : if (rc < 0) {
296 0 : goto invalid;
297 : }
298 :
299 0 : free_rpc_vhost_blk_ctrlr(&req);
300 :
301 0 : spdk_jsonrpc_send_bool_response(request, true);
302 0 : return;
303 :
304 0 : invalid:
305 0 : free_rpc_vhost_blk_ctrlr(&req);
306 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
307 : spdk_strerror(-rc));
308 :
309 : }
310 0 : SPDK_RPC_REGISTER("vhost_create_blk_controller", rpc_vhost_create_blk_controller,
311 : SPDK_RPC_RUNTIME)
312 :
313 : struct rpc_delete_vhost_ctrlr {
314 : char *ctrlr;
315 : };
316 :
317 : static const struct spdk_json_object_decoder rpc_delete_vhost_ctrlr_decoder[] = {
318 : {"ctrlr", offsetof(struct rpc_delete_vhost_ctrlr, ctrlr), spdk_json_decode_string },
319 : };
320 :
321 : static void
322 0 : free_rpc_delete_vhost_ctrlr(struct rpc_delete_vhost_ctrlr *req)
323 : {
324 0 : free(req->ctrlr);
325 0 : }
326 :
327 : static void
328 0 : rpc_vhost_delete_controller(struct spdk_jsonrpc_request *request,
329 : const struct spdk_json_val *params)
330 : {
331 0 : struct rpc_delete_vhost_ctrlr req = {0};
332 : struct spdk_vhost_dev *vdev;
333 : int rc;
334 :
335 0 : if (spdk_json_decode_object(params, rpc_delete_vhost_ctrlr_decoder,
336 : SPDK_COUNTOF(rpc_delete_vhost_ctrlr_decoder), &req)) {
337 0 : SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n");
338 0 : rc = -EINVAL;
339 0 : goto invalid;
340 : }
341 :
342 0 : spdk_vhost_lock();
343 0 : vdev = spdk_vhost_dev_find(req.ctrlr);
344 0 : if (vdev == NULL) {
345 0 : spdk_vhost_unlock();
346 0 : rc = -ENODEV;
347 0 : goto invalid;
348 : }
349 0 : spdk_vhost_unlock();
350 :
351 0 : rc = spdk_vhost_dev_remove(vdev);
352 0 : if (rc < 0) {
353 0 : goto invalid;
354 : }
355 :
356 0 : free_rpc_delete_vhost_ctrlr(&req);
357 :
358 0 : spdk_jsonrpc_send_bool_response(request, true);
359 0 : return;
360 :
361 0 : invalid:
362 0 : free_rpc_delete_vhost_ctrlr(&req);
363 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
364 : spdk_strerror(-rc));
365 :
366 : }
367 0 : SPDK_RPC_REGISTER("vhost_delete_controller", rpc_vhost_delete_controller, SPDK_RPC_RUNTIME)
368 :
369 : struct rpc_get_vhost_ctrlrs {
370 : char *name;
371 : };
372 :
373 : static void
374 0 : _rpc_get_vhost_controller(struct spdk_json_write_ctx *w, struct spdk_vhost_dev *vdev)
375 : {
376 0 : uint32_t delay_base_us, iops_threshold;
377 :
378 0 : spdk_vhost_get_coalescing(vdev, &delay_base_us, &iops_threshold);
379 :
380 0 : spdk_json_write_object_begin(w);
381 :
382 0 : spdk_json_write_named_string(w, "ctrlr", spdk_vhost_dev_get_name(vdev));
383 0 : spdk_json_write_named_string_fmt(w, "cpumask", "0x%s",
384 : spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread)));
385 0 : spdk_json_write_named_uint32(w, "delay_base_us", delay_base_us);
386 0 : spdk_json_write_named_uint32(w, "iops_threshold", iops_threshold);
387 0 : spdk_json_write_named_string(w, "socket", vdev->path);
388 0 : spdk_json_write_named_array_begin(w, "sessions");
389 0 : vhost_session_info_json(vdev, w);
390 0 : spdk_json_write_array_end(w);
391 :
392 0 : spdk_json_write_named_object_begin(w, "backend_specific");
393 0 : vhost_dump_info_json(vdev, w);
394 0 : spdk_json_write_object_end(w);
395 :
396 0 : spdk_json_write_object_end(w);
397 0 : }
398 :
399 : static const struct spdk_json_object_decoder rpc_get_vhost_ctrlrs_decoders[] = {
400 : {"name", offsetof(struct rpc_get_vhost_ctrlrs, name), spdk_json_decode_string, true},
401 : };
402 :
403 : static void
404 0 : free_rpc_get_vhost_ctrlrs(struct rpc_get_vhost_ctrlrs *req)
405 : {
406 0 : free(req->name);
407 0 : }
408 :
409 : static void
410 0 : rpc_vhost_get_controllers(struct spdk_jsonrpc_request *request,
411 : const struct spdk_json_val *params)
412 : {
413 0 : struct rpc_get_vhost_ctrlrs req = {0};
414 : struct spdk_json_write_ctx *w;
415 : struct spdk_vhost_dev *vdev;
416 : int rc;
417 :
418 0 : if (params && spdk_json_decode_object(params, rpc_get_vhost_ctrlrs_decoders,
419 : SPDK_COUNTOF(rpc_get_vhost_ctrlrs_decoders), &req)) {
420 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
421 0 : rc = -EINVAL;
422 0 : goto invalid;
423 : }
424 :
425 0 : spdk_vhost_lock();
426 0 : if (req.name != NULL) {
427 0 : vdev = spdk_vhost_dev_find(req.name);
428 0 : if (vdev == NULL) {
429 0 : spdk_vhost_unlock();
430 0 : rc = -ENODEV;
431 0 : goto invalid;
432 : }
433 :
434 0 : free_rpc_get_vhost_ctrlrs(&req);
435 :
436 0 : w = spdk_jsonrpc_begin_result(request);
437 0 : spdk_json_write_array_begin(w);
438 :
439 0 : _rpc_get_vhost_controller(w, vdev);
440 0 : spdk_vhost_unlock();
441 :
442 0 : spdk_json_write_array_end(w);
443 0 : spdk_jsonrpc_end_result(request, w);
444 0 : return;
445 : }
446 :
447 0 : free_rpc_get_vhost_ctrlrs(&req);
448 :
449 0 : w = spdk_jsonrpc_begin_result(request);
450 0 : spdk_json_write_array_begin(w);
451 :
452 0 : vdev = spdk_vhost_dev_next(NULL);
453 0 : while (vdev != NULL) {
454 0 : _rpc_get_vhost_controller(w, vdev);
455 0 : vdev = spdk_vhost_dev_next(vdev);
456 : }
457 0 : spdk_vhost_unlock();
458 :
459 0 : spdk_json_write_array_end(w);
460 0 : spdk_jsonrpc_end_result(request, w);
461 0 : return;
462 :
463 0 : invalid:
464 0 : free_rpc_get_vhost_ctrlrs(&req);
465 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
466 : spdk_strerror(-rc));
467 : }
468 0 : SPDK_RPC_REGISTER("vhost_get_controllers", rpc_vhost_get_controllers, SPDK_RPC_RUNTIME)
469 :
470 :
471 : struct rpc_vhost_ctrlr_coalescing {
472 : char *ctrlr;
473 : uint32_t delay_base_us;
474 : uint32_t iops_threshold;
475 : };
476 :
477 : static const struct spdk_json_object_decoder rpc_set_vhost_ctrlr_coalescing[] = {
478 : {"ctrlr", offsetof(struct rpc_vhost_ctrlr_coalescing, ctrlr), spdk_json_decode_string },
479 : {"delay_base_us", offsetof(struct rpc_vhost_ctrlr_coalescing, delay_base_us), spdk_json_decode_uint32},
480 : {"iops_threshold", offsetof(struct rpc_vhost_ctrlr_coalescing, iops_threshold), spdk_json_decode_uint32},
481 : };
482 :
483 : static void
484 0 : free_rpc_set_vhost_controllers_event_coalescing(struct rpc_vhost_ctrlr_coalescing *req)
485 : {
486 0 : free(req->ctrlr);
487 0 : }
488 :
489 : static void
490 0 : rpc_vhost_controller_set_coalescing(struct spdk_jsonrpc_request *request,
491 : const struct spdk_json_val *params)
492 : {
493 0 : struct rpc_vhost_ctrlr_coalescing req = {0};
494 : struct spdk_vhost_dev *vdev;
495 : int rc;
496 :
497 0 : if (spdk_json_decode_object(params, rpc_set_vhost_ctrlr_coalescing,
498 : SPDK_COUNTOF(rpc_set_vhost_ctrlr_coalescing), &req)) {
499 0 : SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n");
500 0 : rc = -EINVAL;
501 0 : goto invalid;
502 : }
503 :
504 0 : spdk_vhost_lock();
505 0 : vdev = spdk_vhost_dev_find(req.ctrlr);
506 0 : if (vdev == NULL) {
507 0 : spdk_vhost_unlock();
508 0 : rc = -ENODEV;
509 0 : goto invalid;
510 : }
511 :
512 0 : rc = spdk_vhost_set_coalescing(vdev, req.delay_base_us, req.iops_threshold);
513 0 : spdk_vhost_unlock();
514 0 : if (rc) {
515 0 : goto invalid;
516 : }
517 :
518 0 : free_rpc_set_vhost_controllers_event_coalescing(&req);
519 :
520 0 : spdk_jsonrpc_send_bool_response(request, true);
521 0 : return;
522 :
523 0 : invalid:
524 0 : free_rpc_set_vhost_controllers_event_coalescing(&req);
525 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
526 : spdk_strerror(-rc));
527 : }
528 0 : SPDK_RPC_REGISTER("vhost_controller_set_coalescing", rpc_vhost_controller_set_coalescing,
529 : SPDK_RPC_RUNTIME)
530 :
531 : struct rpc_get_transport {
532 : char *name;
533 : };
534 :
535 : static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = {
536 : {"name", offsetof(struct rpc_get_transport, name), spdk_json_decode_string, true},
537 : };
538 :
539 : static void
540 0 : rpc_virtio_blk_get_transports(struct spdk_jsonrpc_request *request,
541 : const struct spdk_json_val *params)
542 : {
543 0 : struct rpc_get_transport req = { 0 };
544 : struct spdk_json_write_ctx *w;
545 0 : struct spdk_virtio_blk_transport *transport = NULL;
546 :
547 0 : if (params) {
548 0 : if (spdk_json_decode_object(params, rpc_get_transport_decoders,
549 : SPDK_COUNTOF(rpc_get_transport_decoders),
550 : &req)) {
551 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
552 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
553 0 : return;
554 : }
555 : }
556 :
557 0 : if (req.name) {
558 0 : transport = virtio_blk_tgt_get_transport(req.name);
559 0 : if (transport == NULL) {
560 0 : SPDK_ERRLOG("transport '%s' does not exist\n", req.name);
561 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
562 0 : free(req.name);
563 0 : return;
564 : }
565 : }
566 :
567 0 : w = spdk_jsonrpc_begin_result(request);
568 0 : spdk_json_write_array_begin(w);
569 :
570 0 : if (transport) {
571 0 : virtio_blk_transport_dump_opts(transport, w);
572 : } else {
573 0 : for (transport = virtio_blk_transport_get_first(); transport != NULL;
574 0 : transport = virtio_blk_transport_get_next(transport)) {
575 0 : virtio_blk_transport_dump_opts(transport, w);
576 : }
577 : }
578 :
579 0 : spdk_json_write_array_end(w);
580 0 : spdk_jsonrpc_end_result(request, w);
581 0 : free(req.name);
582 : }
583 0 : SPDK_RPC_REGISTER("virtio_blk_get_transports", rpc_virtio_blk_get_transports, SPDK_RPC_RUNTIME)
584 :
585 : struct rpc_virtio_blk_create_transport {
586 : char *name;
587 : };
588 :
589 : static const struct spdk_json_object_decoder rpc_create_virtio_blk_transport[] = {
590 : {"name", offsetof(struct rpc_virtio_blk_create_transport, name), spdk_json_decode_string},
591 : };
592 :
593 : static void
594 0 : free_rpc_virtio_blk_create_transport(struct rpc_virtio_blk_create_transport *req)
595 : {
596 0 : free(req->name);
597 0 : }
598 :
599 : static void
600 0 : rpc_virtio_blk_create_transport(struct spdk_jsonrpc_request *request,
601 : const struct spdk_json_val *params)
602 : {
603 0 : struct rpc_virtio_blk_create_transport req = {0};
604 : int rc;
605 :
606 0 : if (spdk_json_decode_object_relaxed(params, rpc_create_virtio_blk_transport,
607 : SPDK_COUNTOF(rpc_create_virtio_blk_transport), &req)) {
608 0 : SPDK_DEBUGLOG(vhost_rpc, "spdk_json_decode_object failed\n");
609 0 : rc = -EINVAL;
610 0 : goto invalid;
611 : }
612 :
613 0 : spdk_vhost_lock();
614 0 : rc = virtio_blk_transport_create(req.name, params);
615 0 : spdk_vhost_unlock();
616 0 : if (rc != 0) {
617 0 : goto invalid;
618 : }
619 :
620 0 : free_rpc_virtio_blk_create_transport(&req);
621 0 : spdk_jsonrpc_send_bool_response(request, true);
622 0 : return;
623 :
624 0 : invalid:
625 0 : free_rpc_virtio_blk_create_transport(&req);
626 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
627 : }
628 0 : SPDK_RPC_REGISTER("virtio_blk_create_transport", rpc_virtio_blk_create_transport,
629 : SPDK_RPC_RUNTIME)
630 :
631 0 : SPDK_LOG_REGISTER_COMPONENT(vhost_rpc)
|