xref: /spdk/module/bdev/error/vbdev_error_rpc.c (revision 60982c759db49b4f4579f16e3b24df0725ba4b94)
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 {
51 		SPDK_NOTICELOG("Invalid parameter value: error_type\n");
52 		return -EINVAL;
53 	}
54 
55 	return 0;
56 }
57 
58 struct rpc_bdev_error_create {
59 	char *base_name;
60 	char *uuid;
61 };
62 
63 static void
64 free_rpc_bdev_error_create(struct rpc_bdev_error_create *req)
65 {
66 	free(req->base_name);
67 	free(req->uuid);
68 }
69 
70 static const struct spdk_json_object_decoder rpc_bdev_error_create_decoders[] = {
71 	{"base_name", offsetof(struct rpc_bdev_error_create, base_name), spdk_json_decode_string},
72 	{"uuid", offsetof(struct rpc_bdev_error_create, uuid), spdk_json_decode_string, true},
73 };
74 
75 static void
76 rpc_bdev_error_create(struct spdk_jsonrpc_request *request,
77 		      const struct spdk_json_val *params)
78 {
79 	struct rpc_bdev_error_create req = {};
80 	struct spdk_uuid *uuid = NULL;
81 	struct spdk_uuid decoded_uuid;
82 	int rc = 0;
83 
84 	if (spdk_json_decode_object(params, rpc_bdev_error_create_decoders,
85 				    SPDK_COUNTOF(rpc_bdev_error_create_decoders),
86 				    &req)) {
87 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
88 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
89 						 "spdk_json_decode_object failed");
90 		goto cleanup;
91 	}
92 
93 	if (req.uuid) {
94 		if (spdk_uuid_parse(&decoded_uuid, req.uuid)) {
95 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
96 							 "Failed to parse bdev UUID");
97 			goto cleanup;
98 		}
99 		uuid = &decoded_uuid;
100 	}
101 
102 	rc = vbdev_error_create(req.base_name, uuid);
103 	if (rc) {
104 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
105 		goto cleanup;
106 	}
107 
108 	spdk_jsonrpc_send_bool_response(request, true);
109 
110 cleanup:
111 	free_rpc_bdev_error_create(&req);
112 }
113 SPDK_RPC_REGISTER("bdev_error_create", rpc_bdev_error_create, SPDK_RPC_RUNTIME)
114 
115 struct rpc_delete_error {
116 	char *name;
117 };
118 
119 static void
120 free_rpc_delete_error(struct rpc_delete_error *r)
121 {
122 	free(r->name);
123 }
124 
125 static const struct spdk_json_object_decoder rpc_delete_error_decoders[] = {
126 	{"name", offsetof(struct rpc_delete_error, name), spdk_json_decode_string},
127 };
128 
129 static void
130 rpc_bdev_error_delete_cb(void *cb_arg, int bdeverrno)
131 {
132 	struct spdk_jsonrpc_request *request = cb_arg;
133 
134 	if (bdeverrno == 0) {
135 		spdk_jsonrpc_send_bool_response(request, true);
136 	} else {
137 		spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
138 	}
139 }
140 
141 static void
142 rpc_bdev_error_delete(struct spdk_jsonrpc_request *request,
143 		      const struct spdk_json_val *params)
144 {
145 	struct rpc_delete_error req = {NULL};
146 
147 	if (spdk_json_decode_object(params, rpc_delete_error_decoders,
148 				    SPDK_COUNTOF(rpc_delete_error_decoders),
149 				    &req)) {
150 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
151 						 "spdk_json_decode_object failed");
152 		goto cleanup;
153 	}
154 
155 	vbdev_error_delete(req.name, rpc_bdev_error_delete_cb, request);
156 
157 cleanup:
158 	free_rpc_delete_error(&req);
159 }
160 SPDK_RPC_REGISTER("bdev_error_delete", rpc_bdev_error_delete, SPDK_RPC_RUNTIME)
161 
162 struct rpc_error_information {
163 	char *name;
164 	struct vbdev_error_inject_opts opts;
165 };
166 
167 static const struct spdk_json_object_decoder rpc_error_information_decoders[] = {
168 	{"name", offsetof(struct rpc_error_information, name), spdk_json_decode_string},
169 	{"io_type", offsetof(struct rpc_error_information, opts.io_type), rpc_error_bdev_decode_io_type},
170 	{"error_type", offsetof(struct rpc_error_information, opts.error_type), rpc_error_bdev_decode_error_type},
171 	{"num", offsetof(struct rpc_error_information, opts.error_num), spdk_json_decode_uint32, true},
172 	{"corrupt_offset", offsetof(struct rpc_error_information, opts.corrupt_offset), spdk_json_decode_uint64, true},
173 	{"corrupt_value", offsetof(struct rpc_error_information, opts.corrupt_value), spdk_json_decode_uint8, true},
174 };
175 
176 static void
177 free_rpc_error_information(struct rpc_error_information *p)
178 {
179 	free(p->name);
180 }
181 
182 static void
183 rpc_bdev_error_inject_error(struct spdk_jsonrpc_request *request,
184 			    const struct spdk_json_val *params)
185 {
186 	struct rpc_error_information req = {.opts.error_num = 1};
187 	int rc = 0;
188 
189 	if (spdk_json_decode_object(params, rpc_error_information_decoders,
190 				    SPDK_COUNTOF(rpc_error_information_decoders),
191 				    &req)) {
192 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
193 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
194 						 "spdk_json_decode_object failed");
195 		goto cleanup;
196 	}
197 
198 	rc = vbdev_error_inject_error(req.name, &req.opts);
199 	if (rc) {
200 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
201 		goto cleanup;
202 	}
203 
204 	spdk_jsonrpc_send_bool_response(request, true);
205 
206 cleanup:
207 	free_rpc_error_information(&req);
208 }
209 SPDK_RPC_REGISTER("bdev_error_inject_error", rpc_bdev_error_inject_error, SPDK_RPC_RUNTIME)
210