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