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