1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 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 #define ERROR_BDEV_IO_TYPE_INVALID (SPDK_BDEV_IO_TYPE_RESET + 1) 15 #define ERROR_BDEV_ERROR_TYPE_INVALID (VBDEV_IO_PENDING + 1) 16 17 static uint32_t 18 rpc_error_bdev_io_type_parse(char *name) 19 { 20 if (strcmp(name, "read") == 0) { 21 return SPDK_BDEV_IO_TYPE_READ; 22 } else if (strcmp(name, "write") == 0) { 23 return SPDK_BDEV_IO_TYPE_WRITE; 24 } else if (strcmp(name, "flush") == 0) { 25 return SPDK_BDEV_IO_TYPE_FLUSH; 26 } else if (strcmp(name, "unmap") == 0) { 27 return SPDK_BDEV_IO_TYPE_UNMAP; 28 } else if (strcmp(name, "all") == 0) { 29 return 0xffffffff; 30 } else if (strcmp(name, "clear") == 0) { 31 return 0; 32 } 33 return ERROR_BDEV_IO_TYPE_INVALID; 34 } 35 36 static uint32_t 37 rpc_error_bdev_error_type_parse(char *name) 38 { 39 if (strcmp(name, "failure") == 0) { 40 return VBDEV_IO_FAILURE; 41 } else if (strcmp(name, "pending") == 0) { 42 return VBDEV_IO_PENDING; 43 } 44 return ERROR_BDEV_ERROR_TYPE_INVALID; 45 } 46 47 struct rpc_bdev_error_create { 48 char *base_name; 49 }; 50 51 static void 52 free_rpc_bdev_error_create(struct rpc_bdev_error_create *req) 53 { 54 free(req->base_name); 55 } 56 57 static const struct spdk_json_object_decoder rpc_bdev_error_create_decoders[] = { 58 {"base_name", offsetof(struct rpc_bdev_error_create, base_name), spdk_json_decode_string}, 59 }; 60 61 static void 62 rpc_bdev_error_create(struct spdk_jsonrpc_request *request, 63 const struct spdk_json_val *params) 64 { 65 struct rpc_bdev_error_create req = {}; 66 int rc = 0; 67 68 if (spdk_json_decode_object(params, rpc_bdev_error_create_decoders, 69 SPDK_COUNTOF(rpc_bdev_error_create_decoders), 70 &req)) { 71 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 72 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 73 "spdk_json_decode_object failed"); 74 goto cleanup; 75 } 76 77 rc = vbdev_error_create(req.base_name); 78 if (rc) { 79 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 80 goto cleanup; 81 } 82 83 spdk_jsonrpc_send_bool_response(request, true); 84 85 cleanup: 86 free_rpc_bdev_error_create(&req); 87 } 88 SPDK_RPC_REGISTER("bdev_error_create", rpc_bdev_error_create, SPDK_RPC_RUNTIME) 89 90 struct rpc_delete_error { 91 char *name; 92 }; 93 94 static void 95 free_rpc_delete_error(struct rpc_delete_error *r) 96 { 97 free(r->name); 98 } 99 100 static const struct spdk_json_object_decoder rpc_delete_error_decoders[] = { 101 {"name", offsetof(struct rpc_delete_error, name), spdk_json_decode_string}, 102 }; 103 104 static void 105 rpc_bdev_error_delete_cb(void *cb_arg, int bdeverrno) 106 { 107 struct spdk_jsonrpc_request *request = cb_arg; 108 109 if (bdeverrno == 0) { 110 spdk_jsonrpc_send_bool_response(request, true); 111 } else { 112 spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno)); 113 } 114 } 115 116 static void 117 rpc_bdev_error_delete(struct spdk_jsonrpc_request *request, 118 const struct spdk_json_val *params) 119 { 120 struct rpc_delete_error req = {NULL}; 121 122 if (spdk_json_decode_object(params, rpc_delete_error_decoders, 123 SPDK_COUNTOF(rpc_delete_error_decoders), 124 &req)) { 125 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 126 "spdk_json_decode_object failed"); 127 goto cleanup; 128 } 129 130 vbdev_error_delete(req.name, rpc_bdev_error_delete_cb, request); 131 132 cleanup: 133 free_rpc_delete_error(&req); 134 } 135 SPDK_RPC_REGISTER("bdev_error_delete", rpc_bdev_error_delete, SPDK_RPC_RUNTIME) 136 137 struct rpc_error_information { 138 char *name; 139 char *io_type; 140 char *error_type; 141 uint32_t num; 142 }; 143 144 static const struct spdk_json_object_decoder rpc_error_information_decoders[] = { 145 {"name", offsetof(struct rpc_error_information, name), spdk_json_decode_string}, 146 {"io_type", offsetof(struct rpc_error_information, io_type), spdk_json_decode_string}, 147 {"error_type", offsetof(struct rpc_error_information, error_type), spdk_json_decode_string}, 148 {"num", offsetof(struct rpc_error_information, num), spdk_json_decode_uint32, true}, 149 }; 150 151 static void 152 free_rpc_error_information(struct rpc_error_information *p) 153 { 154 free(p->name); 155 free(p->io_type); 156 free(p->error_type); 157 } 158 159 static void 160 rpc_bdev_error_inject_error(struct spdk_jsonrpc_request *request, 161 const struct spdk_json_val *params) 162 { 163 struct rpc_error_information req = {.num = 1}; 164 uint32_t io_type; 165 uint32_t error_type; 166 int rc = 0; 167 168 if (spdk_json_decode_object(params, rpc_error_information_decoders, 169 SPDK_COUNTOF(rpc_error_information_decoders), 170 &req)) { 171 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 172 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 173 "spdk_json_decode_object failed"); 174 goto cleanup; 175 } 176 177 io_type = rpc_error_bdev_io_type_parse(req.io_type); 178 if (io_type == ERROR_BDEV_IO_TYPE_INVALID) { 179 spdk_jsonrpc_send_error_response(request, -EINVAL, 180 "Unexpected io_type value"); 181 goto cleanup; 182 } 183 184 error_type = rpc_error_bdev_error_type_parse(req.error_type); 185 if (error_type == ERROR_BDEV_ERROR_TYPE_INVALID) { 186 spdk_jsonrpc_send_error_response(request, -EINVAL, 187 "Unexpected error_type value"); 188 goto cleanup; 189 } 190 191 rc = vbdev_error_inject_error(req.name, io_type, error_type, req.num); 192 if (rc) { 193 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 194 goto cleanup; 195 } 196 197 spdk_jsonrpc_send_bool_response(request, true); 198 199 cleanup: 200 free_rpc_error_information(&req); 201 } 202 SPDK_RPC_REGISTER("bdev_error_inject_error", rpc_bdev_error_inject_error, SPDK_RPC_RUNTIME) 203