Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2016 Intel Corporation.
3 : * All rights reserved.
4 : */
5 :
6 : #include "bdev_rbd.h"
7 : #include "spdk/util.h"
8 : #include "spdk/uuid.h"
9 : #include "spdk/string.h"
10 : #include "spdk/log.h"
11 :
12 : struct rpc_create_rbd {
13 : char *name;
14 : char *user_id;
15 : char *pool_name;
16 : char *rbd_name;
17 : uint32_t block_size;
18 : char **config;
19 : char *cluster_name;
20 : struct spdk_uuid uuid;
21 : };
22 :
23 : static void
24 0 : free_rpc_create_rbd(struct rpc_create_rbd *req)
25 : {
26 0 : free(req->name);
27 0 : free(req->user_id);
28 0 : free(req->pool_name);
29 0 : free(req->rbd_name);
30 0 : bdev_rbd_free_config(req->config);
31 0 : free(req->cluster_name);
32 0 : }
33 :
34 : static int
35 0 : bdev_rbd_decode_config(const struct spdk_json_val *values, void *out)
36 : {
37 0 : char ***map = out;
38 0 : char **entry;
39 0 : uint32_t i;
40 :
41 0 : if (values->type == SPDK_JSON_VAL_NULL) {
42 : /* treated like empty object: empty config */
43 0 : *map = calloc(1, sizeof(**map));
44 0 : if (!*map) {
45 0 : return -1;
46 : }
47 0 : return 0;
48 : }
49 :
50 0 : if (values->type != SPDK_JSON_VAL_OBJECT_BEGIN) {
51 0 : return -1;
52 : }
53 :
54 0 : *map = calloc(values->len + 1, sizeof(**map));
55 0 : if (!*map) {
56 0 : return -1;
57 : }
58 :
59 0 : for (i = 0, entry = *map; i < values->len;) {
60 0 : const struct spdk_json_val *name = &values[i + 1];
61 0 : const struct spdk_json_val *v = &values[i + 2];
62 : /* Here we catch errors like invalid types. */
63 0 : if (!(entry[0] = spdk_json_strdup(name)) ||
64 0 : !(entry[1] = spdk_json_strdup(v))) {
65 0 : bdev_rbd_free_config(*map);
66 0 : *map = NULL;
67 0 : return -1;
68 : }
69 0 : i += 1 + spdk_json_val_len(v);
70 0 : entry += 2;
71 0 : }
72 :
73 0 : return 0;
74 0 : }
75 :
76 : static const struct spdk_json_object_decoder rpc_create_rbd_decoders[] = {
77 : {"name", offsetof(struct rpc_create_rbd, name), spdk_json_decode_string, true},
78 : {"user_id", offsetof(struct rpc_create_rbd, user_id), spdk_json_decode_string, true},
79 : {"pool_name", offsetof(struct rpc_create_rbd, pool_name), spdk_json_decode_string},
80 : {"rbd_name", offsetof(struct rpc_create_rbd, rbd_name), spdk_json_decode_string},
81 : {"block_size", offsetof(struct rpc_create_rbd, block_size), spdk_json_decode_uint32},
82 : {"config", offsetof(struct rpc_create_rbd, config), bdev_rbd_decode_config, true},
83 : {"cluster_name", offsetof(struct rpc_create_rbd, cluster_name), spdk_json_decode_string, true},
84 : {"uuid", offsetof(struct rpc_create_rbd, uuid), spdk_json_decode_uuid, true}
85 : };
86 :
87 : static void
88 0 : rpc_bdev_rbd_create(struct spdk_jsonrpc_request *request,
89 : const struct spdk_json_val *params)
90 : {
91 0 : struct rpc_create_rbd req = {};
92 0 : struct spdk_json_write_ctx *w;
93 0 : struct spdk_bdev *bdev;
94 0 : int rc = 0;
95 :
96 0 : if (spdk_json_decode_object(params, rpc_create_rbd_decoders,
97 : SPDK_COUNTOF(rpc_create_rbd_decoders),
98 : &req)) {
99 0 : SPDK_DEBUGLOG(bdev_rbd, "spdk_json_decode_object failed\n");
100 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
101 : "spdk_json_decode_object failed");
102 0 : goto cleanup;
103 : }
104 :
105 0 : rc = bdev_rbd_create(&bdev, req.name, req.user_id, req.pool_name,
106 0 : (const char *const *)req.config,
107 0 : req.rbd_name,
108 0 : req.block_size, req.cluster_name, &req.uuid);
109 0 : if (rc) {
110 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
111 0 : goto cleanup;
112 : }
113 :
114 0 : w = spdk_jsonrpc_begin_result(request);
115 0 : spdk_json_write_string(w, spdk_bdev_get_name(bdev));
116 0 : spdk_jsonrpc_end_result(request, w);
117 :
118 : cleanup:
119 0 : free_rpc_create_rbd(&req);
120 0 : }
121 0 : SPDK_RPC_REGISTER("bdev_rbd_create", rpc_bdev_rbd_create, SPDK_RPC_RUNTIME)
122 :
123 : struct rpc_bdev_rbd_delete {
124 : char *name;
125 : };
126 :
127 : static void
128 0 : free_rpc_bdev_rbd_delete(struct rpc_bdev_rbd_delete *req)
129 : {
130 0 : free(req->name);
131 0 : }
132 :
133 : static const struct spdk_json_object_decoder rpc_bdev_rbd_delete_decoders[] = {
134 : {"name", offsetof(struct rpc_bdev_rbd_delete, name), spdk_json_decode_string},
135 : };
136 :
137 : static void
138 0 : _rpc_bdev_rbd_delete_cb(void *cb_arg, int bdeverrno)
139 : {
140 0 : struct spdk_jsonrpc_request *request = cb_arg;
141 :
142 0 : if (bdeverrno == 0) {
143 0 : spdk_jsonrpc_send_bool_response(request, true);
144 0 : } else {
145 0 : spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
146 : }
147 0 : }
148 :
149 : static void
150 0 : rpc_bdev_rbd_delete(struct spdk_jsonrpc_request *request,
151 : const struct spdk_json_val *params)
152 : {
153 0 : struct rpc_bdev_rbd_delete req = {NULL};
154 :
155 0 : if (spdk_json_decode_object(params, rpc_bdev_rbd_delete_decoders,
156 : SPDK_COUNTOF(rpc_bdev_rbd_delete_decoders),
157 : &req)) {
158 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
159 : "spdk_json_decode_object failed");
160 0 : goto cleanup;
161 : }
162 :
163 0 : bdev_rbd_delete(req.name, _rpc_bdev_rbd_delete_cb, request);
164 :
165 : cleanup:
166 0 : free_rpc_bdev_rbd_delete(&req);
167 0 : }
168 0 : SPDK_RPC_REGISTER("bdev_rbd_delete", rpc_bdev_rbd_delete, SPDK_RPC_RUNTIME)
169 :
170 : struct rpc_bdev_rbd_resize {
171 : char *name;
172 : uint64_t new_size;
173 : };
174 :
175 : static const struct spdk_json_object_decoder rpc_bdev_rbd_resize_decoders[] = {
176 : {"name", offsetof(struct rpc_bdev_rbd_resize, name), spdk_json_decode_string},
177 : {"new_size", offsetof(struct rpc_bdev_rbd_resize, new_size), spdk_json_decode_uint64}
178 : };
179 :
180 : static void
181 0 : free_rpc_bdev_rbd_resize(struct rpc_bdev_rbd_resize *req)
182 : {
183 0 : free(req->name);
184 0 : }
185 :
186 : static void
187 0 : rpc_bdev_rbd_resize(struct spdk_jsonrpc_request *request,
188 : const struct spdk_json_val *params)
189 : {
190 0 : struct rpc_bdev_rbd_resize req = {};
191 0 : int rc;
192 :
193 0 : if (spdk_json_decode_object(params, rpc_bdev_rbd_resize_decoders,
194 : SPDK_COUNTOF(rpc_bdev_rbd_resize_decoders),
195 : &req)) {
196 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
197 : "spdk_json_decode_object failed");
198 0 : goto cleanup;
199 : }
200 :
201 0 : rc = bdev_rbd_resize(req.name, req.new_size);
202 0 : if (rc) {
203 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
204 0 : goto cleanup;
205 : }
206 :
207 0 : spdk_jsonrpc_send_bool_response(request, true);
208 : cleanup:
209 0 : free_rpc_bdev_rbd_resize(&req);
210 0 : }
211 0 : SPDK_RPC_REGISTER("bdev_rbd_resize", rpc_bdev_rbd_resize, SPDK_RPC_RUNTIME)
212 :
213 : static void
214 0 : free_rpc_register_cluster(struct cluster_register_info *req)
215 : {
216 0 : free(req->name);
217 0 : free(req->user_id);
218 0 : bdev_rbd_free_config(req->config_param);
219 0 : free(req->config_file);
220 0 : free(req->key_file);
221 0 : free(req->core_mask);
222 0 : }
223 :
224 : static const struct spdk_json_object_decoder rpc_register_cluster_decoders[] = {
225 : {"name", offsetof(struct cluster_register_info, name), spdk_json_decode_string, true},
226 : {"user_id", offsetof(struct cluster_register_info, user_id), spdk_json_decode_string, true},
227 : {"config_param", offsetof(struct cluster_register_info, config_param), bdev_rbd_decode_config, true},
228 : {"config_file", offsetof(struct cluster_register_info, config_file), spdk_json_decode_string, true},
229 : {"key_file", offsetof(struct cluster_register_info, key_file), spdk_json_decode_string, true},
230 : {"core_mask", offsetof(struct cluster_register_info, core_mask), spdk_json_decode_string, true}
231 : };
232 :
233 : static void
234 0 : rpc_bdev_rbd_register_cluster(struct spdk_jsonrpc_request *request,
235 : const struct spdk_json_val *params)
236 : {
237 0 : struct cluster_register_info req = {};
238 0 : int rc = 0;
239 0 : struct spdk_json_write_ctx *w;
240 :
241 0 : if (spdk_json_decode_object(params, rpc_register_cluster_decoders,
242 : SPDK_COUNTOF(rpc_register_cluster_decoders),
243 : &req)) {
244 0 : SPDK_DEBUGLOG(bdev_rbd, "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 cleanup;
248 : }
249 :
250 0 : rc = bdev_rbd_register_cluster(&req);
251 0 : if (rc) {
252 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
253 0 : goto cleanup;
254 : }
255 :
256 0 : w = spdk_jsonrpc_begin_result(request);
257 0 : spdk_json_write_string(w, req.name);
258 0 : spdk_jsonrpc_end_result(request, w);
259 : cleanup:
260 0 : free_rpc_register_cluster(&req);
261 0 : }
262 0 : SPDK_RPC_REGISTER("bdev_rbd_register_cluster", rpc_bdev_rbd_register_cluster, SPDK_RPC_RUNTIME)
263 :
264 : struct rpc_bdev_rbd_unregister_cluster {
265 : char *name;
266 : };
267 :
268 : static void
269 0 : free_rpc_bdev_cluster_unregister(struct rpc_bdev_rbd_unregister_cluster *req)
270 : {
271 0 : free(req->name);
272 0 : }
273 :
274 : static const struct spdk_json_object_decoder rpc_bdev_rbd_unregister_cluster_decoders[] = {
275 : {"name", offsetof(struct rpc_bdev_rbd_unregister_cluster, name), spdk_json_decode_string},
276 : };
277 :
278 : static void
279 0 : rpc_bdev_rbd_unregister_cluster(struct spdk_jsonrpc_request *request,
280 : const struct spdk_json_val *params)
281 : {
282 0 : struct rpc_bdev_rbd_unregister_cluster req = {NULL};
283 0 : int rc;
284 :
285 0 : if (spdk_json_decode_object(params, rpc_bdev_rbd_unregister_cluster_decoders,
286 : SPDK_COUNTOF(rpc_bdev_rbd_unregister_cluster_decoders),
287 : &req)) {
288 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
289 : "spdk_json_decode_object failed");
290 0 : goto cleanup;
291 : }
292 :
293 0 : rc = bdev_rbd_unregister_cluster(req.name);
294 0 : if (rc) {
295 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
296 0 : goto cleanup;
297 : }
298 :
299 0 : spdk_jsonrpc_send_bool_response(request, true);
300 :
301 : cleanup:
302 0 : free_rpc_bdev_cluster_unregister(&req);
303 0 : }
304 0 : SPDK_RPC_REGISTER("bdev_rbd_unregister_cluster", rpc_bdev_rbd_unregister_cluster, SPDK_RPC_RUNTIME)
305 :
306 : struct rpc_bdev_rbd_get_cluster_info {
307 : char *name;
308 : };
309 :
310 : static void
311 0 : free_rpc_bdev_rbd_get_cluster_info(struct rpc_bdev_rbd_get_cluster_info *req)
312 : {
313 0 : free(req->name);
314 0 : }
315 :
316 : static const struct spdk_json_object_decoder rpc_bdev_rbd_get_cluster_info_decoders[] = {
317 : {"name", offsetof(struct rpc_bdev_rbd_get_cluster_info, name), spdk_json_decode_string, true},
318 : };
319 :
320 : static void
321 0 : rpc_bdev_rbd_get_clusters_info(struct spdk_jsonrpc_request *request,
322 : const struct spdk_json_val *params)
323 : {
324 0 : struct rpc_bdev_rbd_get_cluster_info req = {NULL};
325 0 : int rc;
326 :
327 0 : if (params && spdk_json_decode_object(params, rpc_bdev_rbd_get_cluster_info_decoders,
328 : SPDK_COUNTOF(rpc_bdev_rbd_get_cluster_info_decoders),
329 : &req)) {
330 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
331 : "spdk_json_decode_object failed");
332 0 : goto cleanup;
333 : }
334 :
335 0 : rc = bdev_rbd_get_clusters_info(request, req.name);
336 0 : if (rc) {
337 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
338 0 : goto cleanup;
339 : }
340 :
341 : cleanup:
342 0 : free_rpc_bdev_rbd_get_cluster_info(&req);
343 0 : }
344 0 : SPDK_RPC_REGISTER("bdev_rbd_get_clusters_info", rpc_bdev_rbd_get_clusters_info, SPDK_RPC_RUNTIME)
|