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 : 67 : 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 : 67 : SPDK_RPC_REGISTER("ublk_destroy_target", rpc_ublk_destroy_target, SPDK_RPC_RUNTIME)
78 : :
79 : : struct rpc_ublk_start_disk {
80 : : char *bdev_name;
81 : : uint32_t ublk_id;
82 : : uint32_t num_queues;
83 : : uint32_t queue_depth;
84 : : struct spdk_jsonrpc_request *request;
85 : : };
86 : :
87 : : static const struct spdk_json_object_decoder rpc_ublk_start_disk_decoders[] = {
88 : : {"bdev_name", offsetof(struct rpc_ublk_start_disk, bdev_name), spdk_json_decode_string},
89 : : {"ublk_id", offsetof(struct rpc_ublk_start_disk, ublk_id), spdk_json_decode_uint32},
90 : : {"num_queues", offsetof(struct rpc_ublk_start_disk, num_queues), spdk_json_decode_uint32, true},
91 : : {"queue_depth", offsetof(struct rpc_ublk_start_disk, queue_depth), spdk_json_decode_uint32, true},
92 : : };
93 : :
94 : : static void
95 : 0 : free_rpc_ublk_start_disk(struct rpc_ublk_start_disk *req)
96 : : {
97 : 0 : free(req->bdev_name);
98 : 0 : free(req);
99 : 0 : }
100 : :
101 : : static void
102 : 0 : rpc_ublk_start_disk_done(void *cb_arg, int rc)
103 : : {
104 : 0 : struct rpc_ublk_start_disk *req = cb_arg;
105 : : struct spdk_json_write_ctx *w;
106 : :
107 [ # # ]: 0 : if (rc == 0) {
108 : 0 : w = spdk_jsonrpc_begin_result(req->request);
109 : 0 : spdk_json_write_uint32(w, req->ublk_id);
110 : 0 : spdk_jsonrpc_end_result(req->request, w);
111 : : } else {
112 : 0 : spdk_jsonrpc_send_error_response(req->request, rc, spdk_strerror(-rc));
113 : : }
114 : :
115 : 0 : free_rpc_ublk_start_disk(req);
116 : 0 : }
117 : :
118 : : static void
119 : 0 : rpc_ublk_start_disk(struct spdk_jsonrpc_request *request,
120 : : const struct spdk_json_val *params)
121 : : {
122 : : struct rpc_ublk_start_disk *req;
123 : : int rc;
124 : :
125 : 0 : req = calloc(1, sizeof(*req));
126 [ # # ]: 0 : if (req == NULL) {
127 : 0 : SPDK_ERRLOG("could not allocate request.\n");
128 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
129 : 0 : return;
130 : : }
131 : 0 : req->request = request;
132 : 0 : req->queue_depth = UBLK_DEV_QUEUE_DEPTH;
133 : 0 : req->num_queues = UBLK_DEV_NUM_QUEUE;
134 : :
135 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_ublk_start_disk_decoders,
136 : : SPDK_COUNTOF(rpc_ublk_start_disk_decoders),
137 : : req)) {
138 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
139 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
140 : : "spdk_json_decode_object failed");
141 : 0 : goto out;
142 : : }
143 : :
144 : 0 : rc = ublk_start_disk(req->bdev_name, req->ublk_id, req->num_queues, req->queue_depth,
145 : : rpc_ublk_start_disk_done, req);
146 [ # # ]: 0 : if (rc != 0) {
147 : 0 : rpc_ublk_start_disk_done(req, rc);
148 : : }
149 : :
150 : 0 : return;
151 : :
152 : 0 : out:
153 : 0 : free_rpc_ublk_start_disk(req);
154 : : }
155 : :
156 : 67 : SPDK_RPC_REGISTER("ublk_start_disk", rpc_ublk_start_disk, SPDK_RPC_RUNTIME)
157 : :
158 : : struct rpc_ublk_stop_disk {
159 : : uint32_t ublk_id;
160 : : struct spdk_jsonrpc_request *request;
161 : : };
162 : :
163 : : static void
164 : 0 : free_rpc_ublk_stop_disk(struct rpc_ublk_stop_disk *req)
165 : : {
166 : 0 : free(req);
167 : 0 : }
168 : :
169 : : static const struct spdk_json_object_decoder rpc_ublk_stop_disk_decoders[] = {
170 : : {"ublk_id", offsetof(struct rpc_ublk_stop_disk, ublk_id), spdk_json_decode_uint32},
171 : : };
172 : :
173 : : static void
174 : 0 : rpc_ublk_stop_disk_done(void *cb_arg, int rc)
175 : : {
176 : 0 : struct rpc_ublk_stop_disk *req = cb_arg;
177 : :
178 : 0 : spdk_jsonrpc_send_bool_response(req->request, true);
179 : 0 : free_rpc_ublk_stop_disk(req);
180 : 0 : }
181 : :
182 : : static void
183 : 0 : rpc_ublk_stop_disk(struct spdk_jsonrpc_request *request,
184 : : const struct spdk_json_val *params)
185 : : {
186 : : struct rpc_ublk_stop_disk *req;
187 : : int rc;
188 : :
189 : 0 : req = calloc(1, sizeof(*req));
190 [ # # ]: 0 : if (req == NULL) {
191 : 0 : SPDK_ERRLOG("could not allocate request.\n");
192 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
193 : 0 : return;
194 : : }
195 : 0 : req->request = request;
196 : :
197 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_ublk_stop_disk_decoders,
198 : : SPDK_COUNTOF(rpc_ublk_stop_disk_decoders),
199 : : req)) {
200 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
201 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
202 : : "spdk_json_decode_object failed");
203 : 0 : goto invalid;
204 : : }
205 : :
206 : 0 : rc = ublk_stop_disk(req->ublk_id, rpc_ublk_stop_disk_done, req);
207 [ # # ]: 0 : if (rc) {
208 : 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
209 : 0 : goto invalid;
210 : : }
211 : 0 : return;
212 : :
213 : 0 : invalid:
214 : 0 : free_rpc_ublk_stop_disk(req);
215 : : }
216 : :
217 : 67 : SPDK_RPC_REGISTER("ublk_stop_disk", rpc_ublk_stop_disk, SPDK_RPC_RUNTIME)
218 : :
219 : : static void
220 : 0 : rpc_dump_ublk_info(struct spdk_json_write_ctx *w,
221 : : struct spdk_ublk_dev *ublk)
222 : : {
223 : : char ublk_path[32];
224 : :
225 : 0 : snprintf(ublk_path, 32, "%s%u", "/dev/ublkb", ublk_dev_get_id(ublk));
226 : 0 : spdk_json_write_object_begin(w);
227 : :
228 : 0 : spdk_json_write_named_string(w, "ublk_device", ublk_path);
229 : 0 : spdk_json_write_named_uint32(w, "id", ublk_dev_get_id(ublk));
230 : 0 : spdk_json_write_named_uint32(w, "queue_depth", ublk_dev_get_queue_depth(ublk));
231 : 0 : spdk_json_write_named_uint32(w, "num_queues", ublk_dev_get_num_queues(ublk));
232 : 0 : spdk_json_write_named_string(w, "bdev_name", ublk_dev_get_bdev_name(ublk));
233 : :
234 : 0 : spdk_json_write_object_end(w);
235 : 0 : }
236 : :
237 : : struct rpc_ublk_get_disks {
238 : : uint32_t ublk_id;
239 : : };
240 : :
241 : : static const struct spdk_json_object_decoder rpc_ublk_get_disks_decoders[] = {
242 : : {"ublk_id", offsetof(struct rpc_ublk_get_disks, ublk_id), spdk_json_decode_uint32, true},
243 : : };
244 : :
245 : : static void
246 : 0 : rpc_ublk_get_disks(struct spdk_jsonrpc_request *request,
247 : : const struct spdk_json_val *params)
248 : : {
249 : 0 : struct rpc_ublk_get_disks req = {};
250 : : struct spdk_json_write_ctx *w;
251 : 0 : struct spdk_ublk_dev *ublk = NULL;
252 : :
253 [ # # ]: 0 : if (params != NULL) {
254 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_ublk_get_disks_decoders,
255 : : SPDK_COUNTOF(rpc_ublk_get_disks_decoders),
256 : : &req)) {
257 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
258 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
259 : : "spdk_json_decode_object failed");
260 : 0 : return;
261 : : }
262 : :
263 [ # # ]: 0 : if (req.ublk_id) {
264 : 0 : ublk = ublk_dev_find_by_id(req.ublk_id);
265 [ # # ]: 0 : if (ublk == NULL) {
266 : 0 : SPDK_ERRLOG("ublk device '%d' does not exist\n", req.ublk_id);
267 : 0 : spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
268 : 0 : return;
269 : : }
270 : : }
271 : : }
272 : :
273 : 0 : w = spdk_jsonrpc_begin_result(request);
274 : 0 : spdk_json_write_array_begin(w);
275 : :
276 [ # # ]: 0 : if (ublk != NULL) {
277 : 0 : rpc_dump_ublk_info(w, ublk);
278 : : } else {
279 [ # # ]: 0 : for (ublk = ublk_dev_first(); ublk != NULL; ublk = ublk_dev_next(ublk)) {
280 : 0 : rpc_dump_ublk_info(w, ublk);
281 : : }
282 : : }
283 : :
284 : 0 : spdk_json_write_array_end(w);
285 : 0 : spdk_jsonrpc_end_result(request, w);
286 : :
287 : 0 : return;
288 : : }
289 : 67 : SPDK_RPC_REGISTER("ublk_get_disks", rpc_ublk_get_disks, SPDK_RPC_RUNTIME)
290 : :
291 : : struct rpc_ublk_recover_disk {
292 : : char *bdev_name;
293 : : uint32_t ublk_id;
294 : : struct spdk_jsonrpc_request *request;
295 : : };
296 : :
297 : : static const struct spdk_json_object_decoder rpc_ublk_recover_disk_decoders[] = {
298 : : {"bdev_name", offsetof(struct rpc_ublk_recover_disk, bdev_name), spdk_json_decode_string},
299 : : {"ublk_id", offsetof(struct rpc_ublk_recover_disk, ublk_id), spdk_json_decode_uint32},
300 : : };
301 : :
302 : : static void
303 : 0 : free_rpc_ublk_recover_disk(struct rpc_ublk_recover_disk *req)
304 : : {
305 : 0 : free(req->bdev_name);
306 : 0 : free(req);
307 : 0 : }
308 : :
309 : : static void
310 : 0 : rpc_ublk_recover_disk_done(void *cb_arg, int rc)
311 : : {
312 : 0 : struct rpc_ublk_recover_disk *req = cb_arg;
313 : : struct spdk_json_write_ctx *w;
314 : :
315 [ # # ]: 0 : if (rc == 0) {
316 : 0 : w = spdk_jsonrpc_begin_result(req->request);
317 : 0 : spdk_json_write_uint32(w, req->ublk_id);
318 : 0 : spdk_jsonrpc_end_result(req->request, w);
319 : : } else {
320 : 0 : spdk_jsonrpc_send_error_response(req->request, rc, spdk_strerror(-rc));
321 : : }
322 : :
323 : 0 : free_rpc_ublk_recover_disk(req);
324 : 0 : }
325 : :
326 : : static void
327 : 0 : rpc_ublk_recover_disk(struct spdk_jsonrpc_request *request,
328 : : const struct spdk_json_val *params)
329 : : {
330 : : struct rpc_ublk_recover_disk *req;
331 : : int rc;
332 : :
333 : 0 : req = calloc(1, sizeof(*req));
334 [ # # ]: 0 : if (req == NULL) {
335 : 0 : SPDK_ERRLOG("could not allocate request.\n");
336 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
337 : 0 : return;
338 : : }
339 : 0 : req->request = request;
340 : :
341 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_ublk_recover_disk_decoders,
342 : : SPDK_COUNTOF(rpc_ublk_recover_disk_decoders),
343 : : req)) {
344 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
345 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
346 : : "spdk_json_decode_object failed");
347 : 0 : free(req);
348 : 0 : return;
349 : : }
350 : :
351 : 0 : rc = ublk_start_disk_recovery(req->bdev_name, req->ublk_id, NULL, NULL);
352 : 0 : rpc_ublk_recover_disk_done(req, rc);
353 : : }
354 : :
355 : 67 : SPDK_RPC_REGISTER("ublk_recover_disk", rpc_ublk_recover_disk, SPDK_RPC_RUNTIME)
|