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 "bdev_rbd.h" 35 #include "spdk/util.h" 36 #include "spdk/uuid.h" 37 #include "spdk/string.h" 38 #include "spdk/log.h" 39 40 struct rpc_create_rbd { 41 char *name; 42 char *user_id; 43 char *pool_name; 44 char *rbd_name; 45 uint32_t block_size; 46 char **config; 47 char *cluster_name; 48 char *uuid; 49 }; 50 51 static void 52 free_rpc_create_rbd(struct rpc_create_rbd *req) 53 { 54 free(req->name); 55 free(req->user_id); 56 free(req->pool_name); 57 free(req->rbd_name); 58 bdev_rbd_free_config(req->config); 59 free(req->cluster_name); 60 free(req->uuid); 61 } 62 63 static int 64 bdev_rbd_decode_config(const struct spdk_json_val *values, void *out) 65 { 66 char ***map = out; 67 char **entry; 68 uint32_t i; 69 70 if (values->type == SPDK_JSON_VAL_NULL) { 71 /* treated like empty object: empty config */ 72 *map = calloc(1, sizeof(**map)); 73 if (!*map) { 74 return -1; 75 } 76 return 0; 77 } 78 79 if (values->type != SPDK_JSON_VAL_OBJECT_BEGIN) { 80 return -1; 81 } 82 83 *map = calloc(values->len + 1, sizeof(**map)); 84 if (!*map) { 85 return -1; 86 } 87 88 for (i = 0, entry = *map; i < values->len;) { 89 const struct spdk_json_val *name = &values[i + 1]; 90 const struct spdk_json_val *v = &values[i + 2]; 91 /* Here we catch errors like invalid types. */ 92 if (!(entry[0] = spdk_json_strdup(name)) || 93 !(entry[1] = spdk_json_strdup(v))) { 94 bdev_rbd_free_config(*map); 95 *map = NULL; 96 return -1; 97 } 98 i += 1 + spdk_json_val_len(v); 99 entry += 2; 100 } 101 102 return 0; 103 } 104 105 static const struct spdk_json_object_decoder rpc_create_rbd_decoders[] = { 106 {"name", offsetof(struct rpc_create_rbd, name), spdk_json_decode_string, true}, 107 {"user_id", offsetof(struct rpc_create_rbd, user_id), spdk_json_decode_string, true}, 108 {"pool_name", offsetof(struct rpc_create_rbd, pool_name), spdk_json_decode_string}, 109 {"rbd_name", offsetof(struct rpc_create_rbd, rbd_name), spdk_json_decode_string}, 110 {"block_size", offsetof(struct rpc_create_rbd, block_size), spdk_json_decode_uint32}, 111 {"config", offsetof(struct rpc_create_rbd, config), bdev_rbd_decode_config, true}, 112 {"cluster_name", offsetof(struct rpc_create_rbd, cluster_name), spdk_json_decode_string, true}, 113 {"uuid", offsetof(struct rpc_create_rbd, uuid), spdk_json_decode_string, true} 114 }; 115 116 static void 117 rpc_bdev_rbd_create(struct spdk_jsonrpc_request *request, 118 const struct spdk_json_val *params) 119 { 120 struct rpc_create_rbd req = {}; 121 struct spdk_json_write_ctx *w; 122 struct spdk_bdev *bdev; 123 int rc = 0; 124 struct spdk_uuid *uuid = NULL; 125 struct spdk_uuid decoded_uuid; 126 127 if (spdk_json_decode_object(params, rpc_create_rbd_decoders, 128 SPDK_COUNTOF(rpc_create_rbd_decoders), 129 &req)) { 130 SPDK_DEBUGLOG(bdev_rbd, "spdk_json_decode_object failed\n"); 131 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 132 "spdk_json_decode_object failed"); 133 goto cleanup; 134 } 135 136 if (req.uuid) { 137 if (spdk_uuid_parse(&decoded_uuid, req.uuid)) { 138 spdk_jsonrpc_send_error_response(request, -EINVAL, 139 "Failed to parse bdev UUID"); 140 goto cleanup; 141 } 142 uuid = &decoded_uuid; 143 } 144 145 rc = bdev_rbd_create(&bdev, req.name, req.user_id, req.pool_name, 146 (const char *const *)req.config, 147 req.rbd_name, 148 req.block_size, req.cluster_name, uuid); 149 if (rc) { 150 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 151 goto cleanup; 152 } 153 154 w = spdk_jsonrpc_begin_result(request); 155 spdk_json_write_string(w, spdk_bdev_get_name(bdev)); 156 spdk_jsonrpc_end_result(request, w); 157 158 cleanup: 159 free_rpc_create_rbd(&req); 160 } 161 SPDK_RPC_REGISTER("bdev_rbd_create", rpc_bdev_rbd_create, SPDK_RPC_RUNTIME) 162 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_rbd_create, construct_rbd_bdev) 163 164 struct rpc_bdev_rbd_delete { 165 char *name; 166 }; 167 168 static void 169 free_rpc_bdev_rbd_delete(struct rpc_bdev_rbd_delete *req) 170 { 171 free(req->name); 172 } 173 174 static const struct spdk_json_object_decoder rpc_bdev_rbd_delete_decoders[] = { 175 {"name", offsetof(struct rpc_bdev_rbd_delete, name), spdk_json_decode_string}, 176 }; 177 178 static void 179 _rpc_bdev_rbd_delete_cb(void *cb_arg, int bdeverrno) 180 { 181 struct spdk_jsonrpc_request *request = cb_arg; 182 183 spdk_jsonrpc_send_bool_response(request, bdeverrno == 0); 184 } 185 186 static void 187 rpc_bdev_rbd_delete(struct spdk_jsonrpc_request *request, 188 const struct spdk_json_val *params) 189 { 190 struct rpc_bdev_rbd_delete req = {NULL}; 191 struct spdk_bdev *bdev; 192 193 if (spdk_json_decode_object(params, rpc_bdev_rbd_delete_decoders, 194 SPDK_COUNTOF(rpc_bdev_rbd_delete_decoders), 195 &req)) { 196 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 197 "spdk_json_decode_object failed"); 198 goto cleanup; 199 } 200 201 bdev = spdk_bdev_get_by_name(req.name); 202 if (bdev == NULL) { 203 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 204 goto cleanup; 205 } 206 207 bdev_rbd_delete(bdev, _rpc_bdev_rbd_delete_cb, request); 208 209 cleanup: 210 free_rpc_bdev_rbd_delete(&req); 211 } 212 SPDK_RPC_REGISTER("bdev_rbd_delete", rpc_bdev_rbd_delete, SPDK_RPC_RUNTIME) 213 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_rbd_delete, delete_rbd_bdev) 214 215 struct rpc_bdev_rbd_resize { 216 char *name; 217 uint64_t new_size; 218 }; 219 220 static const struct spdk_json_object_decoder rpc_bdev_rbd_resize_decoders[] = { 221 {"name", offsetof(struct rpc_bdev_rbd_resize, name), spdk_json_decode_string}, 222 {"new_size", offsetof(struct rpc_bdev_rbd_resize, new_size), spdk_json_decode_uint64} 223 }; 224 225 static void 226 free_rpc_bdev_rbd_resize(struct rpc_bdev_rbd_resize *req) 227 { 228 free(req->name); 229 } 230 231 static void 232 rpc_bdev_rbd_resize(struct spdk_jsonrpc_request *request, 233 const struct spdk_json_val *params) 234 { 235 struct rpc_bdev_rbd_resize req = {}; 236 struct spdk_bdev *bdev; 237 int rc; 238 239 if (spdk_json_decode_object(params, rpc_bdev_rbd_resize_decoders, 240 SPDK_COUNTOF(rpc_bdev_rbd_resize_decoders), 241 &req)) { 242 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 243 "spdk_json_decode_object failed"); 244 goto cleanup; 245 } 246 247 bdev = spdk_bdev_get_by_name(req.name); 248 if (bdev == NULL) { 249 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 250 goto cleanup; 251 } 252 253 rc = bdev_rbd_resize(bdev, req.new_size); 254 if (rc) { 255 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 256 goto cleanup; 257 } 258 259 spdk_jsonrpc_send_bool_response(request, true); 260 cleanup: 261 free_rpc_bdev_rbd_resize(&req); 262 } 263 SPDK_RPC_REGISTER("bdev_rbd_resize", rpc_bdev_rbd_resize, SPDK_RPC_RUNTIME) 264 265 static void 266 free_rpc_register_cluster(struct cluster_register_info *req) 267 { 268 free(req->name); 269 free(req->user_id); 270 bdev_rbd_free_config(req->config_param); 271 free(req->config_file); 272 } 273 274 static const struct spdk_json_object_decoder rpc_register_cluster_decoders[] = { 275 {"name", offsetof(struct cluster_register_info, name), spdk_json_decode_string, true}, 276 {"user_id", offsetof(struct cluster_register_info, user_id), spdk_json_decode_string, true}, 277 {"config_param", offsetof(struct cluster_register_info, config_param), bdev_rbd_decode_config, true}, 278 {"config_file", offsetof(struct cluster_register_info, config_file), bdev_rbd_decode_config, true} 279 }; 280 281 static void 282 rpc_bdev_rbd_register_cluster(struct spdk_jsonrpc_request *request, 283 const struct spdk_json_val *params) 284 { 285 struct cluster_register_info req = {}; 286 int rc = 0; 287 struct spdk_json_write_ctx *w; 288 289 if (spdk_json_decode_object(params, rpc_register_cluster_decoders, 290 SPDK_COUNTOF(rpc_register_cluster_decoders), 291 &req)) { 292 SPDK_DEBUGLOG(bdev_rbd, "spdk_json_decode_object failed\n"); 293 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 294 "spdk_json_decode_object failed"); 295 goto cleanup; 296 } 297 298 rc = bdev_rbd_register_cluster(&req); 299 if (rc) { 300 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 301 goto cleanup; 302 } 303 304 w = spdk_jsonrpc_begin_result(request); 305 spdk_json_write_string(w, req.name); 306 spdk_jsonrpc_end_result(request, w); 307 cleanup: 308 free_rpc_register_cluster(&req); 309 } 310 SPDK_RPC_REGISTER("bdev_rbd_register_cluster", rpc_bdev_rbd_register_cluster, SPDK_RPC_RUNTIME) 311 312 struct rpc_bdev_rbd_unregister_cluster { 313 char *name; 314 }; 315 316 static void 317 free_rpc_bdev_cluster_unregister(struct rpc_bdev_rbd_unregister_cluster *req) 318 { 319 free(req->name); 320 } 321 322 static const struct spdk_json_object_decoder rpc_bdev_rbd_unregister_cluster_decoders[] = { 323 {"name", offsetof(struct rpc_bdev_rbd_unregister_cluster, name), spdk_json_decode_string}, 324 }; 325 326 static void 327 rpc_bdev_rbd_unregister_cluster(struct spdk_jsonrpc_request *request, 328 const struct spdk_json_val *params) 329 { 330 struct rpc_bdev_rbd_unregister_cluster req = {NULL}; 331 int rc; 332 333 if (spdk_json_decode_object(params, rpc_bdev_rbd_unregister_cluster_decoders, 334 SPDK_COUNTOF(rpc_bdev_rbd_unregister_cluster_decoders), 335 &req)) { 336 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 337 "spdk_json_decode_object failed"); 338 goto cleanup; 339 } 340 341 rc = bdev_rbd_unregister_cluster(req.name); 342 if (rc) { 343 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 344 goto cleanup; 345 } 346 347 spdk_jsonrpc_send_bool_response(request, true); 348 349 cleanup: 350 free_rpc_bdev_cluster_unregister(&req); 351 } 352 SPDK_RPC_REGISTER("bdev_rbd_unregister_cluster", rpc_bdev_rbd_unregister_cluster, SPDK_RPC_RUNTIME) 353 354 struct rpc_bdev_rbd_get_cluster_info { 355 char *name; 356 }; 357 358 static void 359 free_rpc_bdev_rbd_get_cluster_info(struct rpc_bdev_rbd_get_cluster_info *req) 360 { 361 free(req->name); 362 } 363 364 static const struct spdk_json_object_decoder rpc_bdev_rbd_get_cluster_info_decoders[] = { 365 {"name", offsetof(struct rpc_bdev_rbd_get_cluster_info, name), spdk_json_decode_string, true}, 366 }; 367 368 static void 369 rpc_bdev_rbd_get_clusters_info(struct spdk_jsonrpc_request *request, 370 const struct spdk_json_val *params) 371 { 372 struct rpc_bdev_rbd_get_cluster_info req = {NULL}; 373 int rc; 374 375 if (params && spdk_json_decode_object(params, rpc_bdev_rbd_get_cluster_info_decoders, 376 SPDK_COUNTOF(rpc_bdev_rbd_get_cluster_info_decoders), 377 &req)) { 378 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 379 "spdk_json_decode_object failed"); 380 goto cleanup; 381 } 382 383 rc = bdev_rbd_get_clusters_info(request, req.name); 384 if (rc) { 385 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 386 goto cleanup; 387 } 388 389 cleanup: 390 free_rpc_bdev_rbd_get_cluster_info(&req); 391 } 392 SPDK_RPC_REGISTER("bdev_rbd_get_clusters_info", rpc_bdev_rbd_get_clusters_info, SPDK_RPC_RUNTIME) 393