xref: /spdk/module/bdev/nvme/vbdev_opal_rpc.c (revision 03e3fc4f5835983a4e6602b4e770922e798ce263)
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/string.h"
37 #include "spdk_internal/log.h"
38 
39 #include "vbdev_opal.h"
40 
41 struct rpc_bdev_nvme_opal_init {
42 	char *nvme_ctrlr_name;
43 	char *password;
44 };
45 
46 static void
47 free_rpc_bdev_nvme_opal_init(struct rpc_bdev_nvme_opal_init *req)
48 {
49 	free(req->nvme_ctrlr_name);
50 	free(req->password);
51 }
52 
53 static const struct spdk_json_object_decoder rpc_bdev_nvme_opal_init_decoders[] = {
54 	{"nvme_ctrlr_name", offsetof(struct rpc_bdev_nvme_opal_init, nvme_ctrlr_name), spdk_json_decode_string},
55 	{"password", offsetof(struct rpc_bdev_nvme_opal_init, password), spdk_json_decode_string},
56 };
57 
58 static void
59 rpc_bdev_nvme_opal_init(struct spdk_jsonrpc_request *request,
60 			const struct spdk_json_val *params)
61 {
62 	struct rpc_bdev_nvme_opal_init req = {};
63 	struct spdk_json_write_ctx *w;
64 	struct nvme_bdev_ctrlr *nvme_ctrlr;
65 	int rc;
66 
67 	if (spdk_json_decode_object(params, rpc_bdev_nvme_opal_init_decoders,
68 				    SPDK_COUNTOF(rpc_bdev_nvme_opal_init_decoders),
69 				    &req)) {
70 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
71 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
72 		goto out;
73 	}
74 
75 	/* check if opal supported */
76 	nvme_ctrlr = nvme_bdev_ctrlr_get_by_name(req.nvme_ctrlr_name);
77 	if (nvme_ctrlr == NULL || nvme_ctrlr->opal_dev == NULL) {
78 		SPDK_ERRLOG("%s not support opal\n", req.nvme_ctrlr_name);
79 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
80 		goto out;
81 	}
82 
83 	/* take ownership */
84 	rc = spdk_opal_cmd_take_ownership(nvme_ctrlr->opal_dev, req.password);
85 	if (rc) {
86 		SPDK_ERRLOG("Take ownership failure: %d\n", rc);
87 		switch (rc) {
88 		case -EBUSY:
89 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
90 							 "SP Busy, try again later");
91 			break;
92 		case -EACCES:
93 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
94 							 "This drive is already enabled");
95 			break;
96 		default:
97 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
98 		}
99 		goto out;
100 	}
101 
102 	/* activate locking SP */
103 	rc = spdk_opal_cmd_activate_locking_sp(nvme_ctrlr->opal_dev, req.password);
104 	if (rc) {
105 		SPDK_ERRLOG("Activate locking SP failure: %d\n", rc);
106 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
107 		goto out;
108 	}
109 
110 	w = spdk_jsonrpc_begin_result(request);
111 	spdk_json_write_bool(w, true);
112 	spdk_jsonrpc_end_result(request, w);
113 
114 out:
115 	free_rpc_bdev_nvme_opal_init(&req);
116 }
117 SPDK_RPC_REGISTER("bdev_nvme_opal_init", rpc_bdev_nvme_opal_init, SPDK_RPC_RUNTIME)
118 
119 struct rpc_bdev_nvme_opal_revert {
120 	char *nvme_ctrlr_name;
121 	char *password;
122 };
123 
124 static void
125 free_rpc_bdev_nvme_opal_revert(struct rpc_bdev_nvme_opal_revert *req)
126 {
127 	free(req->nvme_ctrlr_name);
128 	free(req->password);
129 }
130 
131 static const struct spdk_json_object_decoder rpc_bdev_nvme_opal_revert_decoders[] = {
132 	{"nvme_ctrlr_name", offsetof(struct rpc_bdev_nvme_opal_revert, nvme_ctrlr_name), spdk_json_decode_string},
133 	{"password", offsetof(struct rpc_bdev_nvme_opal_revert, password), spdk_json_decode_string},
134 };
135 
136 static void
137 rpc_bdev_nvme_opal_revert(struct spdk_jsonrpc_request *request,
138 			  const struct spdk_json_val *params)
139 {
140 	struct rpc_bdev_nvme_opal_revert req = {};
141 	struct spdk_json_write_ctx *w;
142 	struct nvme_bdev_ctrlr *nvme_ctrlr;
143 	int rc;
144 
145 	if (spdk_json_decode_object(params, rpc_bdev_nvme_opal_revert_decoders,
146 				    SPDK_COUNTOF(rpc_bdev_nvme_opal_revert_decoders),
147 				    &req)) {
148 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
149 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
150 		goto out;
151 	}
152 
153 	/* check if opal supported */
154 	nvme_ctrlr = nvme_bdev_ctrlr_get_by_name(req.nvme_ctrlr_name);
155 	if (nvme_ctrlr == NULL || nvme_ctrlr->opal_dev == NULL) {
156 		SPDK_ERRLOG("%s not support opal\n", req.nvme_ctrlr_name);
157 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
158 		goto out;
159 	}
160 
161 	/* TODO: delete all opal vbdev before revert TPer */
162 
163 	rc = spdk_opal_cmd_revert_tper(nvme_ctrlr->opal_dev, req.password);
164 	if (rc) {
165 		SPDK_ERRLOG("Revert TPer failure: %d\n", rc);
166 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
167 		goto out;
168 	}
169 
170 	w = spdk_jsonrpc_begin_result(request);
171 	spdk_json_write_bool(w, true);
172 	spdk_jsonrpc_end_result(request, w);
173 
174 out:
175 	free_rpc_bdev_nvme_opal_revert(&req);
176 }
177 SPDK_RPC_REGISTER("bdev_nvme_opal_revert", rpc_bdev_nvme_opal_revert, SPDK_RPC_RUNTIME)
178 
179 struct rpc_bdev_opal_create {
180 	char *nvme_ctrlr_name;
181 	uint32_t nsid;
182 	uint16_t locking_range_id;
183 	uint64_t range_start;
184 	uint64_t range_length;
185 	char *password;
186 };
187 
188 static void
189 free_rpc_bdev_opal_create(struct rpc_bdev_opal_create *req)
190 {
191 	free(req->nvme_ctrlr_name);
192 	free(req->password);
193 }
194 
195 static const struct spdk_json_object_decoder rpc_bdev_opal_create_decoders[] = {
196 	{"nvme_ctrlr_name", offsetof(struct rpc_bdev_opal_create, nvme_ctrlr_name), spdk_json_decode_string},
197 	{"nsid", offsetof(struct rpc_bdev_opal_create, nsid), spdk_json_decode_uint32},
198 	{"locking_range_id", offsetof(struct rpc_bdev_opal_create, locking_range_id), spdk_json_decode_uint16},
199 	{"range_start", offsetof(struct rpc_bdev_opal_create, range_start), spdk_json_decode_uint64},
200 	{"range_length", offsetof(struct rpc_bdev_opal_create, range_length), spdk_json_decode_uint64},
201 	{"password", offsetof(struct rpc_bdev_opal_create, password), spdk_json_decode_string},
202 };
203 
204 static void
205 rpc_bdev_opal_create(struct spdk_jsonrpc_request *request,
206 		     const struct spdk_json_val *params)
207 {
208 	struct rpc_bdev_opal_create req = {};
209 	struct spdk_json_write_ctx *w;
210 	char *opal_bdev_name;
211 	int rc;
212 
213 	if (spdk_json_decode_object(params, rpc_bdev_opal_create_decoders,
214 				    SPDK_COUNTOF(rpc_bdev_opal_create_decoders),
215 				    &req)) {
216 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
217 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
218 		goto out;
219 	}
220 
221 	rc = vbdev_opal_create(req.nvme_ctrlr_name, req.nsid, req.locking_range_id, req.range_start,
222 			       req.range_length, req.password);
223 	if (rc != 0) {
224 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
225 						     "Failed to create opal vbdev from '%s': %s",
226 						     req.nvme_ctrlr_name, spdk_strerror(-rc));
227 		goto out;
228 	}
229 
230 	w = spdk_jsonrpc_begin_result(request);
231 	opal_bdev_name = spdk_sprintf_alloc("%sn%dr%d", req.nvme_ctrlr_name, req.nsid,
232 					    req.locking_range_id);
233 	spdk_json_write_string(w, opal_bdev_name);
234 	spdk_jsonrpc_end_result(request, w);
235 	free(opal_bdev_name);
236 
237 out:
238 	free_rpc_bdev_opal_create(&req);
239 }
240 SPDK_RPC_REGISTER("bdev_opal_create", rpc_bdev_opal_create, SPDK_RPC_RUNTIME)
241 
242 struct rpc_bdev_opal_get_info {
243 	char *bdev_name;
244 	char *password;
245 };
246 
247 static void
248 free_rpc_bdev_opal_get_info(struct rpc_bdev_opal_get_info *req)
249 {
250 	free(req->bdev_name);
251 	free(req->password);
252 }
253 
254 static const struct spdk_json_object_decoder rpc_bdev_opal_get_info_decoders[] = {
255 	{"bdev_name", offsetof(struct rpc_bdev_opal_get_info, bdev_name), spdk_json_decode_string},
256 	{"password", offsetof(struct rpc_bdev_opal_get_info, password), spdk_json_decode_string},
257 };
258 
259 static void
260 rpc_bdev_opal_get_info(struct spdk_jsonrpc_request *request,
261 		       const struct spdk_json_val *params)
262 {
263 	struct rpc_bdev_opal_get_info req = {};
264 	struct spdk_json_write_ctx *w;
265 	struct spdk_opal_locking_range_info *info;
266 
267 	if (spdk_json_decode_object(params, rpc_bdev_opal_get_info_decoders,
268 				    SPDK_COUNTOF(rpc_bdev_opal_get_info_decoders),
269 				    &req)) {
270 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
271 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
272 		goto out;
273 	}
274 
275 	info = vbdev_opal_get_info_from_bdev(req.bdev_name, req.password);
276 	if (info == NULL) {
277 		SPDK_ERRLOG("Get opal info failure\n");
278 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
279 		goto out;
280 	}
281 
282 	w = spdk_jsonrpc_begin_result(request);
283 	spdk_json_write_object_begin(w);
284 
285 	spdk_json_write_named_string(w, "name", req.bdev_name);
286 	spdk_json_write_named_uint64(w, "range_start", info->range_start);
287 	spdk_json_write_named_uint64(w, "range_length", info->range_length);
288 	spdk_json_write_named_bool(w, "read_lock_enabled", info->read_lock_enabled);
289 	spdk_json_write_named_bool(w, "write_lock_enabled", info->write_lock_enabled);
290 	spdk_json_write_named_bool(w, "read_locked", info->read_locked);
291 	spdk_json_write_named_bool(w, "write_locked", info->write_locked);
292 
293 	spdk_json_write_object_end(w);
294 	spdk_jsonrpc_end_result(request, w);
295 
296 out:
297 	free_rpc_bdev_opal_get_info(&req);
298 }
299 SPDK_RPC_REGISTER("bdev_opal_get_info", rpc_bdev_opal_get_info, SPDK_RPC_RUNTIME)
300 
301 struct rpc_bdev_opal_delete {
302 	char *bdev_name;
303 	char *password;
304 };
305 
306 static void
307 free_rpc_bdev_opal_delete(struct rpc_bdev_opal_delete *req)
308 {
309 	free(req->bdev_name);
310 	free(req->password);
311 }
312 
313 static const struct spdk_json_object_decoder rpc_bdev_opal_delete_decoders[] = {
314 	{"bdev_name", offsetof(struct rpc_bdev_opal_delete, bdev_name), spdk_json_decode_string},
315 	{"password", offsetof(struct rpc_bdev_opal_delete, password), spdk_json_decode_string},
316 };
317 
318 static void
319 rpc_bdev_opal_delete(struct spdk_jsonrpc_request *request,
320 		     const struct spdk_json_val *params)
321 {
322 	struct rpc_bdev_opal_delete req = {};
323 	struct spdk_json_write_ctx *w;
324 	int rc;
325 
326 	if (spdk_json_decode_object(params, rpc_bdev_opal_delete_decoders,
327 				    SPDK_COUNTOF(rpc_bdev_opal_delete_decoders),
328 				    &req)) {
329 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
330 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
331 		goto out;
332 	}
333 
334 	rc = vbdev_opal_destruct(req.bdev_name, req.password);
335 	if (rc < 0) {
336 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc));
337 		goto out;
338 	}
339 
340 	w = spdk_jsonrpc_begin_result(request);
341 	spdk_json_write_bool(w, true);
342 	spdk_jsonrpc_end_result(request, w);
343 out:
344 	free_rpc_bdev_opal_delete(&req);
345 }
346 SPDK_RPC_REGISTER("bdev_opal_delete", rpc_bdev_opal_delete, SPDK_RPC_RUNTIME)
347 
348 struct rpc_bdev_opal_set_lock_state {
349 	char *bdev_name;
350 	uint16_t user_id;
351 	char *password;
352 	char *lock_state;
353 };
354 
355 static void
356 free_rpc_bdev_opal_set_lock_state(struct rpc_bdev_opal_set_lock_state *req)
357 {
358 	free(req->bdev_name);
359 	free(req->password);
360 	free(req->lock_state);
361 }
362 
363 static const struct spdk_json_object_decoder rpc_bdev_opal_set_lock_state_decoders[] = {
364 	{"bdev_name", offsetof(struct rpc_bdev_opal_set_lock_state, bdev_name), spdk_json_decode_string},
365 	{"user_id", offsetof(struct rpc_bdev_opal_set_lock_state, user_id), spdk_json_decode_uint16},
366 	{"password", offsetof(struct rpc_bdev_opal_set_lock_state, password), spdk_json_decode_string},
367 	{"lock_state", offsetof(struct rpc_bdev_opal_set_lock_state, lock_state), spdk_json_decode_string},
368 };
369 
370 static void
371 rpc_bdev_opal_set_lock_state(struct spdk_jsonrpc_request *request,
372 			     const struct spdk_json_val *params)
373 {
374 	struct rpc_bdev_opal_set_lock_state req = {};
375 	struct spdk_json_write_ctx *w;
376 	int rc;
377 
378 	if (spdk_json_decode_object(params, rpc_bdev_opal_set_lock_state_decoders,
379 				    SPDK_COUNTOF(rpc_bdev_opal_set_lock_state_decoders),
380 				    &req)) {
381 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
382 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
383 		goto out;
384 	}
385 
386 	rc = vbdev_opal_set_lock_state(req.bdev_name, req.user_id, req.password, req.lock_state);
387 	if (rc != 0) {
388 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc));
389 		goto out;
390 	}
391 
392 	w = spdk_jsonrpc_begin_result(request);
393 	spdk_json_write_bool(w, true);
394 	spdk_jsonrpc_end_result(request, w);
395 
396 out:
397 	free_rpc_bdev_opal_set_lock_state(&req);
398 }
399 SPDK_RPC_REGISTER("bdev_opal_set_lock_state", rpc_bdev_opal_set_lock_state, SPDK_RPC_RUNTIME)
400 
401 struct rpc_bdev_opal_new_user {
402 	char *bdev_name;
403 	char *admin_password;
404 	uint16_t user_id;
405 	char *user_password;
406 };
407 
408 static void
409 free_rpc_bdev_opal_new_user(struct rpc_bdev_opal_new_user *req)
410 {
411 	free(req->bdev_name);
412 	free(req->admin_password);
413 	free(req->user_password);
414 }
415 
416 static const struct spdk_json_object_decoder rpc_bdev_opal_new_user_decoders[] = {
417 	{"bdev_name", offsetof(struct rpc_bdev_opal_new_user, bdev_name), spdk_json_decode_string},
418 	{"admin_password", offsetof(struct rpc_bdev_opal_new_user, admin_password), spdk_json_decode_string},
419 	{"user_id", offsetof(struct rpc_bdev_opal_new_user, user_id), spdk_json_decode_uint16},
420 	{"user_password", offsetof(struct rpc_bdev_opal_new_user, user_password), spdk_json_decode_string},
421 };
422 
423 static void
424 rpc_bdev_opal_new_user(struct spdk_jsonrpc_request *request,
425 		       const struct spdk_json_val *params)
426 {
427 	struct rpc_bdev_opal_new_user req = {};
428 	struct spdk_json_write_ctx *w;
429 	int rc;
430 
431 	if (spdk_json_decode_object(params, rpc_bdev_opal_new_user_decoders,
432 				    SPDK_COUNTOF(rpc_bdev_opal_new_user_decoders),
433 				    &req)) {
434 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
435 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
436 		goto out;
437 	}
438 
439 	rc = vbdev_opal_enable_new_user(req.bdev_name, req.admin_password, req.user_id,
440 					req.user_password);
441 	if (rc != 0) {
442 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc));
443 		goto out;
444 	}
445 
446 	w = spdk_jsonrpc_begin_result(request);
447 	spdk_json_write_bool(w, true);
448 	spdk_jsonrpc_end_result(request, w);
449 
450 out:
451 	free_rpc_bdev_opal_new_user(&req);
452 }
453 SPDK_RPC_REGISTER("bdev_opal_new_user", rpc_bdev_opal_new_user, SPDK_RPC_RUNTIME)
454