xref: /spdk/module/bdev/delay/vbdev_delay_rpc.c (revision 03e3fc4f5835983a4e6602b4e770922e798ce263)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *
12  *     * Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *     * Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in
16  *       the documentation and/or other materials provided with the
17  *       distribution.
18  *     * Neither the name of Intel Corporation nor the names of its
19  *       contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "vbdev_delay.h"
36 #include "spdk/rpc.h"
37 #include "spdk/util.h"
38 #include "spdk/string.h"
39 #include "spdk_internal/log.h"
40 #include "spdk_internal/assert.h"
41 
42 struct rpc_update_latency {
43 	char *delay_bdev_name;
44 	char *latency_type;
45 	uint64_t latency_us;
46 };
47 
48 static const struct spdk_json_object_decoder rpc_update_latency_decoders[] = {
49 	{"delay_bdev_name", offsetof(struct rpc_update_latency, delay_bdev_name), spdk_json_decode_string},
50 	{"latency_type", offsetof(struct rpc_update_latency, latency_type), spdk_json_decode_string},
51 	{"latency_us", offsetof(struct rpc_update_latency, latency_us), spdk_json_decode_uint64}
52 };
53 
54 static void
55 free_rpc_update_latency(struct rpc_update_latency *req)
56 {
57 	free(req->delay_bdev_name);
58 	free(req->latency_type);
59 }
60 
61 static void
62 rpc_bdev_delay_update_latency(struct spdk_jsonrpc_request *request,
63 			      const struct spdk_json_val *params)
64 {
65 	struct rpc_update_latency req = {NULL};
66 	struct spdk_json_write_ctx *w;
67 	enum delay_io_type latency_type;
68 	int rc = 0;
69 
70 	if (spdk_json_decode_object(params, rpc_update_latency_decoders,
71 				    SPDK_COUNTOF(rpc_update_latency_decoders),
72 				    &req)) {
73 		SPDK_DEBUGLOG(SPDK_LOG_VBDEV_DELAY, "spdk_json_decode_object failed\n");
74 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
75 						 "spdk_json_decode_object failed");
76 		goto cleanup;
77 	}
78 
79 	if (!strncmp(req.latency_type, "avg_read", 9)) {
80 		latency_type = DELAY_AVG_READ;
81 	} else if (!strncmp(req.latency_type, "p99_read", 9)) {
82 		latency_type = DELAY_P99_READ;
83 	} else if (!strncmp(req.latency_type, "avg_write", 10)) {
84 		latency_type = DELAY_AVG_WRITE;
85 	} else if (!strncmp(req.latency_type, "p99_write", 10)) {
86 		latency_type = DELAY_P99_WRITE;
87 	} else {
88 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
89 						 "Please specify a valid latency type.");
90 		goto cleanup;
91 	}
92 
93 	rc = vbdev_delay_update_latency_value(req.delay_bdev_name, req.latency_us, latency_type);
94 
95 	if (rc == -ENODEV) {
96 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
97 						 "The requested bdev does not exist.");
98 		goto cleanup;
99 	} else if (rc == -EINVAL) {
100 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST,
101 						 "The requested bdev is not a delay bdev.");
102 		goto cleanup;
103 	} else if (rc) {
104 		SPDK_UNREACHABLE();
105 	}
106 
107 	w = spdk_jsonrpc_begin_result(request);
108 	spdk_json_write_bool(w, true);
109 	spdk_jsonrpc_end_result(request, w);
110 
111 cleanup:
112 	free_rpc_update_latency(&req);
113 }
114 SPDK_RPC_REGISTER("bdev_delay_update_latency", rpc_bdev_delay_update_latency, SPDK_RPC_RUNTIME)
115 
116 struct rpc_construct_delay {
117 	char *base_bdev_name;
118 	char *name;
119 	uint64_t avg_read_latency;
120 	uint64_t p99_read_latency;
121 	uint64_t avg_write_latency;
122 	uint64_t p99_write_latency;
123 };
124 
125 static void
126 free_rpc_construct_delay(struct rpc_construct_delay *r)
127 {
128 	free(r->base_bdev_name);
129 	free(r->name);
130 }
131 
132 static const struct spdk_json_object_decoder rpc_construct_delay_decoders[] = {
133 	{"base_bdev_name", offsetof(struct rpc_construct_delay, base_bdev_name), spdk_json_decode_string},
134 	{"name", offsetof(struct rpc_construct_delay, name), spdk_json_decode_string},
135 	{"avg_read_latency", offsetof(struct rpc_construct_delay, avg_read_latency), spdk_json_decode_uint64},
136 	{"p99_read_latency", offsetof(struct rpc_construct_delay, p99_read_latency), spdk_json_decode_uint64},
137 	{"avg_write_latency", offsetof(struct rpc_construct_delay, avg_write_latency), spdk_json_decode_uint64},
138 	{"p99_write_latency", offsetof(struct rpc_construct_delay, p99_write_latency), spdk_json_decode_uint64},
139 };
140 
141 static void
142 rpc_bdev_delay_create(struct spdk_jsonrpc_request *request,
143 		      const struct spdk_json_val *params)
144 {
145 	struct rpc_construct_delay req = {NULL};
146 	struct spdk_json_write_ctx *w;
147 	int rc;
148 
149 	if (spdk_json_decode_object(params, rpc_construct_delay_decoders,
150 				    SPDK_COUNTOF(rpc_construct_delay_decoders),
151 				    &req)) {
152 		SPDK_DEBUGLOG(SPDK_LOG_VBDEV_DELAY, "spdk_json_decode_object failed\n");
153 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
154 						 "spdk_json_decode_object failed");
155 		goto cleanup;
156 	}
157 
158 	rc = create_delay_disk(req.base_bdev_name, req.name, req.avg_read_latency, req.p99_read_latency,
159 			       req.avg_write_latency, req.p99_write_latency);
160 	if (rc != 0) {
161 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
162 		goto cleanup;
163 	}
164 
165 	w = spdk_jsonrpc_begin_result(request);
166 	spdk_json_write_string(w, req.name);
167 	spdk_jsonrpc_end_result(request, w);
168 
169 cleanup:
170 	free_rpc_construct_delay(&req);
171 }
172 SPDK_RPC_REGISTER("bdev_delay_create", rpc_bdev_delay_create, SPDK_RPC_RUNTIME)
173 
174 struct rpc_delete_delay {
175 	char *name;
176 };
177 
178 static void
179 free_rpc_delete_delay(struct rpc_delete_delay *req)
180 {
181 	free(req->name);
182 }
183 
184 static const struct spdk_json_object_decoder rpc_delete_delay_decoders[] = {
185 	{"name", offsetof(struct rpc_delete_delay, name), spdk_json_decode_string},
186 };
187 
188 static void
189 rpc_bdev_delay_delete_cb(void *cb_arg, int bdeverrno)
190 {
191 	struct spdk_jsonrpc_request *request = cb_arg;
192 	struct spdk_json_write_ctx *w;
193 
194 	w = spdk_jsonrpc_begin_result(request);
195 	spdk_json_write_bool(w, bdeverrno == 0);
196 	spdk_jsonrpc_end_result(request, w);
197 }
198 
199 static void
200 rpc_bdev_delay_delete(struct spdk_jsonrpc_request *request,
201 		      const struct spdk_json_val *params)
202 {
203 	struct rpc_delete_delay req = {NULL};
204 	struct spdk_bdev *bdev;
205 
206 	if (spdk_json_decode_object(params, rpc_delete_delay_decoders,
207 				    SPDK_COUNTOF(rpc_delete_delay_decoders),
208 				    &req)) {
209 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
210 						 "spdk_json_decode_object failed");
211 		goto cleanup;
212 	}
213 
214 	bdev = spdk_bdev_get_by_name(req.name);
215 	if (bdev == NULL) {
216 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
217 		goto cleanup;
218 	}
219 
220 	delete_delay_disk(bdev, rpc_bdev_delay_delete_cb, request);
221 
222 cleanup:
223 	free_rpc_delete_delay(&req);
224 }
225 SPDK_RPC_REGISTER("bdev_delay_delete", rpc_bdev_delay_delete, SPDK_RPC_RUNTIME)
226