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 if (bdeverrno == 0) { 184 spdk_jsonrpc_send_bool_response(request, true); 185 } else { 186 spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno)); 187 } 188 } 189 190 static void 191 rpc_bdev_rbd_delete(struct spdk_jsonrpc_request *request, 192 const struct spdk_json_val *params) 193 { 194 struct rpc_bdev_rbd_delete req = {NULL}; 195 196 if (spdk_json_decode_object(params, rpc_bdev_rbd_delete_decoders, 197 SPDK_COUNTOF(rpc_bdev_rbd_delete_decoders), 198 &req)) { 199 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 200 "spdk_json_decode_object failed"); 201 goto cleanup; 202 } 203 204 bdev_rbd_delete(req.name, _rpc_bdev_rbd_delete_cb, request); 205 206 cleanup: 207 free_rpc_bdev_rbd_delete(&req); 208 } 209 SPDK_RPC_REGISTER("bdev_rbd_delete", rpc_bdev_rbd_delete, SPDK_RPC_RUNTIME) 210 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_rbd_delete, delete_rbd_bdev) 211 212 struct rpc_bdev_rbd_resize { 213 char *name; 214 uint64_t new_size; 215 }; 216 217 static const struct spdk_json_object_decoder rpc_bdev_rbd_resize_decoders[] = { 218 {"name", offsetof(struct rpc_bdev_rbd_resize, name), spdk_json_decode_string}, 219 {"new_size", offsetof(struct rpc_bdev_rbd_resize, new_size), spdk_json_decode_uint64} 220 }; 221 222 static void 223 free_rpc_bdev_rbd_resize(struct rpc_bdev_rbd_resize *req) 224 { 225 free(req->name); 226 } 227 228 static void 229 rpc_bdev_rbd_resize(struct spdk_jsonrpc_request *request, 230 const struct spdk_json_val *params) 231 { 232 struct rpc_bdev_rbd_resize req = {}; 233 int rc; 234 235 if (spdk_json_decode_object(params, rpc_bdev_rbd_resize_decoders, 236 SPDK_COUNTOF(rpc_bdev_rbd_resize_decoders), 237 &req)) { 238 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 239 "spdk_json_decode_object failed"); 240 goto cleanup; 241 } 242 243 rc = bdev_rbd_resize(req.name, req.new_size); 244 if (rc) { 245 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 246 goto cleanup; 247 } 248 249 spdk_jsonrpc_send_bool_response(request, true); 250 cleanup: 251 free_rpc_bdev_rbd_resize(&req); 252 } 253 SPDK_RPC_REGISTER("bdev_rbd_resize", rpc_bdev_rbd_resize, SPDK_RPC_RUNTIME) 254 255 static void 256 free_rpc_register_cluster(struct cluster_register_info *req) 257 { 258 free(req->name); 259 free(req->user_id); 260 bdev_rbd_free_config(req->config_param); 261 free(req->config_file); 262 free(req->key_file); 263 } 264 265 static const struct spdk_json_object_decoder rpc_register_cluster_decoders[] = { 266 {"name", offsetof(struct cluster_register_info, name), spdk_json_decode_string, true}, 267 {"user_id", offsetof(struct cluster_register_info, user_id), spdk_json_decode_string, true}, 268 {"config_param", offsetof(struct cluster_register_info, config_param), bdev_rbd_decode_config, true}, 269 {"config_file", offsetof(struct cluster_register_info, config_file), spdk_json_decode_string, true}, 270 {"key_file", offsetof(struct cluster_register_info, key_file), spdk_json_decode_string, true} 271 }; 272 273 static void 274 rpc_bdev_rbd_register_cluster(struct spdk_jsonrpc_request *request, 275 const struct spdk_json_val *params) 276 { 277 struct cluster_register_info req = {}; 278 int rc = 0; 279 struct spdk_json_write_ctx *w; 280 281 if (spdk_json_decode_object(params, rpc_register_cluster_decoders, 282 SPDK_COUNTOF(rpc_register_cluster_decoders), 283 &req)) { 284 SPDK_DEBUGLOG(bdev_rbd, "spdk_json_decode_object failed\n"); 285 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 286 "spdk_json_decode_object failed"); 287 goto cleanup; 288 } 289 290 rc = bdev_rbd_register_cluster(&req); 291 if (rc) { 292 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 293 goto cleanup; 294 } 295 296 w = spdk_jsonrpc_begin_result(request); 297 spdk_json_write_string(w, req.name); 298 spdk_jsonrpc_end_result(request, w); 299 cleanup: 300 free_rpc_register_cluster(&req); 301 } 302 SPDK_RPC_REGISTER("bdev_rbd_register_cluster", rpc_bdev_rbd_register_cluster, SPDK_RPC_RUNTIME) 303 304 struct rpc_bdev_rbd_unregister_cluster { 305 char *name; 306 }; 307 308 static void 309 free_rpc_bdev_cluster_unregister(struct rpc_bdev_rbd_unregister_cluster *req) 310 { 311 free(req->name); 312 } 313 314 static const struct spdk_json_object_decoder rpc_bdev_rbd_unregister_cluster_decoders[] = { 315 {"name", offsetof(struct rpc_bdev_rbd_unregister_cluster, name), spdk_json_decode_string}, 316 }; 317 318 static void 319 rpc_bdev_rbd_unregister_cluster(struct spdk_jsonrpc_request *request, 320 const struct spdk_json_val *params) 321 { 322 struct rpc_bdev_rbd_unregister_cluster req = {NULL}; 323 int rc; 324 325 if (spdk_json_decode_object(params, rpc_bdev_rbd_unregister_cluster_decoders, 326 SPDK_COUNTOF(rpc_bdev_rbd_unregister_cluster_decoders), 327 &req)) { 328 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 329 "spdk_json_decode_object failed"); 330 goto cleanup; 331 } 332 333 rc = bdev_rbd_unregister_cluster(req.name); 334 if (rc) { 335 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 336 goto cleanup; 337 } 338 339 spdk_jsonrpc_send_bool_response(request, true); 340 341 cleanup: 342 free_rpc_bdev_cluster_unregister(&req); 343 } 344 SPDK_RPC_REGISTER("bdev_rbd_unregister_cluster", rpc_bdev_rbd_unregister_cluster, SPDK_RPC_RUNTIME) 345 346 struct rpc_bdev_rbd_get_cluster_info { 347 char *name; 348 }; 349 350 static void 351 free_rpc_bdev_rbd_get_cluster_info(struct rpc_bdev_rbd_get_cluster_info *req) 352 { 353 free(req->name); 354 } 355 356 static const struct spdk_json_object_decoder rpc_bdev_rbd_get_cluster_info_decoders[] = { 357 {"name", offsetof(struct rpc_bdev_rbd_get_cluster_info, name), spdk_json_decode_string, true}, 358 }; 359 360 static void 361 rpc_bdev_rbd_get_clusters_info(struct spdk_jsonrpc_request *request, 362 const struct spdk_json_val *params) 363 { 364 struct rpc_bdev_rbd_get_cluster_info req = {NULL}; 365 int rc; 366 367 if (params && spdk_json_decode_object(params, rpc_bdev_rbd_get_cluster_info_decoders, 368 SPDK_COUNTOF(rpc_bdev_rbd_get_cluster_info_decoders), 369 &req)) { 370 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 371 "spdk_json_decode_object failed"); 372 goto cleanup; 373 } 374 375 rc = bdev_rbd_get_clusters_info(request, req.name); 376 if (rc) { 377 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 378 goto cleanup; 379 } 380 381 cleanup: 382 free_rpc_bdev_rbd_get_cluster_info(&req); 383 } 384 SPDK_RPC_REGISTER("bdev_rbd_get_clusters_info", rpc_bdev_rbd_get_clusters_info, SPDK_RPC_RUNTIME) 385