xref: /spdk/module/bdev/ftl/bdev_ftl_rpc.c (revision 7506a7aa53d239f533af3bc768f0d2af55e735fe)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/rpc.h"
35 #include "spdk/util.h"
36 #include "spdk/bdev_module.h"
37 #include "spdk/string.h"
38 #include "spdk/log.h"
39 
40 #include "bdev_ftl.h"
41 
42 struct rpc_bdev_ftl_create {
43 	char *name;
44 	char *base_bdev;
45 	char *uuid;
46 	char *cache_bdev;
47 	struct spdk_ftl_conf ftl_conf;
48 };
49 
50 static void
51 free_rpc_bdev_ftl_create(struct rpc_bdev_ftl_create *req)
52 {
53 	free(req->name);
54 	free(req->base_bdev);
55 	free(req->uuid);
56 	free(req->cache_bdev);
57 	free((char *)req->ftl_conf.l2p_path);
58 }
59 
60 static const struct spdk_json_object_decoder rpc_bdev_ftl_create_decoders[] = {
61 	{"name", offsetof(struct rpc_bdev_ftl_create, name), spdk_json_decode_string},
62 	{"base_bdev", offsetof(struct rpc_bdev_ftl_create, base_bdev), spdk_json_decode_string},
63 	{"uuid", offsetof(struct rpc_bdev_ftl_create, uuid), spdk_json_decode_string, true},
64 	{"cache", offsetof(struct rpc_bdev_ftl_create, cache_bdev), spdk_json_decode_string, true},
65 	{
66 		"allow_open_bands", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
67 		offsetof(struct spdk_ftl_conf, allow_open_bands), spdk_json_decode_bool, true
68 	},
69 	{
70 		"overprovisioning", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
71 		offsetof(struct spdk_ftl_conf, lba_rsvd), spdk_json_decode_uint64, true
72 	},
73 	{
74 		"use_append", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
75 		offsetof(struct spdk_ftl_conf, use_append), spdk_json_decode_bool, true
76 	},
77 	{
78 		"l2p_path", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
79 		offsetof(struct spdk_ftl_conf, l2p_path),
80 		spdk_json_decode_string, true
81 	},
82 	{
83 		"limit_crit", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
84 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_CRIT]) +
85 		offsetof(struct spdk_ftl_limit, limit),
86 		spdk_json_decode_uint64, true
87 	},
88 	{
89 		"limit_crit_threshold", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
90 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_CRIT]) +
91 		offsetof(struct spdk_ftl_limit, thld),
92 		spdk_json_decode_uint64, true
93 	},
94 	{
95 		"limit_high", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
96 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_HIGH]) +
97 		offsetof(struct spdk_ftl_limit, limit),
98 		spdk_json_decode_uint64, true
99 	},
100 	{
101 		"limit_high_threshold", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
102 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_HIGH]) +
103 		offsetof(struct spdk_ftl_limit, thld),
104 		spdk_json_decode_uint64, true
105 	},
106 	{
107 		"limit_low", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
108 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_LOW]) +
109 		offsetof(struct spdk_ftl_limit, limit),
110 		spdk_json_decode_uint64, true
111 	},
112 	{
113 		"limit_low_threshold", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
114 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_LOW]) +
115 		offsetof(struct spdk_ftl_limit, thld),
116 		spdk_json_decode_uint64, true
117 	},
118 	{
119 		"limit_start", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
120 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_START]) +
121 		offsetof(struct spdk_ftl_limit, limit),
122 		spdk_json_decode_uint64, true
123 	},
124 	{
125 		"limit_start_threshold", offsetof(struct rpc_bdev_ftl_create, ftl_conf) +
126 		offsetof(struct spdk_ftl_conf, limits[SPDK_FTL_LIMIT_START]) +
127 		offsetof(struct spdk_ftl_limit, thld),
128 		spdk_json_decode_uint64, true
129 	},
130 };
131 
132 static void
133 rpc_bdev_ftl_create_cb(const struct ftl_bdev_info *bdev_info, void *ctx, int status)
134 {
135 	struct spdk_jsonrpc_request *request = ctx;
136 	char bdev_uuid[SPDK_UUID_STRING_LEN];
137 	struct spdk_json_write_ctx *w;
138 
139 	if (status) {
140 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
141 						     "Failed to create FTL bdev: %s",
142 						     spdk_strerror(-status));
143 		return;
144 	}
145 
146 	w = spdk_jsonrpc_begin_result(request);
147 	spdk_uuid_fmt_lower(bdev_uuid, sizeof(bdev_uuid), &bdev_info->uuid);
148 	spdk_json_write_object_begin(w);
149 	spdk_json_write_named_string(w, "name", bdev_info->name);
150 	spdk_json_write_named_string(w, "uuid", bdev_uuid);
151 	spdk_json_write_object_end(w);
152 	spdk_jsonrpc_end_result(request, w);
153 }
154 
155 static void
156 rpc_bdev_ftl_create(struct spdk_jsonrpc_request *request,
157 		    const struct spdk_json_val *params)
158 {
159 	struct rpc_bdev_ftl_create req = {};
160 	struct ftl_bdev_init_opts opts = {};
161 	struct spdk_json_write_ctx *w;
162 	int rc;
163 
164 	spdk_ftl_conf_init_defaults(&req.ftl_conf);
165 
166 	if (spdk_json_decode_object(params, rpc_bdev_ftl_create_decoders,
167 				    SPDK_COUNTOF(rpc_bdev_ftl_create_decoders),
168 				    &req)) {
169 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
170 						 "Invalid parameters");
171 		goto invalid;
172 	}
173 
174 	if (req.cache_bdev && !spdk_bdev_get_by_name(req.cache_bdev)) {
175 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
176 						     "No such bdev: %s", req.cache_bdev);
177 		goto invalid;
178 	}
179 
180 	opts.name = req.name;
181 	opts.mode = SPDK_FTL_MODE_CREATE;
182 	opts.base_bdev = req.base_bdev;
183 	opts.cache_bdev = req.cache_bdev;
184 	opts.ftl_conf = req.ftl_conf;
185 
186 	if (req.uuid) {
187 		if (spdk_uuid_parse(&opts.uuid, req.uuid) < 0) {
188 			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
189 							     "Failed to parse uuid: %s",
190 							     req.uuid);
191 			goto invalid;
192 		}
193 
194 		if (!spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) {
195 			opts.mode &= ~SPDK_FTL_MODE_CREATE;
196 		}
197 	}
198 
199 	rc = bdev_ftl_create_bdev(&opts, rpc_bdev_ftl_create_cb, request);
200 	if (rc) {
201 		if (rc == -ENODEV) {
202 			w = spdk_jsonrpc_begin_result(request);
203 			spdk_json_write_string_fmt(w, "FTL bdev: %s creation deferred", req.name);
204 			spdk_jsonrpc_end_result(request, w);
205 		} else {
206 			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
207 							     "Failed to create FTL bdev: %s",
208 							     spdk_strerror(-rc));
209 		}
210 		goto invalid;
211 	}
212 
213 invalid:
214 	free_rpc_bdev_ftl_create(&req);
215 }
216 
217 SPDK_RPC_REGISTER("bdev_ftl_create", rpc_bdev_ftl_create, SPDK_RPC_RUNTIME)
218 
219 struct rpc_delete_ftl {
220 	char *name;
221 };
222 
223 static const struct spdk_json_object_decoder rpc_delete_ftl_decoders[] = {
224 	{"name", offsetof(struct rpc_bdev_ftl_create, name), spdk_json_decode_string},
225 };
226 
227 static void
228 rpc_bdev_ftl_delete_cb(void *cb_arg, int bdeverrno)
229 {
230 	struct spdk_jsonrpc_request *request = cb_arg;
231 
232 	if (bdeverrno == 0) {
233 		spdk_jsonrpc_send_bool_response(request, true);
234 	} else {
235 		spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
236 	}
237 }
238 
239 static void
240 rpc_bdev_ftl_delete(struct spdk_jsonrpc_request *request,
241 		    const struct spdk_json_val *params)
242 {
243 	struct rpc_delete_ftl attrs = {};
244 
245 	if (spdk_json_decode_object(params, rpc_delete_ftl_decoders,
246 				    SPDK_COUNTOF(rpc_delete_ftl_decoders),
247 				    &attrs)) {
248 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
249 						 "Invalid parameters");
250 		goto invalid;
251 	}
252 
253 	bdev_ftl_delete_bdev(attrs.name, rpc_bdev_ftl_delete_cb, request);
254 invalid:
255 	free(attrs.name);
256 }
257 
258 SPDK_RPC_REGISTER("bdev_ftl_delete", rpc_bdev_ftl_delete, SPDK_RPC_RUNTIME)
259