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