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