1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2019 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "vbdev_delay.h" 7 #include "spdk/rpc.h" 8 #include "spdk/util.h" 9 #include "spdk/string.h" 10 #include "spdk/log.h" 11 #include "spdk_internal/assert.h" 12 13 struct rpc_update_latency { 14 char *delay_bdev_name; 15 char *latency_type; 16 uint64_t latency_us; 17 }; 18 19 static const struct spdk_json_object_decoder rpc_update_latency_decoders[] = { 20 {"delay_bdev_name", offsetof(struct rpc_update_latency, delay_bdev_name), spdk_json_decode_string}, 21 {"latency_type", offsetof(struct rpc_update_latency, latency_type), spdk_json_decode_string}, 22 {"latency_us", offsetof(struct rpc_update_latency, latency_us), spdk_json_decode_uint64} 23 }; 24 25 static void 26 free_rpc_update_latency(struct rpc_update_latency *req) 27 { 28 free(req->delay_bdev_name); 29 free(req->latency_type); 30 } 31 32 static void 33 rpc_bdev_delay_update_latency(struct spdk_jsonrpc_request *request, 34 const struct spdk_json_val *params) 35 { 36 struct rpc_update_latency req = {NULL}; 37 enum delay_io_type latency_type; 38 int rc = 0; 39 40 if (spdk_json_decode_object(params, rpc_update_latency_decoders, 41 SPDK_COUNTOF(rpc_update_latency_decoders), 42 &req)) { 43 SPDK_DEBUGLOG(vbdev_delay, "spdk_json_decode_object failed\n"); 44 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 45 "spdk_json_decode_object failed"); 46 goto cleanup; 47 } 48 49 if (!strncmp(req.latency_type, "avg_read", 9)) { 50 latency_type = DELAY_AVG_READ; 51 } else if (!strncmp(req.latency_type, "p99_read", 9)) { 52 latency_type = DELAY_P99_READ; 53 } else if (!strncmp(req.latency_type, "avg_write", 10)) { 54 latency_type = DELAY_AVG_WRITE; 55 } else if (!strncmp(req.latency_type, "p99_write", 10)) { 56 latency_type = DELAY_P99_WRITE; 57 } else { 58 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 59 "Please specify a valid latency type."); 60 goto cleanup; 61 } 62 63 rc = vbdev_delay_update_latency_value(req.delay_bdev_name, req.latency_us, latency_type); 64 65 if (rc == -ENODEV) { 66 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 67 "The requested bdev does not exist."); 68 goto cleanup; 69 } else if (rc == -EINVAL) { 70 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST, 71 "The requested bdev is not a delay bdev."); 72 goto cleanup; 73 } else if (rc) { 74 SPDK_UNREACHABLE(); 75 } 76 77 spdk_jsonrpc_send_bool_response(request, true); 78 79 cleanup: 80 free_rpc_update_latency(&req); 81 } 82 SPDK_RPC_REGISTER("bdev_delay_update_latency", rpc_bdev_delay_update_latency, SPDK_RPC_RUNTIME) 83 84 struct rpc_construct_delay { 85 char *base_bdev_name; 86 char *name; 87 struct spdk_uuid uuid; 88 uint64_t avg_read_latency; 89 uint64_t p99_read_latency; 90 uint64_t avg_write_latency; 91 uint64_t p99_write_latency; 92 }; 93 94 static void 95 free_rpc_construct_delay(struct rpc_construct_delay *r) 96 { 97 free(r->base_bdev_name); 98 free(r->name); 99 } 100 101 static const struct spdk_json_object_decoder rpc_construct_delay_decoders[] = { 102 {"base_bdev_name", offsetof(struct rpc_construct_delay, base_bdev_name), spdk_json_decode_string}, 103 {"name", offsetof(struct rpc_construct_delay, name), spdk_json_decode_string}, 104 {"uuid", offsetof(struct rpc_construct_delay, uuid), spdk_json_decode_uuid, true}, 105 {"avg_read_latency", offsetof(struct rpc_construct_delay, avg_read_latency), spdk_json_decode_uint64}, 106 {"p99_read_latency", offsetof(struct rpc_construct_delay, p99_read_latency), spdk_json_decode_uint64}, 107 {"avg_write_latency", offsetof(struct rpc_construct_delay, avg_write_latency), spdk_json_decode_uint64}, 108 {"p99_write_latency", offsetof(struct rpc_construct_delay, p99_write_latency), spdk_json_decode_uint64}, 109 }; 110 111 static void 112 rpc_bdev_delay_create(struct spdk_jsonrpc_request *request, 113 const struct spdk_json_val *params) 114 { 115 struct rpc_construct_delay req = {NULL}; 116 struct spdk_json_write_ctx *w; 117 int rc; 118 119 if (spdk_json_decode_object(params, rpc_construct_delay_decoders, 120 SPDK_COUNTOF(rpc_construct_delay_decoders), 121 &req)) { 122 SPDK_DEBUGLOG(vbdev_delay, "spdk_json_decode_object failed\n"); 123 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 124 "spdk_json_decode_object failed"); 125 goto cleanup; 126 } 127 128 rc = create_delay_disk(req.base_bdev_name, req.name, &req.uuid, req.avg_read_latency, 129 req.p99_read_latency, 130 req.avg_write_latency, req.p99_write_latency); 131 if (rc != 0) { 132 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 133 goto cleanup; 134 } 135 136 w = spdk_jsonrpc_begin_result(request); 137 spdk_json_write_string(w, req.name); 138 spdk_jsonrpc_end_result(request, w); 139 140 cleanup: 141 free_rpc_construct_delay(&req); 142 } 143 SPDK_RPC_REGISTER("bdev_delay_create", rpc_bdev_delay_create, SPDK_RPC_RUNTIME) 144 145 struct rpc_delete_delay { 146 char *name; 147 }; 148 149 static void 150 free_rpc_delete_delay(struct rpc_delete_delay *req) 151 { 152 free(req->name); 153 } 154 155 static const struct spdk_json_object_decoder rpc_delete_delay_decoders[] = { 156 {"name", offsetof(struct rpc_delete_delay, name), spdk_json_decode_string}, 157 }; 158 159 static void 160 rpc_bdev_delay_delete_cb(void *cb_arg, int bdeverrno) 161 { 162 struct spdk_jsonrpc_request *request = cb_arg; 163 164 if (bdeverrno == 0) { 165 spdk_jsonrpc_send_bool_response(request, true); 166 } else { 167 spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno)); 168 } 169 } 170 171 static void 172 rpc_bdev_delay_delete(struct spdk_jsonrpc_request *request, 173 const struct spdk_json_val *params) 174 { 175 struct rpc_delete_delay req = {NULL}; 176 177 if (spdk_json_decode_object(params, rpc_delete_delay_decoders, 178 SPDK_COUNTOF(rpc_delete_delay_decoders), 179 &req)) { 180 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 181 "spdk_json_decode_object failed"); 182 goto cleanup; 183 } 184 185 delete_delay_disk(req.name, rpc_bdev_delay_delete_cb, request); 186 187 cleanup: 188 free_rpc_delete_delay(&req); 189 } 190 SPDK_RPC_REGISTER("bdev_delay_delete", rpc_bdev_delay_delete, SPDK_RPC_RUNTIME) 191