xref: /spdk/module/bdev/raid/bdev_raid_rpc.c (revision 488570ebd418ba07c9e69e65106dcc964f3bb41b)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/rpc.h"
7 #include "spdk/bdev.h"
8 #include "bdev_raid.h"
9 #include "spdk/util.h"
10 #include "spdk/string.h"
11 #include "spdk/log.h"
12 #include "spdk/env.h"
13 
14 #define RPC_MAX_BASE_BDEVS 255
15 
16 /*
17  * Input structure for bdev_raid_get_bdevs RPC
18  */
19 struct rpc_bdev_raid_get_bdevs {
20 	/* category - all or online or configuring or offline */
21 	char *category;
22 };
23 
24 /*
25  * brief:
26  * free_rpc_bdev_raid_get_bdevs function frees RPC bdev_raid_get_bdevs related parameters
27  * params:
28  * req - pointer to RPC request
29  * returns:
30  * none
31  */
32 static void
33 free_rpc_bdev_raid_get_bdevs(struct rpc_bdev_raid_get_bdevs *req)
34 {
35 	free(req->category);
36 }
37 
38 /*
39  * Decoder object for RPC get_raids
40  */
41 static const struct spdk_json_object_decoder rpc_bdev_raid_get_bdevs_decoders[] = {
42 	{"category", offsetof(struct rpc_bdev_raid_get_bdevs, category), spdk_json_decode_string},
43 };
44 
45 /*
46  * brief:
47  * rpc_bdev_raid_get_bdevs function is the RPC for rpc_bdev_raid_get_bdevs. This is used to list
48  * all the raid bdev names based on the input category requested. Category should be
49  * one of "all", "online", "configuring" or "offline". "all" means all the raids
50  * whether they are online or configuring or offline. "online" is the raid bdev which
51  * is registered with bdev layer. "configuring" is the raid bdev which does not have
52  * full configuration discovered yet. "offline" is the raid bdev which is not
53  * registered with bdev as of now and it has encountered any error or user has
54  * requested to offline the raid.
55  * params:
56  * request - pointer to json rpc request
57  * params - pointer to request parameters
58  * returns:
59  * none
60  */
61 static void
62 rpc_bdev_raid_get_bdevs(struct spdk_jsonrpc_request *request,
63 			const struct spdk_json_val *params)
64 {
65 	struct rpc_bdev_raid_get_bdevs   req = {};
66 	struct spdk_json_write_ctx  *w;
67 	struct raid_bdev            *raid_bdev;
68 
69 	if (spdk_json_decode_object(params, rpc_bdev_raid_get_bdevs_decoders,
70 				    SPDK_COUNTOF(rpc_bdev_raid_get_bdevs_decoders),
71 				    &req)) {
72 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
73 						 "spdk_json_decode_object failed");
74 		goto cleanup;
75 	}
76 
77 	if (!(strcmp(req.category, "all") == 0 ||
78 	      strcmp(req.category, "online") == 0 ||
79 	      strcmp(req.category, "configuring") == 0 ||
80 	      strcmp(req.category, "offline") == 0)) {
81 		spdk_jsonrpc_send_error_response(request, -EINVAL, spdk_strerror(EINVAL));
82 		goto cleanup;
83 	}
84 
85 	w = spdk_jsonrpc_begin_result(request);
86 	spdk_json_write_array_begin(w);
87 
88 	/* Get raid bdev list based on the category requested */
89 	if (strcmp(req.category, "all") == 0) {
90 		TAILQ_FOREACH(raid_bdev, &g_raid_bdev_list, global_link) {
91 			spdk_json_write_string(w, raid_bdev->bdev.name);
92 		}
93 	} else if (strcmp(req.category, "online") == 0) {
94 		TAILQ_FOREACH(raid_bdev, &g_raid_bdev_configured_list, state_link) {
95 			spdk_json_write_string(w, raid_bdev->bdev.name);
96 		}
97 	} else if (strcmp(req.category, "configuring") == 0) {
98 		TAILQ_FOREACH(raid_bdev, &g_raid_bdev_configuring_list, state_link) {
99 			spdk_json_write_string(w, raid_bdev->bdev.name);
100 		}
101 	} else {
102 		TAILQ_FOREACH(raid_bdev, &g_raid_bdev_offline_list, state_link) {
103 			spdk_json_write_string(w, raid_bdev->bdev.name);
104 		}
105 	}
106 	spdk_json_write_array_end(w);
107 	spdk_jsonrpc_end_result(request, w);
108 
109 cleanup:
110 	free_rpc_bdev_raid_get_bdevs(&req);
111 }
112 SPDK_RPC_REGISTER("bdev_raid_get_bdevs", rpc_bdev_raid_get_bdevs, SPDK_RPC_RUNTIME)
113 
114 /*
115  * Base bdevs in RPC bdev_raid_create
116  */
117 struct rpc_bdev_raid_create_base_bdevs {
118 	/* Number of base bdevs */
119 	size_t           num_base_bdevs;
120 
121 	/* List of base bdevs names */
122 	char             *base_bdevs[RPC_MAX_BASE_BDEVS];
123 };
124 
125 /*
126  * Input structure for RPC rpc_bdev_raid_create
127  */
128 struct rpc_bdev_raid_create {
129 	/* Raid bdev name */
130 	char                                 *name;
131 
132 	/* RAID strip size in KB */
133 	uint32_t                             strip_size_kb;
134 
135 	/* RAID raid level */
136 	enum raid_level                      level;
137 
138 	/* Base bdevs information */
139 	struct rpc_bdev_raid_create_base_bdevs base_bdevs;
140 };
141 
142 /*
143  * brief:
144  * free_rpc_bdev_raid_create function is to free RPC bdev_raid_create related parameters
145  * params:
146  * req - pointer to RPC request
147  * returns:
148  * none
149  */
150 static void
151 free_rpc_bdev_raid_create(struct rpc_bdev_raid_create *req)
152 {
153 	size_t i;
154 
155 	free(req->name);
156 	for (i = 0; i < req->base_bdevs.num_base_bdevs; i++) {
157 		free(req->base_bdevs.base_bdevs[i]);
158 	}
159 }
160 
161 /*
162  * Decoder function for RPC bdev_raid_create to decode raid level
163  */
164 static int
165 decode_raid_level(const struct spdk_json_val *val, void *out)
166 {
167 	int ret;
168 	char *str = NULL;
169 	enum raid_level level;
170 
171 	ret = spdk_json_decode_string(val, &str);
172 	if (ret == 0 && str != NULL) {
173 		level = raid_bdev_parse_raid_level(str);
174 		if (level == INVALID_RAID_LEVEL) {
175 			ret = -EINVAL;
176 		} else {
177 			*(enum raid_level *)out = level;
178 		}
179 	}
180 
181 	free(str);
182 	return ret;
183 }
184 
185 /*
186  * Decoder function for RPC bdev_raid_create to decode base bdevs list
187  */
188 static int
189 decode_base_bdevs(const struct spdk_json_val *val, void *out)
190 {
191 	struct rpc_bdev_raid_create_base_bdevs *base_bdevs = out;
192 	return spdk_json_decode_array(val, spdk_json_decode_string, base_bdevs->base_bdevs,
193 				      RPC_MAX_BASE_BDEVS, &base_bdevs->num_base_bdevs, sizeof(char *));
194 }
195 
196 /*
197  * Decoder object for RPC bdev_raid_create
198  */
199 static const struct spdk_json_object_decoder rpc_bdev_raid_create_decoders[] = {
200 	{"name", offsetof(struct rpc_bdev_raid_create, name), spdk_json_decode_string},
201 	{"strip_size_kb", offsetof(struct rpc_bdev_raid_create, strip_size_kb), spdk_json_decode_uint32, true},
202 	{"raid_level", offsetof(struct rpc_bdev_raid_create, level), decode_raid_level},
203 	{"base_bdevs", offsetof(struct rpc_bdev_raid_create, base_bdevs), decode_base_bdevs},
204 };
205 
206 /*
207  * brief:
208  * rpc_bdev_raid_create function is the RPC for creating RAID bdevs. It takes
209  * input as raid bdev name, raid level, strip size in KB and list of base bdev names.
210  * params:
211  * request - pointer to json rpc request
212  * params - pointer to request parameters
213  * returns:
214  * none
215  */
216 static void
217 rpc_bdev_raid_create(struct spdk_jsonrpc_request *request,
218 		     const struct spdk_json_val *params)
219 {
220 	struct rpc_bdev_raid_create	req = {};
221 	struct raid_bdev_config		*raid_cfg;
222 	int				rc;
223 	size_t				i;
224 
225 	if (spdk_json_decode_object(params, rpc_bdev_raid_create_decoders,
226 				    SPDK_COUNTOF(rpc_bdev_raid_create_decoders),
227 				    &req)) {
228 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
229 						 "spdk_json_decode_object failed");
230 		goto cleanup;
231 	}
232 
233 	if (req.strip_size_kb == 0) {
234 		spdk_jsonrpc_send_error_response(request, EINVAL, "strip size not specified");
235 		goto cleanup;
236 	}
237 
238 	rc = raid_bdev_config_add(req.name, req.strip_size_kb, req.base_bdevs.num_base_bdevs,
239 				  req.level,
240 				  &raid_cfg);
241 	if (rc != 0) {
242 		spdk_jsonrpc_send_error_response_fmt(request, rc,
243 						     "Failed to add RAID bdev config %s: %s",
244 						     req.name, spdk_strerror(-rc));
245 		goto cleanup;
246 	}
247 
248 	for (i = 0; i < req.base_bdevs.num_base_bdevs; i++) {
249 		rc = raid_bdev_config_add_base_bdev(raid_cfg, req.base_bdevs.base_bdevs[i], i);
250 		if (rc != 0) {
251 			raid_bdev_config_cleanup(raid_cfg);
252 			spdk_jsonrpc_send_error_response_fmt(request, rc,
253 							     "Failed to add base bdev %s to RAID bdev config %s: %s",
254 							     req.base_bdevs.base_bdevs[i], req.name,
255 							     spdk_strerror(-rc));
256 			goto cleanup;
257 		}
258 	}
259 
260 	rc = raid_bdev_create(raid_cfg);
261 	if (rc != 0) {
262 		raid_bdev_config_cleanup(raid_cfg);
263 		spdk_jsonrpc_send_error_response_fmt(request, rc,
264 						     "Failed to create RAID bdev %s: %s",
265 						     req.name, spdk_strerror(-rc));
266 		goto cleanup;
267 	}
268 
269 	rc = raid_bdev_add_base_devices(raid_cfg);
270 	if (rc != 0) {
271 		spdk_jsonrpc_send_error_response_fmt(request, rc,
272 						     "Failed to add any base bdev to RAID bdev %s: %s",
273 						     req.name, spdk_strerror(-rc));
274 		goto cleanup;
275 	}
276 
277 	spdk_jsonrpc_send_bool_response(request, true);
278 
279 cleanup:
280 	free_rpc_bdev_raid_create(&req);
281 }
282 SPDK_RPC_REGISTER("bdev_raid_create", rpc_bdev_raid_create, SPDK_RPC_RUNTIME)
283 
284 /*
285  * Input structure for RPC deleting a raid bdev
286  */
287 struct rpc_bdev_raid_delete {
288 	/* raid bdev name */
289 	char *name;
290 };
291 
292 /*
293  * brief:
294  * free_rpc_bdev_raid_delete function is used to free RPC bdev_raid_delete related parameters
295  * params:
296  * req - pointer to RPC request
297  * params:
298  * none
299  */
300 static void
301 free_rpc_bdev_raid_delete(struct rpc_bdev_raid_delete *req)
302 {
303 	free(req->name);
304 }
305 
306 /*
307  * Decoder object for RPC raid_bdev_delete
308  */
309 static const struct spdk_json_object_decoder rpc_bdev_raid_delete_decoders[] = {
310 	{"name", offsetof(struct rpc_bdev_raid_delete, name), spdk_json_decode_string},
311 };
312 
313 struct rpc_bdev_raid_delete_ctx {
314 	struct rpc_bdev_raid_delete req;
315 	struct raid_bdev_config *raid_cfg;
316 	struct spdk_jsonrpc_request *request;
317 };
318 
319 /*
320  * brief:
321  * params:
322  * cb_arg - pointer to the callback context.
323  * rc - return code of the deletion of the raid bdev.
324  * returns:
325  * none
326  */
327 static void
328 bdev_raid_delete_done(void *cb_arg, int rc)
329 {
330 	struct rpc_bdev_raid_delete_ctx *ctx = cb_arg;
331 	struct raid_bdev_config *raid_cfg;
332 	struct spdk_jsonrpc_request *request = ctx->request;
333 
334 	if (rc != 0) {
335 		SPDK_ERRLOG("Failed to delete raid bdev %s (%d): %s\n",
336 			    ctx->req.name, rc, spdk_strerror(-rc));
337 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
338 						 spdk_strerror(-rc));
339 		goto exit;
340 	}
341 
342 	raid_cfg = ctx->raid_cfg;
343 	assert(raid_cfg->raid_bdev == NULL);
344 
345 	raid_bdev_config_cleanup(raid_cfg);
346 
347 	spdk_jsonrpc_send_bool_response(request, true);
348 exit:
349 	free_rpc_bdev_raid_delete(&ctx->req);
350 	free(ctx);
351 }
352 
353 /*
354  * brief:
355  * rpc_bdev_raid_delete function is the RPC for deleting a raid bdev. It takes raid
356  * name as input and delete that raid bdev including freeing the base bdev
357  * resources.
358  * params:
359  * request - pointer to json rpc request
360  * params - pointer to request parameters
361  * returns:
362  * none
363  */
364 static void
365 rpc_bdev_raid_delete(struct spdk_jsonrpc_request *request,
366 		     const struct spdk_json_val *params)
367 {
368 	struct rpc_bdev_raid_delete_ctx *ctx;
369 
370 	ctx = calloc(1, sizeof(*ctx));
371 	if (!ctx) {
372 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
373 		return;
374 	}
375 
376 	if (spdk_json_decode_object(params, rpc_bdev_raid_delete_decoders,
377 				    SPDK_COUNTOF(rpc_bdev_raid_delete_decoders),
378 				    &ctx->req)) {
379 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
380 						 "spdk_json_decode_object failed");
381 		goto cleanup;
382 	}
383 
384 	ctx->raid_cfg = raid_bdev_config_find_by_name(ctx->req.name);
385 	if (ctx->raid_cfg == NULL) {
386 		spdk_jsonrpc_send_error_response_fmt(request, ENODEV,
387 						     "raid bdev %s is not found in config",
388 						     ctx->req.name);
389 		goto cleanup;
390 	}
391 
392 	ctx->request = request;
393 
394 	/* Remove all the base bdevs from this raid bdev before deleting the raid bdev */
395 	raid_bdev_remove_base_devices(ctx->raid_cfg, bdev_raid_delete_done, ctx);
396 
397 	return;
398 
399 cleanup:
400 	free_rpc_bdev_raid_delete(&ctx->req);
401 	free(ctx);
402 }
403 SPDK_RPC_REGISTER("bdev_raid_delete", rpc_bdev_raid_delete, SPDK_RPC_RUNTIME)
404