xref: /spdk/module/vfu_device/vfu_virtio_rpc.c (revision 307b8c112ffd90a26d53dd15fad67bd9038ef526)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/bdev.h"
7 #include "spdk/log.h"
8 #include "spdk/rpc.h"
9 #include "spdk/env.h"
10 #include "spdk/string.h"
11 #include "spdk/util.h"
12 #include "spdk/thread.h"
13 
14 #include "vfu_virtio_internal.h"
15 
16 struct rpc_delete_vfu_endpoint {
17 	char		*name;
18 };
19 
20 static const struct spdk_json_object_decoder rpc_delete_vfu_endpoint_decode[] = {
21 	{"name", offsetof(struct rpc_delete_vfu_endpoint, name), spdk_json_decode_string }
22 };
23 
24 static void
25 free_rpc_delete_vfu_endpoint(struct rpc_delete_vfu_endpoint *req)
26 {
27 	free(req->name);
28 }
29 
30 static void
31 rpc_vfu_virtio_delete_endpoint(struct spdk_jsonrpc_request *request,
32 			       const struct spdk_json_val *params)
33 {
34 	struct rpc_delete_vfu_endpoint req = {0};
35 	int rc;
36 
37 	if (spdk_json_decode_object(params, rpc_delete_vfu_endpoint_decode,
38 				    SPDK_COUNTOF(rpc_delete_vfu_endpoint_decode),
39 				    &req)) {
40 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
41 		rc = -EINVAL;
42 		goto invalid;
43 	}
44 
45 	rc = spdk_vfu_delete_endpoint(req.name);
46 	if (rc < 0) {
47 		goto invalid;
48 	}
49 	free_rpc_delete_vfu_endpoint(&req);
50 
51 	spdk_jsonrpc_send_bool_response(request, true);
52 	return;
53 
54 invalid:
55 	free_rpc_delete_vfu_endpoint(&req);
56 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
57 					 spdk_strerror(-rc));
58 }
59 SPDK_RPC_REGISTER("vfu_virtio_delete_endpoint", rpc_vfu_virtio_delete_endpoint,
60 		  SPDK_RPC_RUNTIME)
61 
62 struct rpc_vfu_virtio_create_blk {
63 	char		*name;
64 	char		*bdev_name;
65 	char		*cpumask;
66 	uint16_t	num_queues;
67 	uint16_t	qsize;
68 	bool		packed_ring;
69 };
70 
71 static const struct spdk_json_object_decoder rpc_construct_vfu_virtio_create_blk[] = {
72 	{"name", offsetof(struct rpc_vfu_virtio_create_blk, name), spdk_json_decode_string },
73 	{"bdev_name", offsetof(struct rpc_vfu_virtio_create_blk, bdev_name), spdk_json_decode_string },
74 	{"cpumask", offsetof(struct rpc_vfu_virtio_create_blk, cpumask), spdk_json_decode_string, true},
75 	{"num_queues", offsetof(struct rpc_vfu_virtio_create_blk, num_queues), spdk_json_decode_uint16, true },
76 	{"qsize", offsetof(struct rpc_vfu_virtio_create_blk, qsize), spdk_json_decode_uint16, true },
77 	{"packed_ring", offsetof(struct rpc_vfu_virtio_create_blk, packed_ring), spdk_json_decode_bool, true},
78 };
79 
80 static void
81 free_rpc_vfu_virtio_create_blk(struct rpc_vfu_virtio_create_blk *req)
82 {
83 	free(req->name);
84 	free(req->bdev_name);
85 	free(req->cpumask);
86 }
87 
88 static void
89 rpc_vfu_virtio_create_blk_endpoint(struct spdk_jsonrpc_request *request,
90 				   const struct spdk_json_val *params)
91 {
92 	struct rpc_vfu_virtio_create_blk req = {0};
93 	int rc;
94 
95 	if (spdk_json_decode_object(params, rpc_construct_vfu_virtio_create_blk,
96 				    SPDK_COUNTOF(rpc_construct_vfu_virtio_create_blk),
97 				    &req)) {
98 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
99 		rc = -EINVAL;
100 		goto invalid;
101 	}
102 
103 	rc = spdk_vfu_create_endpoint(req.name, req.cpumask, "virtio_blk");
104 	if (rc) {
105 		SPDK_ERRLOG("Failed to create virtio_blk endpoint\n");
106 		goto invalid;
107 	}
108 
109 	rc = vfu_virtio_blk_add_bdev(req.name, req.bdev_name, req.num_queues, req.qsize,
110 				     req.packed_ring);
111 	if (rc < 0) {
112 		spdk_vfu_delete_endpoint(req.name);
113 		goto invalid;
114 	}
115 	free_rpc_vfu_virtio_create_blk(&req);
116 
117 	spdk_jsonrpc_send_bool_response(request, true);
118 	return;
119 
120 invalid:
121 	free_rpc_vfu_virtio_create_blk(&req);
122 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
123 					 spdk_strerror(-rc));
124 }
125 SPDK_RPC_REGISTER("vfu_virtio_create_blk_endpoint", rpc_vfu_virtio_create_blk_endpoint,
126 		  SPDK_RPC_RUNTIME)
127 
128 struct rpc_vfu_virtio_scsi {
129 	char		*name;
130 	uint8_t		scsi_target_num;
131 	char		*bdev_name;
132 };
133 
134 static const struct spdk_json_object_decoder rpc_construct_vfu_virtio_scsi[] = {
135 	{"name", offsetof(struct rpc_vfu_virtio_scsi, name), spdk_json_decode_string },
136 	{"scsi_target_num", offsetof(struct rpc_vfu_virtio_scsi, scsi_target_num), spdk_json_decode_uint8 },
137 	{"bdev_name", offsetof(struct rpc_vfu_virtio_scsi, bdev_name), spdk_json_decode_string },
138 };
139 
140 static void
141 free_rpc_vfu_virtio_scsi(struct rpc_vfu_virtio_scsi *req)
142 {
143 	free(req->name);
144 	free(req->bdev_name);
145 }
146 
147 static void
148 rpc_vfu_virtio_scsi_add_target(struct spdk_jsonrpc_request *request,
149 			       const struct spdk_json_val *params)
150 {
151 	struct rpc_vfu_virtio_scsi req = {0};
152 	int rc;
153 
154 	if (spdk_json_decode_object(params, rpc_construct_vfu_virtio_scsi,
155 				    SPDK_COUNTOF(rpc_construct_vfu_virtio_scsi),
156 				    &req)) {
157 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
158 		rc = -EINVAL;
159 		goto invalid;
160 	}
161 
162 	rc = vfu_virtio_scsi_add_target(req.name, req.scsi_target_num, req.bdev_name);;
163 	if (rc < 0) {
164 		goto invalid;
165 	}
166 
167 	free_rpc_vfu_virtio_scsi(&req);
168 	spdk_jsonrpc_send_bool_response(request, true);
169 	return;
170 
171 invalid:
172 	free_rpc_vfu_virtio_scsi(&req);
173 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
174 					 spdk_strerror(-rc));
175 }
176 SPDK_RPC_REGISTER("vfu_virtio_scsi_add_target", rpc_vfu_virtio_scsi_add_target,
177 		  SPDK_RPC_RUNTIME)
178 
179 struct rpc_vfu_virtio_scsi_remove {
180 	char		*name;
181 	uint8_t		scsi_target_num;
182 };
183 
184 static const struct spdk_json_object_decoder rpc_remove_vfu_virtio_scsi_target[] = {
185 	{"name", offsetof(struct rpc_vfu_virtio_scsi_remove, name), spdk_json_decode_string },
186 	{"scsi_target_num", offsetof(struct rpc_vfu_virtio_scsi_remove, scsi_target_num), spdk_json_decode_uint8 },
187 };
188 
189 static void
190 free_rpc_vfu_virtio_scsi_remove(struct rpc_vfu_virtio_scsi_remove *req)
191 {
192 	free(req->name);
193 }
194 
195 static void
196 rpc_vfu_virtio_scsi_remove_target(struct spdk_jsonrpc_request *request,
197 				  const struct spdk_json_val *params)
198 {
199 	struct rpc_vfu_virtio_scsi_remove req = {0};
200 	int rc;
201 
202 	if (spdk_json_decode_object(params, rpc_remove_vfu_virtio_scsi_target,
203 				    SPDK_COUNTOF(rpc_remove_vfu_virtio_scsi_target),
204 				    &req)) {
205 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
206 		rc = -EINVAL;
207 		goto invalid;
208 	}
209 
210 	rc = vfu_virtio_scsi_remove_target(req.name, req.scsi_target_num);
211 	if (rc < 0) {
212 		goto invalid;
213 	}
214 
215 	free_rpc_vfu_virtio_scsi_remove(&req);
216 	spdk_jsonrpc_send_bool_response(request, true);
217 	return;
218 
219 invalid:
220 	free_rpc_vfu_virtio_scsi_remove(&req);
221 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
222 					 spdk_strerror(-rc));
223 }
224 SPDK_RPC_REGISTER("vfu_virtio_scsi_remove_target", rpc_vfu_virtio_scsi_remove_target,
225 		  SPDK_RPC_RUNTIME)
226 
227 struct rpc_vfu_virtio_create_scsi {
228 	char		*name;
229 	char		*cpumask;
230 	uint16_t	num_io_queues;
231 	uint16_t	qsize;
232 	bool		packed_ring;
233 };
234 
235 static const struct spdk_json_object_decoder rpc_construct_vfu_virtio_create_scsi[] = {
236 	{"name", offsetof(struct rpc_vfu_virtio_create_scsi, name), spdk_json_decode_string },
237 	{"cpumask", offsetof(struct rpc_vfu_virtio_create_scsi, cpumask), spdk_json_decode_string, true},
238 	{"num_io_queues", offsetof(struct rpc_vfu_virtio_create_scsi, num_io_queues), spdk_json_decode_uint16, true },
239 	{"qsize", offsetof(struct rpc_vfu_virtio_create_scsi, qsize), spdk_json_decode_uint16, true },
240 	{"packed_ring", offsetof(struct rpc_vfu_virtio_create_scsi, packed_ring), spdk_json_decode_bool, true},
241 };
242 
243 static void
244 free_rpc_vfu_virtio_create_scsi(struct rpc_vfu_virtio_create_scsi *req)
245 {
246 	free(req->name);
247 	free(req->cpumask);
248 }
249 
250 static void
251 rpc_vfu_virtio_create_scsi_endpoint(struct spdk_jsonrpc_request *request,
252 				    const struct spdk_json_val *params)
253 {
254 	struct rpc_vfu_virtio_create_scsi req = {0};
255 	int rc;
256 
257 	if (spdk_json_decode_object(params, rpc_construct_vfu_virtio_create_scsi,
258 				    SPDK_COUNTOF(rpc_construct_vfu_virtio_create_scsi),
259 				    &req)) {
260 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
261 		rc = -EINVAL;
262 		goto invalid;
263 	}
264 
265 	rc = spdk_vfu_create_endpoint(req.name, req.cpumask, "virtio_scsi");
266 	if (rc) {
267 		SPDK_ERRLOG("Failed to create virtio_blk endpoint\n");
268 		goto invalid;
269 	}
270 
271 	rc = vfu_virtio_scsi_set_options(req.name, req.num_io_queues, req.qsize, req.packed_ring);
272 	if (rc < 0) {
273 		spdk_vfu_delete_endpoint(req.name);
274 		goto invalid;
275 	}
276 	free_rpc_vfu_virtio_create_scsi(&req);
277 
278 	spdk_jsonrpc_send_bool_response(request, true);
279 	return;
280 
281 invalid:
282 	free_rpc_vfu_virtio_create_scsi(&req);
283 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
284 					 spdk_strerror(-rc));
285 }
286 SPDK_RPC_REGISTER("vfu_virtio_create_scsi_endpoint", rpc_vfu_virtio_create_scsi_endpoint,
287 		  SPDK_RPC_RUNTIME)
288