xref: /spdk/module/bdev/ftl/bdev_ftl_rpc.c (revision 510f4c134a21b45ff3a5add9ebc6c6cf7e49aeab)
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