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 uint64_t avg_read_latency; 88 uint64_t p99_read_latency; 89 uint64_t avg_write_latency; 90 uint64_t p99_write_latency; 91 }; 92 93 static void 94 free_rpc_construct_delay(struct rpc_construct_delay *r) 95 { 96 free(r->base_bdev_name); 97 free(r->name); 98 } 99 100 static const struct spdk_json_object_decoder rpc_construct_delay_decoders[] = { 101 {"base_bdev_name", offsetof(struct rpc_construct_delay, base_bdev_name), spdk_json_decode_string}, 102 {"name", offsetof(struct rpc_construct_delay, name), spdk_json_decode_string}, 103 {"avg_read_latency", offsetof(struct rpc_construct_delay, avg_read_latency), spdk_json_decode_uint64}, 104 {"p99_read_latency", offsetof(struct rpc_construct_delay, p99_read_latency), spdk_json_decode_uint64}, 105 {"avg_write_latency", offsetof(struct rpc_construct_delay, avg_write_latency), spdk_json_decode_uint64}, 106 {"p99_write_latency", offsetof(struct rpc_construct_delay, p99_write_latency), spdk_json_decode_uint64}, 107 }; 108 109 static void 110 rpc_bdev_delay_create(struct spdk_jsonrpc_request *request, 111 const struct spdk_json_val *params) 112 { 113 struct rpc_construct_delay req = {NULL}; 114 struct spdk_json_write_ctx *w; 115 int rc; 116 117 if (spdk_json_decode_object(params, rpc_construct_delay_decoders, 118 SPDK_COUNTOF(rpc_construct_delay_decoders), 119 &req)) { 120 SPDK_DEBUGLOG(vbdev_delay, "spdk_json_decode_object failed\n"); 121 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 122 "spdk_json_decode_object failed"); 123 goto cleanup; 124 } 125 126 rc = create_delay_disk(req.base_bdev_name, req.name, req.avg_read_latency, req.p99_read_latency, 127 req.avg_write_latency, req.p99_write_latency); 128 if (rc != 0) { 129 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 130 goto cleanup; 131 } 132 133 w = spdk_jsonrpc_begin_result(request); 134 spdk_json_write_string(w, req.name); 135 spdk_jsonrpc_end_result(request, w); 136 137 cleanup: 138 free_rpc_construct_delay(&req); 139 } 140 SPDK_RPC_REGISTER("bdev_delay_create", rpc_bdev_delay_create, SPDK_RPC_RUNTIME) 141 142 struct rpc_delete_delay { 143 char *name; 144 }; 145 146 static void 147 free_rpc_delete_delay(struct rpc_delete_delay *req) 148 { 149 free(req->name); 150 } 151 152 static const struct spdk_json_object_decoder rpc_delete_delay_decoders[] = { 153 {"name", offsetof(struct rpc_delete_delay, name), spdk_json_decode_string}, 154 }; 155 156 static void 157 rpc_bdev_delay_delete_cb(void *cb_arg, int bdeverrno) 158 { 159 struct spdk_jsonrpc_request *request = cb_arg; 160 161 if (bdeverrno == 0) { 162 spdk_jsonrpc_send_bool_response(request, true); 163 } else { 164 spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno)); 165 } 166 } 167 168 static void 169 rpc_bdev_delay_delete(struct spdk_jsonrpc_request *request, 170 const struct spdk_json_val *params) 171 { 172 struct rpc_delete_delay req = {NULL}; 173 174 if (spdk_json_decode_object(params, rpc_delete_delay_decoders, 175 SPDK_COUNTOF(rpc_delete_delay_decoders), 176 &req)) { 177 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 178 "spdk_json_decode_object failed"); 179 goto cleanup; 180 } 181 182 delete_delay_disk(req.name, rpc_bdev_delay_delete_cb, request); 183 184 cleanup: 185 free_rpc_delete_delay(&req); 186 } 187 SPDK_RPC_REGISTER("bdev_delay_delete", rpc_bdev_delay_delete, SPDK_RPC_RUNTIME) 188