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 "l2p_dram_limit", offsetof(struct spdk_ftl_conf, l2p_dram_limit), 42 spdk_json_decode_uint64, true 43 }, 44 { 45 "core_mask", offsetof(struct spdk_ftl_conf, core_mask), 46 spdk_json_decode_string, true 47 }, 48 { 49 "fast_shutdown", offsetof(struct spdk_ftl_conf, fast_shutdown), 50 spdk_json_decode_bool, true 51 }, 52 }; 53 54 static void 55 rpc_bdev_ftl_create_cb(const struct ftl_bdev_info *bdev_info, void *ctx, int status) 56 { 57 struct spdk_jsonrpc_request *request = ctx; 58 char bdev_uuid[SPDK_UUID_STRING_LEN]; 59 struct spdk_json_write_ctx *w; 60 61 if (status) { 62 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 63 "Failed to create FTL bdev: %s", 64 spdk_strerror(-status)); 65 return; 66 } 67 68 w = spdk_jsonrpc_begin_result(request); 69 spdk_uuid_fmt_lower(bdev_uuid, sizeof(bdev_uuid), &bdev_info->uuid); 70 spdk_json_write_object_begin(w); 71 spdk_json_write_named_string(w, "name", bdev_info->name); 72 spdk_json_write_named_string(w, "uuid", bdev_uuid); 73 spdk_json_write_object_end(w); 74 spdk_jsonrpc_end_result(request, w); 75 } 76 77 static void 78 rpc_bdev_ftl_create(struct spdk_jsonrpc_request *request, 79 const struct spdk_json_val *params) 80 { 81 struct spdk_ftl_conf conf = {}; 82 struct spdk_json_write_ctx *w; 83 int rc; 84 85 spdk_ftl_get_default_conf(&conf); 86 87 if (spdk_json_decode_object(params, rpc_bdev_ftl_create_decoders, 88 SPDK_COUNTOF(rpc_bdev_ftl_create_decoders), 89 &conf)) { 90 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 91 "Invalid parameters"); 92 goto out; 93 } 94 95 if (spdk_mem_all_zero(&conf.uuid, sizeof(conf.uuid))) { 96 conf.mode |= SPDK_FTL_MODE_CREATE; 97 } 98 99 rc = bdev_ftl_create_bdev(&conf, rpc_bdev_ftl_create_cb, request); 100 if (rc == -ENODEV) { 101 rc = bdev_ftl_defer_init(&conf); 102 if (rc == 0) { 103 w = spdk_jsonrpc_begin_result(request); 104 spdk_json_write_string_fmt(w, "FTL bdev: %s creation deferred", conf.name); 105 spdk_jsonrpc_end_result(request, w); 106 } 107 } 108 109 if (rc) { 110 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 111 "Failed to create FTL bdev: %s", 112 spdk_strerror(-rc)); 113 } 114 out: 115 spdk_ftl_conf_deinit(&conf); 116 } 117 SPDK_RPC_REGISTER("bdev_ftl_create", rpc_bdev_ftl_create, SPDK_RPC_RUNTIME) 118 119 static void 120 rpc_bdev_ftl_load(struct spdk_jsonrpc_request *request, 121 const struct spdk_json_val *params) 122 { 123 rpc_bdev_ftl_create(request, params); 124 } 125 SPDK_RPC_REGISTER("bdev_ftl_load", rpc_bdev_ftl_load, SPDK_RPC_RUNTIME) 126 127 struct rpc_delete_ftl { 128 char *name; 129 bool fast_shutdown; 130 }; 131 132 static const struct spdk_json_object_decoder rpc_delete_ftl_decoders[] = { 133 {"name", offsetof(struct rpc_delete_ftl, name), spdk_json_decode_string}, 134 { 135 "fast_shutdown", offsetof(struct rpc_delete_ftl, fast_shutdown), 136 spdk_json_decode_bool, true 137 }, 138 }; 139 140 static void 141 rpc_bdev_ftl_delete_cb(void *cb_arg, int bdeverrno) 142 { 143 struct spdk_jsonrpc_request *request = cb_arg; 144 145 spdk_jsonrpc_send_bool_response(request, bdeverrno == 0); 146 } 147 148 static void 149 rpc_bdev_ftl_delete(struct spdk_jsonrpc_request *request, 150 const struct spdk_json_val *params) 151 { 152 struct rpc_delete_ftl attrs = {}; 153 154 if (spdk_json_decode_object(params, rpc_delete_ftl_decoders, 155 SPDK_COUNTOF(rpc_delete_ftl_decoders), 156 &attrs)) { 157 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 158 "Invalid parameters"); 159 goto invalid; 160 } 161 162 bdev_ftl_delete_bdev(attrs.name, attrs.fast_shutdown, rpc_bdev_ftl_delete_cb, request); 163 invalid: 164 free(attrs.name); 165 } 166 SPDK_RPC_REGISTER("bdev_ftl_delete", rpc_bdev_ftl_delete, SPDK_RPC_RUNTIME) 167 168 static void 169 rpc_bdev_ftl_unload(struct spdk_jsonrpc_request *request, 170 const struct spdk_json_val *params) 171 { 172 rpc_bdev_ftl_delete(request, params); 173 } 174 SPDK_RPC_REGISTER("bdev_ftl_unload", rpc_bdev_ftl_unload, SPDK_RPC_RUNTIME) 175