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