xref: /spdk/module/bdev/delay/vbdev_delay_rpc.c (revision 9889ab2dc80e40dae92dcef361d53dcba722043d)
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 
41 struct rpc_update_latency {
42 	char *delay_bdev_name;
43 	char *latency_type;
44 	uint64_t latency_us;
45 };
46 
47 static const struct spdk_json_object_decoder rpc_update_latency_decoders[] = {
48 	{"delay_bdev_name", offsetof(struct rpc_update_latency, delay_bdev_name), spdk_json_decode_string},
49 	{"latency_type", offsetof(struct rpc_update_latency, latency_type), spdk_json_decode_string},
50 	{"latency_us", offsetof(struct rpc_update_latency, latency_us), spdk_json_decode_uint64}
51 };
52 
53 static void
54 free_rpc_update_latency(struct rpc_update_latency *req)
55 {
56 	free(req->delay_bdev_name);
57 	free(req->latency_type);
58 }
59 
60 static void
61 spdk_rpc_bdev_delay_update_latency(struct spdk_jsonrpc_request *request,
62 				   const struct spdk_json_val *params)
63 {
64 	struct rpc_update_latency req = {NULL};
65 	struct spdk_json_write_ctx *w;
66 	enum delay_io_type latency_type;
67 	int rc = 0;
68 
69 	if (spdk_json_decode_object(params, rpc_update_latency_decoders,
70 				    SPDK_COUNTOF(rpc_update_latency_decoders),
71 				    &req)) {
72 		SPDK_DEBUGLOG(SPDK_LOG_VBDEV_DELAY, "spdk_json_decode_object failed\n");
73 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
74 						 "spdk_json_decode_object failed");
75 		goto cleanup;
76 	}
77 
78 	if (!strncmp(req.latency_type, "avg_read", 9)) {
79 		latency_type = DELAY_AVG_READ;
80 	} else if (!strncmp(req.latency_type, "p99_read", 9)) {
81 		latency_type = DELAY_P99_READ;
82 	} else if (!strncmp(req.latency_type, "avg_write", 10)) {
83 		latency_type = DELAY_AVG_WRITE;
84 	} else if (!strncmp(req.latency_type, "p99_write", 10)) {
85 		latency_type = DELAY_P99_WRITE;
86 	} else {
87 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
88 						 "Please specify a valid latency type.");
89 		goto cleanup;
90 	}
91 
92 	rc = vbdev_delay_update_latency_value(req.delay_bdev_name, req.latency_us, latency_type);
93 
94 	if (rc == -ENODEV) {
95 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
96 						 "The requested bdev does not exist.");
97 		goto cleanup;
98 	} else if (rc == -EINVAL) {
99 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST,
100 						 "The requested bdev is not a delay bdev.");
101 		goto cleanup;
102 	} else if (rc) {
103 		/* currently, only the two error cases are defined. Any new error paths should be handled here. */
104 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
105 						 "An unknown error occured.");
106 		goto cleanup;
107 	}
108 
109 	w = spdk_jsonrpc_begin_result(request);
110 	spdk_json_write_bool(w, true);
111 	spdk_jsonrpc_end_result(request, w);
112 
113 cleanup:
114 	free_rpc_update_latency(&req);
115 }
116 SPDK_RPC_REGISTER("bdev_delay_update_latency", spdk_rpc_bdev_delay_update_latency, SPDK_RPC_RUNTIME)
117 
118 struct rpc_construct_delay {
119 	char *base_bdev_name;
120 	char *name;
121 	uint64_t avg_read_latency;
122 	uint64_t p99_read_latency;
123 	uint64_t avg_write_latency;
124 	uint64_t p99_write_latency;
125 };
126 
127 static void
128 free_rpc_construct_delay(struct rpc_construct_delay *r)
129 {
130 	free(r->base_bdev_name);
131 	free(r->name);
132 }
133 
134 static const struct spdk_json_object_decoder rpc_construct_delay_decoders[] = {
135 	{"base_bdev_name", offsetof(struct rpc_construct_delay, base_bdev_name), spdk_json_decode_string},
136 	{"name", offsetof(struct rpc_construct_delay, name), spdk_json_decode_string},
137 	{"avg_read_latency", offsetof(struct rpc_construct_delay, avg_read_latency), spdk_json_decode_uint64},
138 	{"p99_read_latency", offsetof(struct rpc_construct_delay, p99_read_latency), spdk_json_decode_uint64},
139 	{"avg_write_latency", offsetof(struct rpc_construct_delay, avg_write_latency), spdk_json_decode_uint64},
140 	{"p99_write_latency", offsetof(struct rpc_construct_delay, p99_write_latency), spdk_json_decode_uint64},
141 };
142 
143 static void
144 spdk_rpc_bdev_delay_create(struct spdk_jsonrpc_request *request,
145 			   const struct spdk_json_val *params)
146 {
147 	struct rpc_construct_delay req = {NULL};
148 	struct spdk_json_write_ctx *w;
149 	int rc;
150 
151 	if (spdk_json_decode_object(params, rpc_construct_delay_decoders,
152 				    SPDK_COUNTOF(rpc_construct_delay_decoders),
153 				    &req)) {
154 		SPDK_DEBUGLOG(SPDK_LOG_VBDEV_DELAY, "spdk_json_decode_object failed\n");
155 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
156 						 "spdk_json_decode_object failed");
157 		goto cleanup;
158 	}
159 
160 	rc = create_delay_disk(req.base_bdev_name, req.name, req.avg_read_latency, req.p99_read_latency,
161 			       req.avg_write_latency, req.p99_write_latency);
162 	if (rc != 0) {
163 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
164 		goto cleanup;
165 	}
166 
167 	w = spdk_jsonrpc_begin_result(request);
168 	spdk_json_write_string(w, req.name);
169 	spdk_jsonrpc_end_result(request, w);
170 
171 cleanup:
172 	free_rpc_construct_delay(&req);
173 }
174 SPDK_RPC_REGISTER("bdev_delay_create", spdk_rpc_bdev_delay_create, SPDK_RPC_RUNTIME)
175 
176 struct rpc_delete_delay {
177 	char *name;
178 };
179 
180 static void
181 free_rpc_delete_delay(struct rpc_delete_delay *req)
182 {
183 	free(req->name);
184 }
185 
186 static const struct spdk_json_object_decoder rpc_delete_delay_decoders[] = {
187 	{"name", offsetof(struct rpc_delete_delay, name), spdk_json_decode_string},
188 };
189 
190 static void
191 _spdk_rpc_bdev_delay_delete_cb(void *cb_arg, int bdeverrno)
192 {
193 	struct spdk_jsonrpc_request *request = cb_arg;
194 	struct spdk_json_write_ctx *w;
195 
196 	w = spdk_jsonrpc_begin_result(request);
197 	spdk_json_write_bool(w, bdeverrno == 0);
198 	spdk_jsonrpc_end_result(request, w);
199 }
200 
201 static void
202 spdk_rpc_bdev_delay_delete(struct spdk_jsonrpc_request *request,
203 			   const struct spdk_json_val *params)
204 {
205 	struct rpc_delete_delay req = {NULL};
206 	struct spdk_bdev *bdev;
207 
208 	if (spdk_json_decode_object(params, rpc_delete_delay_decoders,
209 				    SPDK_COUNTOF(rpc_delete_delay_decoders),
210 				    &req)) {
211 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
212 						 "spdk_json_decode_object failed");
213 		goto cleanup;
214 	}
215 
216 	bdev = spdk_bdev_get_by_name(req.name);
217 	if (bdev == NULL) {
218 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
219 		goto cleanup;
220 	}
221 
222 	delete_delay_disk(bdev, _spdk_rpc_bdev_delay_delete_cb, request);
223 
224 cleanup:
225 	free_rpc_delete_delay(&req);
226 }
227 SPDK_RPC_REGISTER("bdev_delay_delete", spdk_rpc_bdev_delay_delete, SPDK_RPC_RUNTIME)
228