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