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