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