xref: /spdk/module/bdev/error/vbdev_error_rpc.c (revision 4f651a5c554531bf461572b7ff23a000d690b4c6)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2017 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/stdinc.h"
7 #include "spdk/string.h"
8 #include "spdk/rpc.h"
9 #include "spdk/util.h"
10 #include "spdk/string.h"
11 #include "spdk/log.h"
12 #include "vbdev_error.h"
13 
14 static int
15 rpc_error_bdev_decode_io_type(const struct spdk_json_val *val, void *out)
16 {
17 	uint32_t *io_type = out;
18 
19 	if (spdk_json_strequal(val, "read") == true) {
20 		*io_type = SPDK_BDEV_IO_TYPE_READ;
21 	} else if (spdk_json_strequal(val, "write") == true) {
22 		*io_type = SPDK_BDEV_IO_TYPE_WRITE;
23 	} else if (spdk_json_strequal(val, "flush") == true) {
24 		*io_type = SPDK_BDEV_IO_TYPE_FLUSH;
25 	} else if (spdk_json_strequal(val, "unmap") == true) {
26 		*io_type = SPDK_BDEV_IO_TYPE_UNMAP;
27 	} else if (spdk_json_strequal(val, "all") == true) {
28 		*io_type = 0xffffffff;
29 	} else if (spdk_json_strequal(val, "clear") == true) {
30 		*io_type = 0;
31 	} else {
32 		SPDK_NOTICELOG("Invalid parameter value: io_type\n");
33 		return -EINVAL;
34 	}
35 
36 	return 0;
37 }
38 
39 static int
40 rpc_error_bdev_decode_error_type(const struct spdk_json_val *val, void *out)
41 {
42 	uint32_t *error_type = out;
43 
44 	if (spdk_json_strequal(val, "failure") == true) {
45 		*error_type = VBDEV_IO_FAILURE;
46 	} else if (spdk_json_strequal(val, "pending") == true) {
47 		*error_type = VBDEV_IO_PENDING;
48 	} else if (spdk_json_strequal(val, "corrupt_data") == true) {
49 		*error_type = VBDEV_IO_CORRUPT_DATA;
50 	} else if (spdk_json_strequal(val, "nomem") == true) {
51 		*error_type = VBDEV_IO_NOMEM;
52 	} else {
53 		SPDK_NOTICELOG("Invalid parameter value: error_type\n");
54 		return -EINVAL;
55 	}
56 
57 	return 0;
58 }
59 
60 struct rpc_bdev_error_create {
61 	char *base_name;
62 	char *uuid;
63 };
64 
65 static void
66 free_rpc_bdev_error_create(struct rpc_bdev_error_create *req)
67 {
68 	free(req->base_name);
69 	free(req->uuid);
70 }
71 
72 static const struct spdk_json_object_decoder rpc_bdev_error_create_decoders[] = {
73 	{"base_name", offsetof(struct rpc_bdev_error_create, base_name), spdk_json_decode_string},
74 	{"uuid", offsetof(struct rpc_bdev_error_create, uuid), spdk_json_decode_string, true},
75 };
76 
77 static void
78 rpc_bdev_error_create(struct spdk_jsonrpc_request *request,
79 		      const struct spdk_json_val *params)
80 {
81 	struct rpc_bdev_error_create req = {};
82 	struct spdk_uuid *uuid = NULL;
83 	struct spdk_uuid decoded_uuid;
84 	int rc = 0;
85 
86 	if (spdk_json_decode_object(params, rpc_bdev_error_create_decoders,
87 				    SPDK_COUNTOF(rpc_bdev_error_create_decoders),
88 				    &req)) {
89 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
90 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
91 						 "spdk_json_decode_object failed");
92 		goto cleanup;
93 	}
94 
95 	if (req.uuid) {
96 		if (spdk_uuid_parse(&decoded_uuid, req.uuid)) {
97 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
98 							 "Failed to parse bdev UUID");
99 			goto cleanup;
100 		}
101 		uuid = &decoded_uuid;
102 	}
103 
104 	rc = vbdev_error_create(req.base_name, uuid);
105 	if (rc) {
106 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
107 		goto cleanup;
108 	}
109 
110 	spdk_jsonrpc_send_bool_response(request, true);
111 
112 cleanup:
113 	free_rpc_bdev_error_create(&req);
114 }
115 SPDK_RPC_REGISTER("bdev_error_create", rpc_bdev_error_create, SPDK_RPC_RUNTIME)
116 
117 struct rpc_delete_error {
118 	char *name;
119 };
120 
121 static void
122 free_rpc_delete_error(struct rpc_delete_error *r)
123 {
124 	free(r->name);
125 }
126 
127 static const struct spdk_json_object_decoder rpc_delete_error_decoders[] = {
128 	{"name", offsetof(struct rpc_delete_error, name), spdk_json_decode_string},
129 };
130 
131 static void
132 rpc_bdev_error_delete_cb(void *cb_arg, int bdeverrno)
133 {
134 	struct spdk_jsonrpc_request *request = cb_arg;
135 
136 	if (bdeverrno == 0) {
137 		spdk_jsonrpc_send_bool_response(request, true);
138 	} else {
139 		spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
140 	}
141 }
142 
143 static void
144 rpc_bdev_error_delete(struct spdk_jsonrpc_request *request,
145 		      const struct spdk_json_val *params)
146 {
147 	struct rpc_delete_error req = {NULL};
148 
149 	if (spdk_json_decode_object(params, rpc_delete_error_decoders,
150 				    SPDK_COUNTOF(rpc_delete_error_decoders),
151 				    &req)) {
152 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
153 						 "spdk_json_decode_object failed");
154 		goto cleanup;
155 	}
156 
157 	vbdev_error_delete(req.name, rpc_bdev_error_delete_cb, request);
158 
159 cleanup:
160 	free_rpc_delete_error(&req);
161 }
162 SPDK_RPC_REGISTER("bdev_error_delete", rpc_bdev_error_delete, SPDK_RPC_RUNTIME)
163 
164 struct rpc_error_information {
165 	char *name;
166 	struct vbdev_error_inject_opts opts;
167 };
168 
169 static const struct spdk_json_object_decoder rpc_error_information_decoders[] = {
170 	{"name", offsetof(struct rpc_error_information, name), spdk_json_decode_string},
171 	{"io_type", offsetof(struct rpc_error_information, opts.io_type), rpc_error_bdev_decode_io_type},
172 	{"error_type", offsetof(struct rpc_error_information, opts.error_type), rpc_error_bdev_decode_error_type},
173 	{"num", offsetof(struct rpc_error_information, opts.error_num), spdk_json_decode_uint32, true},
174 	{"queue_depth", offsetof(struct rpc_error_information, opts.error_qd), spdk_json_decode_uint64, true},
175 	{"corrupt_offset", offsetof(struct rpc_error_information, opts.corrupt_offset), spdk_json_decode_uint64, true},
176 	{"corrupt_value", offsetof(struct rpc_error_information, opts.corrupt_value), spdk_json_decode_uint8, true},
177 };
178 
179 static void
180 free_rpc_error_information(struct rpc_error_information *p)
181 {
182 	free(p->name);
183 }
184 
185 static void
186 rpc_bdev_error_inject_error(struct spdk_jsonrpc_request *request,
187 			    const struct spdk_json_val *params)
188 {
189 	struct rpc_error_information req = {.opts.error_num = 1};
190 	int rc = 0;
191 
192 	if (spdk_json_decode_object(params, rpc_error_information_decoders,
193 				    SPDK_COUNTOF(rpc_error_information_decoders),
194 				    &req)) {
195 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
196 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
197 						 "spdk_json_decode_object failed");
198 		goto cleanup;
199 	}
200 
201 	rc = vbdev_error_inject_error(req.name, &req.opts);
202 	if (rc) {
203 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
204 		goto cleanup;
205 	}
206 
207 	spdk_jsonrpc_send_bool_response(request, true);
208 
209 cleanup:
210 	free_rpc_error_information(&req);
211 }
212 SPDK_RPC_REGISTER("bdev_error_inject_error", rpc_bdev_error_inject_error, SPDK_RPC_RUNTIME)
213