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