1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "spdk_internal/log.h" 37 #include "spdk/rpc.h" 38 #include "spdk/util.h" 39 40 #include "spdk/vhost.h" 41 #include "task.h" 42 43 static void 44 json_scsi_dev_write(struct spdk_json_write_ctx *ctx, struct spdk_scsi_dev *dev) 45 { 46 int l, maxlun; 47 48 spdk_json_write_name(ctx, "id"); 49 spdk_json_write_int32(ctx, spdk_scsi_dev_get_id(dev)); 50 51 spdk_json_write_name(ctx, "device_name"); 52 spdk_json_write_string(ctx, spdk_scsi_dev_get_name(dev)); 53 54 spdk_json_write_name(ctx, "luns"); 55 spdk_json_write_array_begin(ctx); 56 maxlun = spdk_scsi_dev_get_max_lun(dev); 57 for (l = 0; l < maxlun; l++) { 58 struct spdk_scsi_lun *lun = spdk_scsi_dev_get_lun(dev, l); 59 60 if (!lun) { 61 continue; 62 } 63 64 spdk_json_write_object_begin(ctx); 65 66 spdk_json_write_name(ctx, "id"); 67 spdk_json_write_int32(ctx, spdk_scsi_lun_get_id(lun)); 68 69 spdk_json_write_name(ctx, "name"); 70 spdk_json_write_string(ctx, spdk_scsi_lun_get_name(lun)); 71 72 spdk_json_write_object_end(ctx); 73 } 74 spdk_json_write_array_end(ctx); 75 } 76 77 static void 78 spdk_rpc_get_vhost_scsi_controllers(struct spdk_jsonrpc_server_conn *conn, 79 const struct spdk_json_val *params, 80 const struct spdk_json_val *id) 81 { 82 struct spdk_json_write_ctx *w; 83 struct spdk_vhost_scsi_ctrlr *ctrlr = NULL; 84 struct spdk_scsi_dev *dev; 85 uint32_t i; 86 char buf[32]; 87 88 if (params != NULL) { 89 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 90 "get_vhost_scsi_controllers requires no parameters"); 91 return; 92 } 93 94 w = spdk_jsonrpc_begin_result(conn, id); 95 spdk_json_write_array_begin(w); 96 while ((ctrlr = spdk_vhost_scsi_ctrlr_next(ctrlr)) != NULL) { 97 spdk_json_write_object_begin(w); 98 99 spdk_json_write_name(w, "ctrlr"); 100 spdk_json_write_string(w, spdk_vhost_scsi_ctrlr_get_name(ctrlr)); 101 102 spdk_json_write_name(w, "cpu_mask"); 103 snprintf(buf, sizeof(buf), "%#" PRIx64, spdk_vhost_scsi_ctrlr_get_cpumask(ctrlr)); 104 spdk_json_write_string(w, buf); 105 106 spdk_json_write_name(w, "scsi_devs"); 107 spdk_json_write_array_begin(w); 108 109 for (i = 0; i < SPDK_VHOST_SCSI_CTRLR_MAX_DEVS; i++) { 110 dev = spdk_vhost_scsi_ctrlr_get_dev(ctrlr, i); 111 if (!dev) 112 continue; 113 114 spdk_json_write_object_begin(w); 115 spdk_json_write_name(w, "scsi_dev_num"); 116 spdk_json_write_uint32(w, i); 117 json_scsi_dev_write(w, dev); 118 spdk_json_write_object_end(w); 119 } 120 121 spdk_json_write_array_end(w); // devs 122 123 spdk_json_write_object_end(w); // ctrl 124 } 125 spdk_json_write_array_end(w); 126 spdk_jsonrpc_end_result(conn, w); 127 return; 128 } 129 SPDK_RPC_REGISTER("get_vhost_scsi_controllers", spdk_rpc_get_vhost_scsi_controllers) 130 131 struct rpc_vhost_scsi_ctrlr { 132 char *ctrlr; 133 char *cpumask; 134 }; 135 136 static void 137 free_rpc_vhost_scsi_ctrlr(struct rpc_vhost_scsi_ctrlr *req) 138 { 139 free(req->ctrlr); 140 free(req->cpumask); 141 } 142 143 static const struct spdk_json_object_decoder rpc_construct_vhost_ctrlr[] = { 144 {"ctrlr", offsetof(struct rpc_vhost_scsi_ctrlr, ctrlr), spdk_json_decode_string }, 145 {"cpumask", offsetof(struct rpc_vhost_scsi_ctrlr, cpumask), spdk_json_decode_string, true}, 146 }; 147 148 static void 149 spdk_rpc_construct_vhost_scsi_controller(struct spdk_jsonrpc_server_conn *conn, 150 const struct spdk_json_val *params, 151 const struct spdk_json_val *id) 152 { 153 struct rpc_vhost_scsi_ctrlr req = {0}; 154 struct spdk_json_write_ctx *w; 155 int rc; 156 uint64_t cpumask; 157 158 if (spdk_json_decode_object(params, rpc_construct_vhost_ctrlr, 159 SPDK_COUNTOF(rpc_construct_vhost_ctrlr), 160 &req)) { 161 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n"); 162 rc = -EINVAL; 163 goto invalid; 164 } 165 166 cpumask = spdk_app_get_core_mask(); 167 if (req.cpumask != NULL && spdk_vhost_parse_core_mask(req.cpumask, &cpumask)) { 168 rc = -EINVAL; 169 goto invalid; 170 } 171 172 rc = spdk_vhost_scsi_ctrlr_construct(req.ctrlr, cpumask); 173 if (rc < 0) { 174 goto invalid; 175 } 176 177 free_rpc_vhost_scsi_ctrlr(&req); 178 179 w = spdk_jsonrpc_begin_result(conn, id); 180 spdk_json_write_bool(w, true); 181 spdk_jsonrpc_end_result(conn, w); 182 return; 183 invalid: 184 free_rpc_vhost_scsi_ctrlr(&req); 185 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, strerror(-rc)); 186 } 187 SPDK_RPC_REGISTER("construct_vhost_scsi_controller", spdk_rpc_construct_vhost_scsi_controller) 188 189 struct rpc_remove_vhost_scsi_ctrlr { 190 char *ctrlr; 191 }; 192 193 static void 194 free_rpc_remove_vhost_scsi_ctrlr(struct rpc_remove_vhost_scsi_ctrlr *req) 195 { 196 free(req->ctrlr); 197 } 198 199 static const struct spdk_json_object_decoder rpc_remove_vhost_ctrlr[] = { 200 {"ctrlr", offsetof(struct rpc_remove_vhost_scsi_ctrlr, ctrlr), spdk_json_decode_string }, 201 }; 202 203 static void 204 spdk_rpc_remove_vhost_scsi_controller(struct spdk_jsonrpc_server_conn *conn, 205 const struct spdk_json_val *params, 206 const struct spdk_json_val *id) 207 { 208 struct rpc_remove_vhost_scsi_ctrlr req = {NULL}; 209 struct spdk_json_write_ctx *w; 210 struct spdk_vhost_scsi_ctrlr *vdev; 211 int rc; 212 213 if (spdk_json_decode_object(params, rpc_remove_vhost_ctrlr, 214 SPDK_COUNTOF(rpc_remove_vhost_ctrlr), 215 &req)) { 216 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n"); 217 rc = -EINVAL; 218 goto invalid; 219 } 220 221 if (!(vdev = spdk_vhost_scsi_ctrlr_find(req.ctrlr))) { 222 rc = -ENODEV; 223 goto invalid; 224 } 225 226 rc = spdk_vhost_scsi_ctrlr_remove(vdev); 227 if (rc < 0) { 228 goto invalid; 229 } 230 231 free_rpc_remove_vhost_scsi_ctrlr(&req); 232 233 if (id != NULL) { 234 w = spdk_jsonrpc_begin_result(conn, id); 235 spdk_json_write_bool(w, true); 236 spdk_jsonrpc_end_result(conn, w); 237 } 238 239 return; 240 invalid: 241 free_rpc_remove_vhost_scsi_ctrlr(&req); 242 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, strerror(-rc)); 243 } 244 SPDK_RPC_REGISTER("remove_vhost_scsi_controller", spdk_rpc_remove_vhost_scsi_controller) 245 246 247 struct rpc_add_vhost_scsi_ctrlr_lun { 248 char *ctrlr; 249 uint32_t scsi_dev_num; 250 char *lun_name; 251 }; 252 253 static void 254 free_rpc_add_vhost_scsi_ctrlr_lun(struct rpc_add_vhost_scsi_ctrlr_lun *req) 255 { 256 free(req->ctrlr); 257 free(req->lun_name); 258 } 259 260 static const struct spdk_json_object_decoder rpc_vhost_add_lun[] = { 261 {"ctrlr", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, ctrlr), spdk_json_decode_string }, 262 {"scsi_dev_num", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, scsi_dev_num), spdk_json_decode_uint32}, 263 {"lun_name", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, lun_name), spdk_json_decode_string }, 264 }; 265 266 static void 267 spdk_rpc_add_vhost_scsi_lun(struct spdk_jsonrpc_server_conn *conn, 268 const struct spdk_json_val *params, 269 const struct spdk_json_val *id) 270 { 271 struct rpc_add_vhost_scsi_ctrlr_lun req = {0}; 272 struct spdk_json_write_ctx *w; 273 int rc; 274 275 if (spdk_json_decode_object(params, rpc_vhost_add_lun, 276 SPDK_COUNTOF(rpc_vhost_add_lun), 277 &req)) { 278 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n"); 279 rc = -EINVAL; 280 goto invalid; 281 } 282 283 rc = spdk_vhost_scsi_ctrlr_add_dev(req.ctrlr, req.scsi_dev_num, req.lun_name); 284 if (rc < 0) { 285 goto invalid; 286 } 287 288 free_rpc_add_vhost_scsi_ctrlr_lun(&req); 289 290 if (id != NULL) { 291 w = spdk_jsonrpc_begin_result(conn, id); 292 spdk_json_write_bool(w, true); 293 spdk_jsonrpc_end_result(conn, w); 294 } 295 296 return; 297 invalid: 298 free_rpc_add_vhost_scsi_ctrlr_lun(&req); 299 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, strerror(-rc)); 300 } 301 SPDK_RPC_REGISTER("add_vhost_scsi_lun", spdk_rpc_add_vhost_scsi_lun) 302 303 struct rpc_remove_vhost_scsi_ctrlr_dev { 304 char *ctrlr; 305 uint32_t scsi_dev_num; 306 }; 307 308 static void 309 free_rpc_remove_vhost_scsi_ctrlr_dev(struct rpc_remove_vhost_scsi_ctrlr_dev *req) 310 { 311 free(req->ctrlr); 312 } 313 314 static const struct spdk_json_object_decoder rpc_vhost_remove_dev[] = { 315 {"ctrlr", offsetof(struct rpc_remove_vhost_scsi_ctrlr_dev, ctrlr), spdk_json_decode_string }, 316 {"scsi_dev_num", offsetof(struct rpc_remove_vhost_scsi_ctrlr_dev, scsi_dev_num), spdk_json_decode_uint32}, 317 }; 318 319 static void 320 spdk_rpc_remove_vhost_scsi_dev(struct spdk_jsonrpc_server_conn *conn, 321 const struct spdk_json_val *params, 322 const struct spdk_json_val *id) 323 { 324 struct rpc_remove_vhost_scsi_ctrlr_dev req = {0}; 325 struct spdk_json_write_ctx *w; 326 struct spdk_vhost_scsi_ctrlr *vdev; 327 int rc; 328 329 if (spdk_json_decode_object(params, rpc_vhost_remove_dev, 330 SPDK_COUNTOF(rpc_vhost_remove_dev), 331 &req)) { 332 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n"); 333 rc = -EINVAL; 334 goto invalid; 335 } 336 337 if (!(vdev = spdk_vhost_scsi_ctrlr_find(req.ctrlr))) { 338 rc = -ENODEV; 339 goto invalid; 340 } 341 342 rc = spdk_vhost_scsi_ctrlr_remove_dev(vdev, req.scsi_dev_num); 343 if (rc < 0) { 344 goto invalid; 345 } 346 347 free_rpc_remove_vhost_scsi_ctrlr_dev(&req); 348 349 if (id != NULL) { 350 w = spdk_jsonrpc_begin_result(conn, id); 351 spdk_json_write_bool(w, true); 352 spdk_jsonrpc_end_result(conn, w); 353 } 354 355 return; 356 invalid: 357 free_rpc_remove_vhost_scsi_ctrlr_dev(&req); 358 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, strerror(-rc)); 359 } 360 SPDK_RPC_REGISTER("remove_vhost_scsi_dev", spdk_rpc_remove_vhost_scsi_dev) 361