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