xref: /spdk/module/bdev/ftl/bdev_ftl_rpc.c (revision 0098e636761237b77c12c30c2408263a5d2260cc)
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/util.h"
8 #include "spdk/bdev_module.h"
9 #include "spdk/string.h"
10 #include "spdk/log.h"
11 
12 #include "bdev_ftl.h"
13 
14 struct rpc_bdev_ftl_create {
15 	char *name;
16 	char *base_bdev;
17 	char *uuid;
18 	char *cache_bdev;
19 	struct spdk_ftl_conf ftl_conf;
20 };
21 
22 static void
23 free_rpc_bdev_ftl_create(struct rpc_bdev_ftl_create *req)
24 {
25 	free(req->name);
26 	free(req->base_bdev);
27 	free(req->uuid);
28 	free(req->cache_bdev);
29 	free((char *)req->ftl_conf.l2p_path);
30 }
31 
32 static const struct spdk_json_object_decoder rpc_bdev_ftl_create_decoders[] = {
33 	{"name", offsetof(struct rpc_bdev_ftl_create, name), spdk_json_decode_string},
34 	{"base_bdev", offsetof(struct rpc_bdev_ftl_create, base_bdev), spdk_json_decode_string},
35 	{"uuid", offsetof(struct rpc_bdev_ftl_create, uuid), spdk_json_decode_string, true},
36 	{"cache", offsetof(struct rpc_bdev_ftl_create, cache_bdev), spdk_json_decode_string, true},
37 	{
38 		"allow_open_bands", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
39 		offsetof(struct spdk_ftl_conf, allow_open_bands), spdk_json_decode_bool, true
40 	},
41 	{
42 		"overprovisioning", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
43 		offsetof(struct spdk_ftl_conf, lba_rsvd), spdk_json_decode_uint64, true
44 	},
45 	{
46 		"use_append", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
47 		offsetof(struct spdk_ftl_conf, use_append), spdk_json_decode_bool, true
48 	},
49 	{
50 		"l2p_path", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
51 		offsetof(struct spdk_ftl_conf, l2p_path),
52 		spdk_json_decode_string, true
53 	},
54 	{
55 		"limit_crit", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
56 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_CRIT]) +
57 		offsetof(struct spdk_ftl_limit, limit),
58 		spdk_json_decode_uint64, true
59 	},
60 	{
61 		"limit_crit_threshold", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
62 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_CRIT]) +
63 		offsetof(struct spdk_ftl_limit, thld),
64 		spdk_json_decode_uint64, true
65 	},
66 	{
67 		"limit_high", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
68 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_HIGH]) +
69 		offsetof(struct spdk_ftl_limit, limit),
70 		spdk_json_decode_uint64, true
71 	},
72 	{
73 		"limit_high_threshold", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
74 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_HIGH]) +
75 		offsetof(struct spdk_ftl_limit, thld),
76 		spdk_json_decode_uint64, true
77 	},
78 	{
79 		"limit_low", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
80 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_LOW]) +
81 		offsetof(struct spdk_ftl_limit, limit),
82 		spdk_json_decode_uint64, true
83 	},
84 	{
85 		"limit_low_threshold", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
86 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_LOW]) +
87 		offsetof(struct spdk_ftl_limit, thld),
88 		spdk_json_decode_uint64, true
89 	},
90 	{
91 		"limit_start", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
92 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_START]) +
93 		offsetof(struct spdk_ftl_limit, limit),
94 		spdk_json_decode_uint64, true
95 	},
96 	{
97 		"limit_start_threshold", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
98 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_START]) +
99 		offsetof(struct spdk_ftl_limit, thld),
100 		spdk_json_decode_uint64, true
101 	},
102 };
103 
104 static void
105 rpc_bdev_ftl_create_cb(const struct ftl_bdev_info *bdev_info, void *ctx, int status)
106 {
107 	struct spdk_jsonrpc_request *request = ctx;
108 	char bdev_uuid[SPDK_UUID_STRING_LEN];
109 	struct spdk_json_write_ctx *w;
110 
111 	if (status) {
112 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
113 						     "Failed to create FTL bdev: %s",
114 						     spdk_strerror(-status));
115 		return;
116 	}
117 
118 	w = spdk_jsonrpc_begin_result(request);
119 	spdk_uuid_fmt_lower(bdev_uuid, sizeof(bdev_uuid), &bdev_info->uuid);
120 	spdk_json_write_object_begin(w);
121 	spdk_json_write_named_string(w, "name", bdev_info->name);
122 	spdk_json_write_named_string(w, "uuid", bdev_uuid);
123 	spdk_json_write_object_end(w);
124 	spdk_jsonrpc_end_result(request, w);
125 }
126 
127 static void
128 rpc_bdev_ftl_create(struct spdk_jsonrpc_request *request,
129 		    const struct spdk_json_val *params)
130 {
131 	struct rpc_bdev_ftl_create req = {};
132 	struct ftl_bdev_init_opts opts = {};
133 	struct spdk_json_write_ctx *w;
134 	int rc;
135 
136 	spdk_ftl_conf_init_defaults(&req.ftl_conf);
137 
138 	if (spdk_json_decode_object(params, rpc_bdev_ftl_create_decoders,
139 				    SPDK_COUNTOF(rpc_bdev_ftl_create_decoders),
140 				    &req)) {
141 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
142 						 "Invalid parameters");
143 		goto invalid;
144 	}
145 
146 	if (req.cache_bdev && !spdk_bdev_get_by_name(req.cache_bdev)) {
147 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
148 						     "No such bdev: %s", req.cache_bdev);
149 		goto invalid;
150 	}
151 
152 	opts.name = req.name;
153 	opts.mode = SPDK_FTL_MODE_CREATE;
154 	opts.base_bdev = req.base_bdev;
155 	opts.cache_bdev = req.cache_bdev;
156 	opts.ftl_conf = req.ftl_conf;
157 
158 	if (req.uuid) {
159 		if (spdk_uuid_parse(&opts.uuid, req.uuid) < 0) {
160 			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
161 							     "Failed to parse uuid: %s",
162 							     req.uuid);
163 			goto invalid;
164 		}
165 
166 		if (!spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) {
167 			opts.mode &= ~SPDK_FTL_MODE_CREATE;
168 		}
169 	}
170 
171 	rc = bdev_ftl_create_bdev(&opts, rpc_bdev_ftl_create_cb, request);
172 	if (rc) {
173 		if (rc == -ENODEV) {
174 			w = spdk_jsonrpc_begin_result(request);
175 			spdk_json_write_string_fmt(w, "FTL bdev: %s creation deferred", req.name);
176 			spdk_jsonrpc_end_result(request, w);
177 		} else {
178 			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
179 							     "Failed to create FTL bdev: %s",
180 							     spdk_strerror(-rc));
181 		}
182 		goto invalid;
183 	}
184 
185 invalid:
186 	free_rpc_bdev_ftl_create(&req);
187 }
188 
189 SPDK_RPC_REGISTER("bdev_ftl_create", rpc_bdev_ftl_create, SPDK_RPC_RUNTIME)
190 
191 struct rpc_delete_ftl {
192 	char *name;
193 };
194 
195 static const struct spdk_json_object_decoder rpc_delete_ftl_decoders[] = {
196 	{"name", offsetof(struct rpc_bdev_ftl_create, name), spdk_json_decode_string},
197 };
198 
199 static void
200 rpc_bdev_ftl_delete_cb(void *cb_arg, int bdeverrno)
201 {
202 	struct spdk_jsonrpc_request *request = cb_arg;
203 
204 	if (bdeverrno == 0) {
205 		spdk_jsonrpc_send_bool_response(request, true);
206 	} else {
207 		spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
208 	}
209 }
210 
211 static void
212 rpc_bdev_ftl_delete(struct spdk_jsonrpc_request *request,
213 		    const struct spdk_json_val *params)
214 {
215 	struct rpc_delete_ftl attrs = {};
216 
217 	if (spdk_json_decode_object(params, rpc_delete_ftl_decoders,
218 				    SPDK_COUNTOF(rpc_delete_ftl_decoders),
219 				    &attrs)) {
220 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
221 						 "Invalid parameters");
222 		goto invalid;
223 	}
224 
225 	bdev_ftl_delete_bdev(attrs.name, rpc_bdev_ftl_delete_cb, request);
226 invalid:
227 	free(attrs.name);
228 }
229 
230 SPDK_RPC_REGISTER("bdev_ftl_delete", rpc_bdev_ftl_delete, SPDK_RPC_RUNTIME)
231