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