xref: /spdk/module/bdev/delay/vbdev_delay_rpc.c (revision 88e3ffd7b6c5ec1ea1a660354d25f02c766092e1)
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/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 	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(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 		SPDK_UNREACHABLE();
104 	}
105 
106 	spdk_jsonrpc_send_bool_response(request, true);
107 
108 cleanup:
109 	free_rpc_update_latency(&req);
110 }
111 SPDK_RPC_REGISTER("bdev_delay_update_latency", rpc_bdev_delay_update_latency, SPDK_RPC_RUNTIME)
112 
113 struct rpc_construct_delay {
114 	char *base_bdev_name;
115 	char *name;
116 	uint64_t avg_read_latency;
117 	uint64_t p99_read_latency;
118 	uint64_t avg_write_latency;
119 	uint64_t p99_write_latency;
120 };
121 
122 static void
123 free_rpc_construct_delay(struct rpc_construct_delay *r)
124 {
125 	free(r->base_bdev_name);
126 	free(r->name);
127 }
128 
129 static const struct spdk_json_object_decoder rpc_construct_delay_decoders[] = {
130 	{"base_bdev_name", offsetof(struct rpc_construct_delay, base_bdev_name), spdk_json_decode_string},
131 	{"name", offsetof(struct rpc_construct_delay, name), spdk_json_decode_string},
132 	{"avg_read_latency", offsetof(struct rpc_construct_delay, avg_read_latency), spdk_json_decode_uint64},
133 	{"p99_read_latency", offsetof(struct rpc_construct_delay, p99_read_latency), spdk_json_decode_uint64},
134 	{"avg_write_latency", offsetof(struct rpc_construct_delay, avg_write_latency), spdk_json_decode_uint64},
135 	{"p99_write_latency", offsetof(struct rpc_construct_delay, p99_write_latency), spdk_json_decode_uint64},
136 };
137 
138 static void
139 rpc_bdev_delay_create(struct spdk_jsonrpc_request *request,
140 		      const struct spdk_json_val *params)
141 {
142 	struct rpc_construct_delay req = {NULL};
143 	struct spdk_json_write_ctx *w;
144 	int rc;
145 
146 	if (spdk_json_decode_object(params, rpc_construct_delay_decoders,
147 				    SPDK_COUNTOF(rpc_construct_delay_decoders),
148 				    &req)) {
149 		SPDK_DEBUGLOG(vbdev_delay, "spdk_json_decode_object failed\n");
150 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
151 						 "spdk_json_decode_object failed");
152 		goto cleanup;
153 	}
154 
155 	rc = create_delay_disk(req.base_bdev_name, req.name, req.avg_read_latency, req.p99_read_latency,
156 			       req.avg_write_latency, req.p99_write_latency);
157 	if (rc != 0) {
158 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
159 		goto cleanup;
160 	}
161 
162 	w = spdk_jsonrpc_begin_result(request);
163 	spdk_json_write_string(w, req.name);
164 	spdk_jsonrpc_end_result(request, w);
165 
166 cleanup:
167 	free_rpc_construct_delay(&req);
168 }
169 SPDK_RPC_REGISTER("bdev_delay_create", rpc_bdev_delay_create, SPDK_RPC_RUNTIME)
170 
171 struct rpc_delete_delay {
172 	char *name;
173 };
174 
175 static void
176 free_rpc_delete_delay(struct rpc_delete_delay *req)
177 {
178 	free(req->name);
179 }
180 
181 static const struct spdk_json_object_decoder rpc_delete_delay_decoders[] = {
182 	{"name", offsetof(struct rpc_delete_delay, name), spdk_json_decode_string},
183 };
184 
185 static void
186 rpc_bdev_delay_delete_cb(void *cb_arg, int bdeverrno)
187 {
188 	struct spdk_jsonrpc_request *request = cb_arg;
189 
190 	spdk_jsonrpc_send_bool_response(request, bdeverrno == 0);
191 }
192 
193 static void
194 rpc_bdev_delay_delete(struct spdk_jsonrpc_request *request,
195 		      const struct spdk_json_val *params)
196 {
197 	struct rpc_delete_delay req = {NULL};
198 	struct spdk_bdev *bdev;
199 
200 	if (spdk_json_decode_object(params, rpc_delete_delay_decoders,
201 				    SPDK_COUNTOF(rpc_delete_delay_decoders),
202 				    &req)) {
203 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
204 						 "spdk_json_decode_object failed");
205 		goto cleanup;
206 	}
207 
208 	bdev = spdk_bdev_get_by_name(req.name);
209 	if (bdev == NULL) {
210 		spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
211 		goto cleanup;
212 	}
213 
214 	delete_delay_disk(bdev, rpc_bdev_delay_delete_cb, request);
215 
216 cleanup:
217 	free_rpc_delete_delay(&req);
218 }
219 SPDK_RPC_REGISTER("bdev_delay_delete", rpc_bdev_delay_delete, SPDK_RPC_RUNTIME)
220