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_add_vhost_scsi_ctrlr_lun { 190 char *ctrlr; 191 uint32_t scsi_dev_num; 192 char *lun_name; 193 }; 194 195 static void 196 free_rpc_add_vhost_scsi_ctrlr_lun(struct rpc_add_vhost_scsi_ctrlr_lun *req) 197 { 198 free(req->ctrlr); 199 free(req->lun_name); 200 } 201 202 static const struct spdk_json_object_decoder rpc_vhost_add_lun[] = { 203 {"ctrlr", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, ctrlr), spdk_json_decode_string }, 204 {"scsi_dev_num", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, scsi_dev_num), spdk_json_decode_uint32}, 205 {"lun_name", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, lun_name), spdk_json_decode_string }, 206 }; 207 208 static void 209 spdk_rpc_add_vhost_scsi_lun(struct spdk_jsonrpc_server_conn *conn, 210 const struct spdk_json_val *params, 211 const struct spdk_json_val *id) 212 { 213 struct rpc_add_vhost_scsi_ctrlr_lun req = {0}; 214 struct spdk_json_write_ctx *w; 215 int rc; 216 217 if (spdk_json_decode_object(params, rpc_vhost_add_lun, 218 SPDK_COUNTOF(rpc_vhost_add_lun), 219 &req)) { 220 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n"); 221 rc = -EINVAL; 222 goto invalid; 223 } 224 225 rc = spdk_vhost_scsi_ctrlr_add_dev(req.ctrlr, req.scsi_dev_num, req.lun_name); 226 if (rc < 0) { 227 goto invalid; 228 } 229 230 free_rpc_add_vhost_scsi_ctrlr_lun(&req); 231 232 w = spdk_jsonrpc_begin_result(conn, id); 233 spdk_json_write_bool(w, true); 234 spdk_jsonrpc_end_result(conn, w); 235 return; 236 invalid: 237 free_rpc_add_vhost_scsi_ctrlr_lun(&req); 238 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, strerror(-rc)); 239 } 240 SPDK_RPC_REGISTER("add_vhost_scsi_lun", spdk_rpc_add_vhost_scsi_lun) 241