Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/string.h"
7 : : #include "spdk/env.h"
8 : : #include "spdk/rpc.h"
9 : : #include "spdk/util.h"
10 : : #include "spdk/log.h"
11 : :
12 : : #include "ublk_internal.h"
13 : :
14 : : struct rpc_ublk_create_target {
15 : : char *cpumask;
16 : : };
17 : :
18 : : static const struct spdk_json_object_decoder rpc_ublk_create_target_decoders[] = {
19 : : {"cpumask", offsetof(struct rpc_ublk_create_target, cpumask), spdk_json_decode_string, true},
20 : : };
21 : :
22 : : static void
23 : 0 : free_rpc_ublk_create_target(struct rpc_ublk_create_target *req)
24 : : {
25 : 0 : free(req->cpumask);
26 : 0 : }
27 : :
28 : : static void
29 : 0 : rpc_ublk_create_target(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
30 : : {
31 : 0 : int rc = 0;
32 : 0 : struct rpc_ublk_create_target req = {};
33 : :
34 [ # # ]: 0 : if (params != NULL) {
35 [ # # ]: 0 : if (spdk_json_decode_object_relaxed(params, rpc_ublk_create_target_decoders,
36 : : SPDK_COUNTOF(rpc_ublk_create_target_decoders),
37 : : &req)) {
38 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
39 : 0 : rc = -EINVAL;
40 : 0 : goto invalid;
41 : : }
42 : : }
43 : 0 : rc = ublk_create_target(req.cpumask, params);
44 [ # # ]: 0 : if (rc != 0) {
45 : 0 : goto invalid;
46 : : }
47 : 0 : spdk_jsonrpc_send_bool_response(request, true);
48 : 0 : free_rpc_ublk_create_target(&req);
49 : 0 : return;
50 : 0 : invalid:
51 : 0 : SPDK_ERRLOG("Can't create ublk target: %s\n", spdk_strerror(-rc));
52 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc));
53 : 0 : free_rpc_ublk_create_target(&req);
54 : : }
55 : 476 : SPDK_RPC_REGISTER("ublk_create_target", rpc_ublk_create_target, SPDK_RPC_RUNTIME)
56 : :
57 : : static void
58 : 0 : ublk_destroy_target_done(void *arg)
59 : : {
60 : 0 : struct spdk_jsonrpc_request *req = arg;
61 : :
62 : 0 : spdk_jsonrpc_send_bool_response(req, true);
63 : 0 : SPDK_NOTICELOG("ublk target has been destroyed\n");
64 : 0 : }
65 : :
66 : : static void
67 : 0 : rpc_ublk_destroy_target(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
68 : : {
69 : 0 : int rc = 0;
70 : :
71 : 0 : rc = ublk_destroy_target(ublk_destroy_target_done, request);
72 [ # # ]: 0 : if (rc != 0) {
73 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc));
74 : 0 : SPDK_ERRLOG("Can't destroy ublk target: %s\n", spdk_strerror(-rc));
75 : : }
76 : 0 : }
77 : 476 : SPDK_RPC_REGISTER("ublk_destroy_target", rpc_ublk_destroy_target, SPDK_RPC_RUNTIME)
78 : :
79 : : struct rpc_ublk_use_fixed_files {
80 : : char *state;
81 : : };
82 : :
83 : : static const struct spdk_json_object_decoder rpc_ublk_use_fixed_files_decoders[] = {
84 : : {"state", offsetof(struct rpc_ublk_use_fixed_files, state), spdk_json_decode_string},
85 : : };
86 : :
87 : : static void
88 : 0 : free_rpc_ublk_use_fixed_files(struct rpc_ublk_use_fixed_files *req)
89 : : {
90 : 0 : free(req->state);
91 : 0 : }
92 : :
93 : : static void
94 : 0 : rpc_ublk_use_fixed_files(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
95 : : {
96 : 0 : int rc = 0;
97 : 0 : struct rpc_ublk_use_fixed_files req = {};
98 : :
99 [ # # ]: 0 : if (params != NULL) {
100 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_ublk_use_fixed_files_decoders,
101 : : SPDK_COUNTOF(rpc_ublk_use_fixed_files_decoders),
102 : : &req)) {
103 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
104 : 0 : rc = -EINVAL;
105 : 0 : goto invalid;
106 : : }
107 : : }
108 : 0 : rc = ublk_use_fixed_files(req.state);
109 [ # # ]: 0 : if (rc != 0) {
110 : 0 : goto invalid;
111 : : }
112 : 0 : free_rpc_ublk_use_fixed_files(&req);
113 : 0 : spdk_jsonrpc_send_bool_response(request, true);
114 : 0 : return;
115 : 0 : invalid:
116 : 0 : SPDK_ERRLOG("Can't change fixed file state: %s\n", spdk_strerror(-rc));
117 : 0 : free_rpc_ublk_use_fixed_files(&req);
118 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc));
119 : :
120 : : }
121 : 476 : SPDK_RPC_REGISTER("ublk_use_fixed_files", rpc_ublk_use_fixed_files, SPDK_RPC_RUNTIME)
122 : :
123 : : struct rpc_ublk_start_disk {
124 : : char *bdev_name;
125 : : uint32_t ublk_id;
126 : : uint32_t num_queues;
127 : : uint32_t queue_depth;
128 : : struct spdk_jsonrpc_request *request;
129 : : };
130 : :
131 : : static const struct spdk_json_object_decoder rpc_ublk_start_disk_decoders[] = {
132 : : {"bdev_name", offsetof(struct rpc_ublk_start_disk, bdev_name), spdk_json_decode_string},
133 : : {"ublk_id", offsetof(struct rpc_ublk_start_disk, ublk_id), spdk_json_decode_uint32},
134 : : {"num_queues", offsetof(struct rpc_ublk_start_disk, num_queues), spdk_json_decode_uint32, true},
135 : : {"queue_depth", offsetof(struct rpc_ublk_start_disk, queue_depth), spdk_json_decode_uint32, true},
136 : : };
137 : :
138 : : static void
139 : 0 : free_rpc_ublk_start_disk(struct rpc_ublk_start_disk *req)
140 : : {
141 : 0 : free(req->bdev_name);
142 : 0 : free(req);
143 : 0 : }
144 : :
145 : : static void
146 : 0 : rpc_ublk_start_disk_done(void *cb_arg, int rc)
147 : : {
148 : 0 : struct rpc_ublk_start_disk *req = cb_arg;
149 : : struct spdk_json_write_ctx *w;
150 : :
151 [ # # ]: 0 : if (rc == 0) {
152 : 0 : w = spdk_jsonrpc_begin_result(req->request);
153 : 0 : spdk_json_write_uint32(w, req->ublk_id);
154 : 0 : spdk_jsonrpc_end_result(req->request, w);
155 : : } else {
156 : 0 : spdk_jsonrpc_send_error_response(req->request, rc, spdk_strerror(-rc));
157 : : }
158 : :
159 : 0 : free_rpc_ublk_start_disk(req);
160 : 0 : }
161 : :
162 : : static void
163 : 0 : rpc_ublk_start_disk(struct spdk_jsonrpc_request *request,
164 : : const struct spdk_json_val *params)
165 : : {
166 : : struct rpc_ublk_start_disk *req;
167 : : int rc;
168 : :
169 : 0 : req = calloc(1, sizeof(*req));
170 [ # # ]: 0 : if (req == NULL) {
171 : 0 : SPDK_ERRLOG("could not allocate request.\n");
172 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
173 : 0 : return;
174 : : }
175 : 0 : req->request = request;
176 : 0 : req->queue_depth = UBLK_DEV_QUEUE_DEPTH;
177 : 0 : req->num_queues = UBLK_DEV_NUM_QUEUE;
178 : :
179 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_ublk_start_disk_decoders,
180 : : SPDK_COUNTOF(rpc_ublk_start_disk_decoders),
181 : : req)) {
182 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
183 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
184 : : "spdk_json_decode_object failed");
185 : 0 : goto out;
186 : : }
187 : :
188 : 0 : rc = ublk_start_disk(req->bdev_name, req->ublk_id, req->num_queues, req->queue_depth,
189 : : rpc_ublk_start_disk_done, req);
190 [ # # ]: 0 : if (rc != 0) {
191 : 0 : rpc_ublk_start_disk_done(req, rc);
192 : : }
193 : :
194 : 0 : return;
195 : :
196 : 0 : out:
197 : 0 : free_rpc_ublk_start_disk(req);
198 : : }
199 : :
200 : 476 : SPDK_RPC_REGISTER("ublk_start_disk", rpc_ublk_start_disk, SPDK_RPC_RUNTIME)
201 : :
202 : : struct rpc_ublk_stop_disk {
203 : : uint32_t ublk_id;
204 : : struct spdk_jsonrpc_request *request;
205 : : };
206 : :
207 : : static void
208 : 0 : free_rpc_ublk_stop_disk(struct rpc_ublk_stop_disk *req)
209 : : {
210 : 0 : free(req);
211 : 0 : }
212 : :
213 : : static const struct spdk_json_object_decoder rpc_ublk_stop_disk_decoders[] = {
214 : : {"ublk_id", offsetof(struct rpc_ublk_stop_disk, ublk_id), spdk_json_decode_uint32},
215 : : };
216 : :
217 : : static void
218 : 0 : rpc_ublk_stop_disk_done(void *cb_arg, int rc)
219 : : {
220 : 0 : struct rpc_ublk_stop_disk *req = cb_arg;
221 : :
222 : 0 : spdk_jsonrpc_send_bool_response(req->request, true);
223 : 0 : free_rpc_ublk_stop_disk(req);
224 : 0 : }
225 : :
226 : : static void
227 : 0 : rpc_ublk_stop_disk(struct spdk_jsonrpc_request *request,
228 : : const struct spdk_json_val *params)
229 : : {
230 : : struct rpc_ublk_stop_disk *req;
231 : : int rc;
232 : :
233 : 0 : req = calloc(1, sizeof(*req));
234 [ # # ]: 0 : if (req == NULL) {
235 : 0 : SPDK_ERRLOG("could not allocate request.\n");
236 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
237 : 0 : return;
238 : : }
239 : 0 : req->request = request;
240 : :
241 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_ublk_stop_disk_decoders,
242 : : SPDK_COUNTOF(rpc_ublk_stop_disk_decoders),
243 : : req)) {
244 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
245 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
246 : : "spdk_json_decode_object failed");
247 : 0 : goto invalid;
248 : : }
249 : :
250 : 0 : rc = ublk_stop_disk(req->ublk_id, rpc_ublk_stop_disk_done, req);
251 [ # # ]: 0 : if (rc) {
252 : 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
253 : 0 : goto invalid;
254 : : }
255 : 0 : return;
256 : :
257 : 0 : invalid:
258 : 0 : free_rpc_ublk_stop_disk(req);
259 : : }
260 : :
261 : 476 : SPDK_RPC_REGISTER("ublk_stop_disk", rpc_ublk_stop_disk, SPDK_RPC_RUNTIME)
262 : :
263 : : static void
264 : 0 : rpc_dump_ublk_info(struct spdk_json_write_ctx *w,
265 : : struct spdk_ublk_dev *ublk)
266 : : {
267 : 0 : char ublk_path[32];
268 : :
269 [ # # ]: 0 : snprintf(ublk_path, 32, "%s%u", "/dev/ublkb", ublk_dev_get_id(ublk));
270 : 0 : spdk_json_write_object_begin(w);
271 : :
272 : 0 : spdk_json_write_named_string(w, "ublk_device", ublk_path);
273 : 0 : spdk_json_write_named_uint32(w, "id", ublk_dev_get_id(ublk));
274 : 0 : spdk_json_write_named_uint32(w, "queue_depth", ublk_dev_get_queue_depth(ublk));
275 : 0 : spdk_json_write_named_uint32(w, "num_queues", ublk_dev_get_num_queues(ublk));
276 : 0 : spdk_json_write_named_string(w, "bdev_name", ublk_dev_get_bdev_name(ublk));
277 : :
278 : 0 : spdk_json_write_object_end(w);
279 : 0 : }
280 : :
281 : : struct rpc_ublk_get_disks {
282 : : uint32_t ublk_id;
283 : : };
284 : :
285 : : static const struct spdk_json_object_decoder rpc_ublk_get_disks_decoders[] = {
286 : : {"ublk_id", offsetof(struct rpc_ublk_get_disks, ublk_id), spdk_json_decode_uint32, true},
287 : : };
288 : :
289 : : static void
290 : 0 : rpc_ublk_get_disks(struct spdk_jsonrpc_request *request,
291 : : const struct spdk_json_val *params)
292 : : {
293 : 0 : struct rpc_ublk_get_disks req = {};
294 : : struct spdk_json_write_ctx *w;
295 : 0 : struct spdk_ublk_dev *ublk = NULL;
296 : :
297 [ # # ]: 0 : if (params != NULL) {
298 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_ublk_get_disks_decoders,
299 : : SPDK_COUNTOF(rpc_ublk_get_disks_decoders),
300 : : &req)) {
301 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
302 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
303 : : "spdk_json_decode_object failed");
304 : 0 : return;
305 : : }
306 : :
307 [ # # ]: 0 : if (req.ublk_id) {
308 : 0 : ublk = ublk_dev_find_by_id(req.ublk_id);
309 [ # # ]: 0 : if (ublk == NULL) {
310 : 0 : SPDK_ERRLOG("ublk device '%d' does not exist\n", req.ublk_id);
311 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
312 : 0 : return;
313 : : }
314 : : }
315 : : }
316 : :
317 : 0 : w = spdk_jsonrpc_begin_result(request);
318 : 0 : spdk_json_write_array_begin(w);
319 : :
320 [ # # ]: 0 : if (ublk != NULL) {
321 : 0 : rpc_dump_ublk_info(w, ublk);
322 : : } else {
323 [ # # ]: 0 : for (ublk = ublk_dev_first(); ublk != NULL; ublk = ublk_dev_next(ublk)) {
324 : 0 : rpc_dump_ublk_info(w, ublk);
325 : : }
326 : : }
327 : :
328 : 0 : spdk_json_write_array_end(w);
329 : 0 : spdk_jsonrpc_end_result(request, w);
330 : :
331 : 0 : return;
332 : : }
333 : 476 : SPDK_RPC_REGISTER("ublk_get_disks", rpc_ublk_get_disks, SPDK_RPC_RUNTIME)
334 : :
335 : : struct rpc_ublk_recover_disk {
336 : : char *bdev_name;
337 : : uint32_t ublk_id;
338 : : struct spdk_jsonrpc_request *request;
339 : : };
340 : :
341 : : static const struct spdk_json_object_decoder rpc_ublk_recover_disk_decoders[] = {
342 : : {"bdev_name", offsetof(struct rpc_ublk_recover_disk, bdev_name), spdk_json_decode_string},
343 : : {"ublk_id", offsetof(struct rpc_ublk_recover_disk, ublk_id), spdk_json_decode_uint32},
344 : : };
345 : :
346 : : static void
347 : 0 : free_rpc_ublk_recover_disk(struct rpc_ublk_recover_disk *req)
348 : : {
349 : 0 : free(req->bdev_name);
350 : 0 : free(req);
351 : 0 : }
352 : :
353 : : static void
354 : 0 : rpc_ublk_recover_disk_done(void *cb_arg, int rc)
355 : : {
356 : 0 : struct rpc_ublk_recover_disk *req = cb_arg;
357 : : struct spdk_json_write_ctx *w;
358 : :
359 [ # # ]: 0 : if (rc == 0) {
360 : 0 : w = spdk_jsonrpc_begin_result(req->request);
361 : 0 : spdk_json_write_uint32(w, req->ublk_id);
362 : 0 : spdk_jsonrpc_end_result(req->request, w);
363 : : } else {
364 : 0 : spdk_jsonrpc_send_error_response(req->request, rc, spdk_strerror(-rc));
365 : : }
366 : :
367 : 0 : free_rpc_ublk_recover_disk(req);
368 : 0 : }
369 : :
370 : : static void
371 : 0 : rpc_ublk_recover_disk(struct spdk_jsonrpc_request *request,
372 : : const struct spdk_json_val *params)
373 : : {
374 : : struct rpc_ublk_recover_disk *req;
375 : : int rc;
376 : :
377 : 0 : req = calloc(1, sizeof(*req));
378 [ # # ]: 0 : if (req == NULL) {
379 : 0 : SPDK_ERRLOG("could not allocate request.\n");
380 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
381 : 0 : return;
382 : : }
383 : 0 : req->request = request;
384 : :
385 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_ublk_recover_disk_decoders,
386 : : SPDK_COUNTOF(rpc_ublk_recover_disk_decoders),
387 : : req)) {
388 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
389 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
390 : : "spdk_json_decode_object failed");
391 : 0 : free(req);
392 : 0 : return;
393 : : }
394 : :
395 : 0 : rc = ublk_start_disk_recovery(req->bdev_name, req->ublk_id, NULL, NULL);
396 : 0 : rpc_ublk_recover_disk_done(req, rc);
397 : : }
398 : :
399 : 476 : SPDK_RPC_REGISTER("ublk_recover_disk", rpc_ublk_recover_disk, SPDK_RPC_RUNTIME)
|