1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/rpc.h" 7 #include "spdk/util.h" 8 #include "spdk/bdev_module.h" 9 #include "spdk/string.h" 10 #include "spdk/log.h" 11 12 #include "bdev_ftl.h" 13 14 static int 15 rpc_bdev_ftl_decode_uuid(const struct spdk_json_val *val, void *out) 16 { 17 char *uuid_str; 18 int ret; 19 20 uuid_str = spdk_json_strdup(val); 21 if (!uuid_str) { 22 return -ENOMEM; 23 } 24 25 ret = spdk_uuid_parse(out, uuid_str); 26 27 free(uuid_str); 28 return ret; 29 } 30 31 static const struct spdk_json_object_decoder rpc_bdev_ftl_create_decoders[] = { 32 {"name", offsetof(struct spdk_ftl_conf, name), spdk_json_decode_string}, 33 {"base_bdev", offsetof(struct spdk_ftl_conf, base_bdev), spdk_json_decode_string}, 34 {"uuid", offsetof(struct spdk_ftl_conf, uuid), rpc_bdev_ftl_decode_uuid, true}, 35 {"cache", offsetof(struct spdk_ftl_conf, cache_bdev), spdk_json_decode_string}, 36 { 37 "overprovisioning", offsetof(struct spdk_ftl_conf, overprovisioning), 38 spdk_json_decode_uint64, true 39 }, 40 { 41 "core_mask", offsetof(struct spdk_ftl_conf, core_mask), 42 spdk_json_decode_string, true 43 }, 44 { 45 "fast_shutdown", offsetof(struct spdk_ftl_conf, fast_shutdown), 46 spdk_json_decode_bool, true 47 }, 48 }; 49 50 static void 51 rpc_bdev_ftl_create_cb(const struct ftl_bdev_info *bdev_info, void *ctx, int status) 52 { 53 struct spdk_jsonrpc_request *request = ctx; 54 char bdev_uuid[SPDK_UUID_STRING_LEN]; 55 struct spdk_json_write_ctx *w; 56 57 if (status) { 58 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 59 "Failed to create FTL bdev: %s", 60 spdk_strerror(-status)); 61 return; 62 } 63 64 w = spdk_jsonrpc_begin_result(request); 65 spdk_uuid_fmt_lower(bdev_uuid, sizeof(bdev_uuid), &bdev_info->uuid); 66 spdk_json_write_object_begin(w); 67 spdk_json_write_named_string(w, "name", bdev_info->name); 68 spdk_json_write_named_string(w, "uuid", bdev_uuid); 69 spdk_json_write_object_end(w); 70 spdk_jsonrpc_end_result(request, w); 71 } 72 73 static void 74 rpc_bdev_ftl_create(struct spdk_jsonrpc_request *request, 75 const struct spdk_json_val *params) 76 { 77 struct spdk_ftl_conf conf = {}; 78 struct spdk_json_write_ctx *w; 79 int rc; 80 81 spdk_ftl_get_default_conf(&conf); 82 83 if (spdk_json_decode_object(params, rpc_bdev_ftl_create_decoders, 84 SPDK_COUNTOF(rpc_bdev_ftl_create_decoders), 85 &conf)) { 86 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 87 "Invalid parameters"); 88 goto out; 89 } 90 91 if (spdk_mem_all_zero(&conf.uuid, sizeof(conf.uuid))) { 92 conf.mode |= SPDK_FTL_MODE_CREATE; 93 } 94 95 rc = bdev_ftl_create_bdev(&conf, rpc_bdev_ftl_create_cb, request); 96 if (rc == -ENODEV) { 97 rc = bdev_ftl_defer_init(&conf); 98 if (rc == 0) { 99 w = spdk_jsonrpc_begin_result(request); 100 spdk_json_write_string_fmt(w, "FTL bdev: %s creation deferred", conf.name); 101 spdk_jsonrpc_end_result(request, w); 102 } 103 } 104 105 if (rc) { 106 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 107 "Failed to create FTL bdev: %s", 108 spdk_strerror(-rc)); 109 } 110 out: 111 spdk_ftl_conf_deinit(&conf); 112 } 113 SPDK_RPC_REGISTER("bdev_ftl_create", rpc_bdev_ftl_create, SPDK_RPC_RUNTIME) 114 115 static void 116 rpc_bdev_ftl_load(struct spdk_jsonrpc_request *request, 117 const struct spdk_json_val *params) 118 { 119 rpc_bdev_ftl_create(request, params); 120 } 121 SPDK_RPC_REGISTER("bdev_ftl_load", rpc_bdev_ftl_load, SPDK_RPC_RUNTIME) 122 123 struct rpc_delete_ftl { 124 char *name; 125 bool fast_shutdown; 126 }; 127 128 static const struct spdk_json_object_decoder rpc_delete_ftl_decoders[] = { 129 {"name", offsetof(struct rpc_delete_ftl, name), spdk_json_decode_string}, 130 { 131 "fast_shutdown", offsetof(struct rpc_delete_ftl, fast_shutdown), 132 spdk_json_decode_bool, true 133 }, 134 }; 135 136 static void 137 rpc_bdev_ftl_delete_cb(void *cb_arg, int bdeverrno) 138 { 139 struct spdk_jsonrpc_request *request = cb_arg; 140 141 spdk_jsonrpc_send_bool_response(request, bdeverrno == 0); 142 } 143 144 static void 145 rpc_bdev_ftl_delete(struct spdk_jsonrpc_request *request, 146 const struct spdk_json_val *params) 147 { 148 struct rpc_delete_ftl attrs = {}; 149 150 if (spdk_json_decode_object(params, rpc_delete_ftl_decoders, 151 SPDK_COUNTOF(rpc_delete_ftl_decoders), 152 &attrs)) { 153 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 154 "Invalid parameters"); 155 goto invalid; 156 } 157 158 bdev_ftl_delete_bdev(attrs.name, attrs.fast_shutdown, rpc_bdev_ftl_delete_cb, request); 159 invalid: 160 free(attrs.name); 161 } 162 SPDK_RPC_REGISTER("bdev_ftl_delete", rpc_bdev_ftl_delete, SPDK_RPC_RUNTIME) 163 164 static void 165 rpc_bdev_ftl_unload(struct spdk_jsonrpc_request *request, 166 const struct spdk_json_val *params) 167 { 168 rpc_bdev_ftl_delete(request, params); 169 } 170 SPDK_RPC_REGISTER("bdev_ftl_unload", rpc_bdev_ftl_unload, SPDK_RPC_RUNTIME) 171