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 revert_tper_done(struct spdk_opal_dev *dev, void *data, int rc) 139 { 140 struct nvme_bdev_ctrlr *ctrlr = data; 141 142 if (rc != 0) { 143 SPDK_ERRLOG("%s revert TPer failed\n", ctrlr->name); 144 return; 145 } 146 147 SPDK_NOTICELOG("%s revert TPer done\n", ctrlr->name); 148 } 149 150 static void 151 spdk_rpc_bdev_nvme_opal_revert(struct spdk_jsonrpc_request *request, 152 const struct spdk_json_val *params) 153 { 154 struct rpc_bdev_nvme_opal_revert req = {}; 155 struct spdk_json_write_ctx *w; 156 struct nvme_bdev_ctrlr *nvme_ctrlr; 157 int rc; 158 159 if (spdk_json_decode_object(params, rpc_bdev_nvme_opal_revert_decoders, 160 SPDK_COUNTOF(rpc_bdev_nvme_opal_revert_decoders), 161 &req)) { 162 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 163 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 164 goto out; 165 } 166 167 /* check if opal supported */ 168 nvme_ctrlr = nvme_bdev_ctrlr_get_by_name(req.nvme_ctrlr_name); 169 if (nvme_ctrlr == NULL || nvme_ctrlr->opal_dev == NULL || 170 !spdk_opal_supported(nvme_ctrlr->opal_dev)) { 171 SPDK_ERRLOG("%s not support opal\n", req.nvme_ctrlr_name); 172 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 173 goto out; 174 } 175 176 /* TODO: delete all opal vbdev before revert TPer */ 177 178 rc = spdk_vbdev_opal_revert_tper(nvme_ctrlr, req.password, revert_tper_done, 179 nvme_ctrlr); 180 if (rc) { 181 SPDK_ERRLOG("Revert TPer failure: %d\n", rc); 182 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 183 goto out; 184 } 185 186 w = spdk_jsonrpc_begin_result(request); 187 spdk_json_write_bool(w, true); 188 spdk_jsonrpc_end_result(request, w); 189 190 out: 191 free_rpc_bdev_nvme_opal_revert(&req); 192 } 193 SPDK_RPC_REGISTER("bdev_nvme_opal_revert", spdk_rpc_bdev_nvme_opal_revert, SPDK_RPC_RUNTIME) 194 195 struct rpc_bdev_opal_create { 196 char *nvme_ctrlr_name; 197 uint32_t nsid; 198 uint16_t locking_range_id; 199 uint64_t range_start; 200 uint64_t range_length; 201 char *password; 202 }; 203 204 static void 205 free_rpc_bdev_opal_create(struct rpc_bdev_opal_create *req) 206 { 207 free(req->nvme_ctrlr_name); 208 free(req->password); 209 } 210 211 static const struct spdk_json_object_decoder rpc_bdev_opal_create_decoders[] = { 212 {"nvme_ctrlr_name", offsetof(struct rpc_bdev_opal_create, nvme_ctrlr_name), spdk_json_decode_string}, 213 {"nsid", offsetof(struct rpc_bdev_opal_create, nsid), spdk_json_decode_uint32}, 214 {"locking_range_id", offsetof(struct rpc_bdev_opal_create, locking_range_id), spdk_json_decode_uint16}, 215 {"range_start", offsetof(struct rpc_bdev_opal_create, range_start), spdk_json_decode_uint64}, 216 {"range_length", offsetof(struct rpc_bdev_opal_create, range_length), spdk_json_decode_uint64}, 217 {"password", offsetof(struct rpc_bdev_opal_create, password), spdk_json_decode_string}, 218 }; 219 220 static void 221 spdk_rpc_bdev_opal_create(struct spdk_jsonrpc_request *request, 222 const struct spdk_json_val *params) 223 { 224 struct rpc_bdev_opal_create req = {}; 225 struct spdk_json_write_ctx *w; 226 char *opal_bdev_name; 227 int rc; 228 229 if (spdk_json_decode_object(params, rpc_bdev_opal_create_decoders, 230 SPDK_COUNTOF(rpc_bdev_opal_create_decoders), 231 &req)) { 232 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 233 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 234 goto out; 235 } 236 237 rc = spdk_vbdev_opal_create(req.nvme_ctrlr_name, req.nsid, req.locking_range_id, req.range_start, 238 req.range_length, req.password); 239 if (rc != 0) { 240 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 241 "Failed to create opal vbdev from '%s': %s", 242 req.nvme_ctrlr_name, spdk_strerror(-rc)); 243 goto out; 244 } 245 246 w = spdk_jsonrpc_begin_result(request); 247 opal_bdev_name = spdk_sprintf_alloc("%sn%dr%d", req.nvme_ctrlr_name, req.nsid, 248 req.locking_range_id); 249 spdk_json_write_string(w, opal_bdev_name); 250 spdk_jsonrpc_end_result(request, w); 251 free(opal_bdev_name); 252 253 out: 254 free_rpc_bdev_opal_create(&req); 255 } 256 SPDK_RPC_REGISTER("bdev_opal_create", spdk_rpc_bdev_opal_create, SPDK_RPC_RUNTIME) 257 258 struct rpc_bdev_opal_get_info { 259 char *bdev_name; 260 char *password; 261 }; 262 263 static void 264 free_rpc_bdev_opal_get_info(struct rpc_bdev_opal_get_info *req) 265 { 266 free(req->bdev_name); 267 free(req->password); 268 } 269 270 static const struct spdk_json_object_decoder rpc_bdev_opal_get_info_decoders[] = { 271 {"bdev_name", offsetof(struct rpc_bdev_opal_get_info, bdev_name), spdk_json_decode_string}, 272 {"password", offsetof(struct rpc_bdev_opal_get_info, password), spdk_json_decode_string}, 273 }; 274 275 static void 276 spdk_rpc_bdev_opal_get_info(struct spdk_jsonrpc_request *request, 277 const struct spdk_json_val *params) 278 { 279 struct rpc_bdev_opal_get_info req = {}; 280 struct spdk_json_write_ctx *w; 281 struct spdk_opal_locking_range_info *info; 282 283 if (spdk_json_decode_object(params, rpc_bdev_opal_get_info_decoders, 284 SPDK_COUNTOF(rpc_bdev_opal_get_info_decoders), 285 &req)) { 286 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 287 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 288 goto out; 289 } 290 291 info = spdk_vbdev_opal_get_info_from_bdev(req.bdev_name, req.password); 292 if (info == NULL) { 293 SPDK_ERRLOG("Get opal info failure\n"); 294 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error"); 295 goto out; 296 } 297 298 w = spdk_jsonrpc_begin_result(request); 299 spdk_json_write_object_begin(w); 300 301 spdk_json_write_named_string(w, "name", req.bdev_name); 302 spdk_json_write_named_uint64(w, "range_start", info->range_start); 303 spdk_json_write_named_uint64(w, "range_length", info->range_length); 304 spdk_json_write_named_bool(w, "read_lock_enabled", info->read_lock_enabled); 305 spdk_json_write_named_bool(w, "write_lock_enabled", info->write_lock_enabled); 306 spdk_json_write_named_bool(w, "read_locked", info->read_locked); 307 spdk_json_write_named_bool(w, "write_locked", info->write_locked); 308 309 spdk_json_write_object_end(w); 310 spdk_jsonrpc_end_result(request, w); 311 312 out: 313 free_rpc_bdev_opal_get_info(&req); 314 } 315 SPDK_RPC_REGISTER("bdev_opal_get_info", spdk_rpc_bdev_opal_get_info, SPDK_RPC_RUNTIME) 316 317 struct rpc_bdev_opal_delete { 318 char *bdev_name; 319 char *password; 320 }; 321 322 static void 323 free_rpc_bdev_opal_delete(struct rpc_bdev_opal_delete *req) 324 { 325 free(req->bdev_name); 326 free(req->password); 327 } 328 329 static const struct spdk_json_object_decoder rpc_bdev_opal_delete_decoders[] = { 330 {"bdev_name", offsetof(struct rpc_bdev_opal_delete, bdev_name), spdk_json_decode_string}, 331 {"password", offsetof(struct rpc_bdev_opal_delete, password), spdk_json_decode_string}, 332 }; 333 334 static void 335 spdk_rpc_bdev_opal_delete(struct spdk_jsonrpc_request *request, 336 const struct spdk_json_val *params) 337 { 338 struct rpc_bdev_opal_delete req = {}; 339 struct spdk_json_write_ctx *w; 340 int rc; 341 342 if (spdk_json_decode_object(params, rpc_bdev_opal_delete_decoders, 343 SPDK_COUNTOF(rpc_bdev_opal_delete_decoders), 344 &req)) { 345 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 346 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 347 goto out; 348 } 349 350 rc = spdk_vbdev_opal_destruct(req.bdev_name, req.password); 351 if (rc < 0) { 352 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc)); 353 goto out; 354 } 355 356 w = spdk_jsonrpc_begin_result(request); 357 spdk_json_write_bool(w, true); 358 spdk_jsonrpc_end_result(request, w); 359 out: 360 free_rpc_bdev_opal_delete(&req); 361 } 362 SPDK_RPC_REGISTER("bdev_opal_delete", spdk_rpc_bdev_opal_delete, SPDK_RPC_RUNTIME) 363 364 struct rpc_bdev_opal_set_lock_state { 365 char *bdev_name; 366 uint16_t user_id; 367 char *password; 368 char *lock_state; 369 }; 370 371 static void 372 free_rpc_bdev_opal_set_lock_state(struct rpc_bdev_opal_set_lock_state *req) 373 { 374 free(req->bdev_name); 375 free(req->password); 376 free(req->lock_state); 377 } 378 379 static const struct spdk_json_object_decoder rpc_bdev_opal_set_lock_state_decoders[] = { 380 {"bdev_name", offsetof(struct rpc_bdev_opal_set_lock_state, bdev_name), spdk_json_decode_string}, 381 {"user_id", offsetof(struct rpc_bdev_opal_set_lock_state, user_id), spdk_json_decode_uint16}, 382 {"password", offsetof(struct rpc_bdev_opal_set_lock_state, password), spdk_json_decode_string}, 383 {"lock_state", offsetof(struct rpc_bdev_opal_set_lock_state, lock_state), spdk_json_decode_string}, 384 }; 385 386 static void 387 spdk_rpc_bdev_opal_set_lock_state(struct spdk_jsonrpc_request *request, 388 const struct spdk_json_val *params) 389 { 390 struct rpc_bdev_opal_set_lock_state req = {}; 391 struct spdk_json_write_ctx *w; 392 int rc; 393 394 if (spdk_json_decode_object(params, rpc_bdev_opal_set_lock_state_decoders, 395 SPDK_COUNTOF(rpc_bdev_opal_set_lock_state_decoders), 396 &req)) { 397 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 398 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 399 goto out; 400 } 401 402 rc = spdk_vbdev_opal_set_lock_state(req.bdev_name, req.user_id, req.password, req.lock_state); 403 if (rc != 0) { 404 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc)); 405 goto out; 406 } 407 408 w = spdk_jsonrpc_begin_result(request); 409 spdk_json_write_bool(w, true); 410 spdk_jsonrpc_end_result(request, w); 411 412 out: 413 free_rpc_bdev_opal_set_lock_state(&req); 414 } 415 SPDK_RPC_REGISTER("bdev_opal_set_lock_state", spdk_rpc_bdev_opal_set_lock_state, SPDK_RPC_RUNTIME) 416 417 struct rpc_bdev_opal_new_user { 418 char *bdev_name; 419 char *admin_password; 420 uint16_t user_id; 421 char *user_password; 422 }; 423 424 static void 425 free_rpc_bdev_opal_new_user(struct rpc_bdev_opal_new_user *req) 426 { 427 free(req->bdev_name); 428 free(req->admin_password); 429 free(req->user_password); 430 } 431 432 static const struct spdk_json_object_decoder rpc_bdev_opal_new_user_decoders[] = { 433 {"bdev_name", offsetof(struct rpc_bdev_opal_new_user, bdev_name), spdk_json_decode_string}, 434 {"admin_password", offsetof(struct rpc_bdev_opal_new_user, admin_password), spdk_json_decode_string}, 435 {"user_id", offsetof(struct rpc_bdev_opal_new_user, user_id), spdk_json_decode_uint16}, 436 {"user_password", offsetof(struct rpc_bdev_opal_new_user, user_password), spdk_json_decode_string}, 437 }; 438 439 static void 440 spdk_rpc_bdev_opal_new_user(struct spdk_jsonrpc_request *request, 441 const struct spdk_json_val *params) 442 { 443 struct rpc_bdev_opal_new_user req = {}; 444 struct spdk_json_write_ctx *w; 445 int rc; 446 447 if (spdk_json_decode_object(params, rpc_bdev_opal_new_user_decoders, 448 SPDK_COUNTOF(rpc_bdev_opal_new_user_decoders), 449 &req)) { 450 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 451 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 452 goto out; 453 } 454 455 rc = spdk_vbdev_opal_enable_new_user(req.bdev_name, req.admin_password, req.user_id, 456 req.user_password); 457 if (rc != 0) { 458 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(-rc)); 459 goto out; 460 } 461 462 w = spdk_jsonrpc_begin_result(request); 463 spdk_json_write_bool(w, true); 464 spdk_jsonrpc_end_result(request, w); 465 466 out: 467 free_rpc_bdev_opal_new_user(&req); 468 } 469 SPDK_RPC_REGISTER("bdev_opal_new_user", spdk_rpc_bdev_opal_new_user, SPDK_RPC_RUNTIME) 470