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