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