xref: /spdk/module/bdev/rbd/bdev_rbd_rpc.c (revision 45a053c5777494f4e8ce4bc1191c9de3920377f7)
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 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
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
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
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
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
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
181 free_rpc_bdev_rbd_resize(struct rpc_bdev_rbd_resize *req)
182 {
183 	free(req->name);
184 }
185 
186 static void
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
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
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
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
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
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
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