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
free_rpc_create_rbd(struct rpc_create_rbd * req)24 free_rpc_create_rbd(struct rpc_create_rbd *req)
25 {
26 free(req->name);
27 free(req->user_id);
28 free(req->pool_name);
29 free(req->rbd_name);
30 bdev_rbd_free_config(req->config);
31 free(req->cluster_name);
32 }
33
34 static int
bdev_rbd_decode_config(const struct spdk_json_val * values,void * out)35 bdev_rbd_decode_config(const struct spdk_json_val *values, void *out)
36 {
37 char ***map = out;
38 char **entry;
39 uint32_t i;
40
41 if (values->type == SPDK_JSON_VAL_NULL) {
42 /* treated like empty object: empty config */
43 *map = calloc(1, sizeof(**map));
44 if (!*map) {
45 return -1;
46 }
47 return 0;
48 }
49
50 if (values->type != SPDK_JSON_VAL_OBJECT_BEGIN) {
51 return -1;
52 }
53
54 *map = calloc(values->len + 1, sizeof(**map));
55 if (!*map) {
56 return -1;
57 }
58
59 for (i = 0, entry = *map; i < values->len;) {
60 const struct spdk_json_val *name = &values[i + 1];
61 const struct spdk_json_val *v = &values[i + 2];
62 /* Here we catch errors like invalid types. */
63 if (!(entry[0] = spdk_json_strdup(name)) ||
64 !(entry[1] = spdk_json_strdup(v))) {
65 bdev_rbd_free_config(*map);
66 *map = NULL;
67 return -1;
68 }
69 i += 1 + spdk_json_val_len(v);
70 entry += 2;
71 }
72
73 return 0;
74 }
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
rpc_bdev_rbd_create(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)88 rpc_bdev_rbd_create(struct spdk_jsonrpc_request *request,
89 const struct spdk_json_val *params)
90 {
91 struct rpc_create_rbd req = {};
92 struct spdk_json_write_ctx *w;
93 struct spdk_bdev *bdev;
94 int rc = 0;
95
96 if (spdk_json_decode_object(params, rpc_create_rbd_decoders,
97 SPDK_COUNTOF(rpc_create_rbd_decoders),
98 &req)) {
99 SPDK_DEBUGLOG(bdev_rbd, "spdk_json_decode_object failed\n");
100 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
101 "spdk_json_decode_object failed");
102 goto cleanup;
103 }
104
105 rc = bdev_rbd_create(&bdev, req.name, req.user_id, req.pool_name,
106 (const char *const *)req.config,
107 req.rbd_name,
108 req.block_size, req.cluster_name, &req.uuid);
109 if (rc) {
110 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
111 goto cleanup;
112 }
113
114 w = spdk_jsonrpc_begin_result(request);
115 spdk_json_write_string(w, spdk_bdev_get_name(bdev));
116 spdk_jsonrpc_end_result(request, w);
117
118 cleanup:
119 free_rpc_create_rbd(&req);
120 }
121 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
free_rpc_bdev_rbd_delete(struct rpc_bdev_rbd_delete * req)128 free_rpc_bdev_rbd_delete(struct rpc_bdev_rbd_delete *req)
129 {
130 free(req->name);
131 }
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
_rpc_bdev_rbd_delete_cb(void * cb_arg,int bdeverrno)138 _rpc_bdev_rbd_delete_cb(void *cb_arg, int bdeverrno)
139 {
140 struct spdk_jsonrpc_request *request = cb_arg;
141
142 if (bdeverrno == 0) {
143 spdk_jsonrpc_send_bool_response(request, true);
144 } else {
145 spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
146 }
147 }
148
149 static void
rpc_bdev_rbd_delete(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)150 rpc_bdev_rbd_delete(struct spdk_jsonrpc_request *request,
151 const struct spdk_json_val *params)
152 {
153 struct rpc_bdev_rbd_delete req = {NULL};
154
155 if (spdk_json_decode_object(params, rpc_bdev_rbd_delete_decoders,
156 SPDK_COUNTOF(rpc_bdev_rbd_delete_decoders),
157 &req)) {
158 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
159 "spdk_json_decode_object failed");
160 goto cleanup;
161 }
162
163 bdev_rbd_delete(req.name, _rpc_bdev_rbd_delete_cb, request);
164
165 cleanup:
166 free_rpc_bdev_rbd_delete(&req);
167 }
168 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
free_rpc_bdev_rbd_resize(struct rpc_bdev_rbd_resize * req)181 free_rpc_bdev_rbd_resize(struct rpc_bdev_rbd_resize *req)
182 {
183 free(req->name);
184 }
185
186 static void
rpc_bdev_rbd_resize(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)187 rpc_bdev_rbd_resize(struct spdk_jsonrpc_request *request,
188 const struct spdk_json_val *params)
189 {
190 struct rpc_bdev_rbd_resize req = {};
191 int rc;
192
193 if (spdk_json_decode_object(params, rpc_bdev_rbd_resize_decoders,
194 SPDK_COUNTOF(rpc_bdev_rbd_resize_decoders),
195 &req)) {
196 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
197 "spdk_json_decode_object failed");
198 goto cleanup;
199 }
200
201 rc = bdev_rbd_resize(req.name, req.new_size);
202 if (rc) {
203 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
204 goto cleanup;
205 }
206
207 spdk_jsonrpc_send_bool_response(request, true);
208 cleanup:
209 free_rpc_bdev_rbd_resize(&req);
210 }
211 SPDK_RPC_REGISTER("bdev_rbd_resize", rpc_bdev_rbd_resize, SPDK_RPC_RUNTIME)
212
213 static void
free_rpc_register_cluster(struct cluster_register_info * req)214 free_rpc_register_cluster(struct cluster_register_info *req)
215 {
216 free(req->name);
217 free(req->user_id);
218 bdev_rbd_free_config(req->config_param);
219 free(req->config_file);
220 free(req->key_file);
221 free(req->core_mask);
222 }
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
rpc_bdev_rbd_register_cluster(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)234 rpc_bdev_rbd_register_cluster(struct spdk_jsonrpc_request *request,
235 const struct spdk_json_val *params)
236 {
237 struct cluster_register_info req = {};
238 int rc = 0;
239 struct spdk_json_write_ctx *w;
240
241 if (spdk_json_decode_object(params, rpc_register_cluster_decoders,
242 SPDK_COUNTOF(rpc_register_cluster_decoders),
243 &req)) {
244 SPDK_DEBUGLOG(bdev_rbd, "spdk_json_decode_object failed\n");
245 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
246 "spdk_json_decode_object failed");
247 goto cleanup;
248 }
249
250 rc = bdev_rbd_register_cluster(&req);
251 if (rc) {
252 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
253 goto cleanup;
254 }
255
256 w = spdk_jsonrpc_begin_result(request);
257 spdk_json_write_string(w, req.name);
258 spdk_jsonrpc_end_result(request, w);
259 cleanup:
260 free_rpc_register_cluster(&req);
261 }
262 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
free_rpc_bdev_cluster_unregister(struct rpc_bdev_rbd_unregister_cluster * req)269 free_rpc_bdev_cluster_unregister(struct rpc_bdev_rbd_unregister_cluster *req)
270 {
271 free(req->name);
272 }
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
rpc_bdev_rbd_unregister_cluster(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)279 rpc_bdev_rbd_unregister_cluster(struct spdk_jsonrpc_request *request,
280 const struct spdk_json_val *params)
281 {
282 struct rpc_bdev_rbd_unregister_cluster req = {NULL};
283 int rc;
284
285 if (spdk_json_decode_object(params, rpc_bdev_rbd_unregister_cluster_decoders,
286 SPDK_COUNTOF(rpc_bdev_rbd_unregister_cluster_decoders),
287 &req)) {
288 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
289 "spdk_json_decode_object failed");
290 goto cleanup;
291 }
292
293 rc = bdev_rbd_unregister_cluster(req.name);
294 if (rc) {
295 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
296 goto cleanup;
297 }
298
299 spdk_jsonrpc_send_bool_response(request, true);
300
301 cleanup:
302 free_rpc_bdev_cluster_unregister(&req);
303 }
304 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
free_rpc_bdev_rbd_get_cluster_info(struct rpc_bdev_rbd_get_cluster_info * req)311 free_rpc_bdev_rbd_get_cluster_info(struct rpc_bdev_rbd_get_cluster_info *req)
312 {
313 free(req->name);
314 }
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
rpc_bdev_rbd_get_clusters_info(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)321 rpc_bdev_rbd_get_clusters_info(struct spdk_jsonrpc_request *request,
322 const struct spdk_json_val *params)
323 {
324 struct rpc_bdev_rbd_get_cluster_info req = {NULL};
325 int rc;
326
327 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 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
331 "spdk_json_decode_object failed");
332 goto cleanup;
333 }
334
335 rc = bdev_rbd_get_clusters_info(request, req.name);
336 if (rc) {
337 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
338 goto cleanup;
339 }
340
341 cleanup:
342 free_rpc_bdev_rbd_get_cluster_info(&req);
343 }
344 SPDK_RPC_REGISTER("bdev_rbd_get_clusters_info", rpc_bdev_rbd_get_clusters_info, SPDK_RPC_RUNTIME)
345