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 <errno.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; 47 48 spdk_json_write_name(ctx, "id"); 49 spdk_json_write_int32(ctx, (int32_t)dev->id); 50 51 spdk_json_write_name(ctx, "device_name"); 52 spdk_json_write_string(ctx, dev->name); 53 54 spdk_json_write_name(ctx, "luns"); 55 spdk_json_write_array_begin(ctx); 56 for (l = 0; l < dev->maxlun; l++) { 57 if (NULL == dev->lun[l]) 58 continue; 59 60 spdk_json_write_object_begin(ctx); 61 62 spdk_json_write_name(ctx, "id"); 63 spdk_json_write_int32(ctx, (int32_t)dev->lun[l]->id); 64 65 spdk_json_write_name(ctx, "name"); 66 spdk_json_write_string(ctx, dev->lun[l]->name); 67 68 spdk_json_write_object_end(ctx); 69 } 70 spdk_json_write_array_end(ctx); 71 } 72 73 static void 74 spdk_rpc_get_vhost_scsi_controllers(struct spdk_jsonrpc_server_conn *conn, 75 const struct spdk_json_val *params, 76 const struct spdk_json_val *id) 77 { 78 struct spdk_json_write_ctx *w; 79 struct spdk_vhost_scsi_ctrlr *ctrlr = NULL; 80 struct spdk_scsi_dev *dev; 81 uint32_t i; 82 char buf[32]; 83 84 if (params != NULL) { 85 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 86 "get_vhost_scsi_controllers requires no parameters"); 87 return; 88 } 89 90 w = spdk_jsonrpc_begin_result(conn, id); 91 spdk_json_write_array_begin(w); 92 while ((ctrlr = spdk_vhost_scsi_ctrlr_next(ctrlr)) != NULL) { 93 spdk_json_write_object_begin(w); 94 95 spdk_json_write_name(w, "ctrlr"); 96 spdk_json_write_string(w, spdk_vhost_scsi_ctrlr_get_name(ctrlr)); 97 98 spdk_json_write_name(w, "cpu_mask"); 99 snprintf(buf, sizeof(buf), "%#" PRIx64, spdk_vhost_scsi_ctrlr_get_cpumask(ctrlr)); 100 spdk_json_write_string(w, buf); 101 102 spdk_json_write_name(w, "scsi_devs"); 103 spdk_json_write_array_begin(w); 104 105 for (i = 0; i < SPDK_VHOST_SCSI_CTRLR_MAX_DEVS; i++) { 106 dev = spdk_vhost_scsi_ctrlr_get_dev(ctrlr, i); 107 if (!dev) 108 continue; 109 110 spdk_json_write_object_begin(w); 111 spdk_json_write_name(w, "scsi_dev_num"); 112 spdk_json_write_uint32(w, i); 113 json_scsi_dev_write(w, dev); 114 spdk_json_write_object_end(w); 115 } 116 117 spdk_json_write_array_end(w); // devs 118 119 spdk_json_write_object_end(w); // ctrl 120 } 121 spdk_json_write_array_end(w); 122 spdk_jsonrpc_end_result(conn, w); 123 return; 124 } 125 SPDK_RPC_REGISTER("get_vhost_scsi_controllers", spdk_rpc_get_vhost_scsi_controllers) 126 127 struct rpc_vhost_scsi_ctrlr { 128 char *ctrlr; 129 char *cpumask; 130 }; 131 132 static void 133 free_rpc_vhost_scsi_ctrlr(struct rpc_vhost_scsi_ctrlr *req) 134 { 135 free(req->ctrlr); 136 free(req->cpumask); 137 } 138 139 static const struct spdk_json_object_decoder rpc_construct_vhost_ctrlr[] = { 140 {"ctrlr", offsetof(struct rpc_vhost_scsi_ctrlr, ctrlr), spdk_json_decode_string }, 141 {"cpumask", offsetof(struct rpc_vhost_scsi_ctrlr, cpumask), spdk_json_decode_string, true}, 142 }; 143 144 static void 145 spdk_rpc_construct_vhost_scsi_controller(struct spdk_jsonrpc_server_conn *conn, 146 const struct spdk_json_val *params, 147 const struct spdk_json_val *id) 148 { 149 struct rpc_vhost_scsi_ctrlr req = {0}; 150 struct spdk_json_write_ctx *w; 151 int rc; 152 uint64_t cpumask; 153 154 if (spdk_json_decode_object(params, rpc_construct_vhost_ctrlr, 155 SPDK_COUNTOF(rpc_construct_vhost_ctrlr), 156 &req)) { 157 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n"); 158 rc = -EINVAL; 159 goto invalid; 160 } 161 162 cpumask = spdk_app_get_core_mask(); 163 if (req.cpumask != NULL && spdk_vhost_parse_core_mask(req.cpumask, &cpumask)) { 164 rc = -EINVAL; 165 goto invalid; 166 } 167 168 rc = spdk_vhost_scsi_ctrlr_construct(req.ctrlr, cpumask); 169 if (rc < 0) { 170 goto invalid; 171 } 172 173 free_rpc_vhost_scsi_ctrlr(&req); 174 175 w = spdk_jsonrpc_begin_result(conn, id); 176 spdk_json_write_bool(w, true); 177 spdk_jsonrpc_end_result(conn, w); 178 return; 179 invalid: 180 free_rpc_vhost_scsi_ctrlr(&req); 181 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, strerror(-rc)); 182 } 183 SPDK_RPC_REGISTER("construct_vhost_scsi_controller", spdk_rpc_construct_vhost_scsi_controller) 184 185 struct rpc_add_vhost_scsi_ctrlr_lun { 186 char *ctrlr; 187 uint32_t scsi_dev_num; 188 char *lun_name; 189 }; 190 191 static void 192 free_rpc_add_vhost_scsi_ctrlr_lun(struct rpc_add_vhost_scsi_ctrlr_lun *req) 193 { 194 free(req->ctrlr); 195 free(req->lun_name); 196 } 197 198 static const struct spdk_json_object_decoder rpc_vhost_add_lun[] = { 199 {"ctrlr", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, ctrlr), spdk_json_decode_string }, 200 {"scsi_dev_num", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, scsi_dev_num), spdk_json_decode_uint32}, 201 {"lun_name", offsetof(struct rpc_add_vhost_scsi_ctrlr_lun, lun_name), spdk_json_decode_string }, 202 }; 203 204 static void 205 spdk_rpc_add_vhost_scsi_lun(struct spdk_jsonrpc_server_conn *conn, 206 const struct spdk_json_val *params, 207 const struct spdk_json_val *id) 208 { 209 struct rpc_add_vhost_scsi_ctrlr_lun req = {0}; 210 struct spdk_json_write_ctx *w; 211 int rc; 212 213 if (spdk_json_decode_object(params, rpc_vhost_add_lun, 214 SPDK_COUNTOF(rpc_vhost_add_lun), 215 &req)) { 216 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n"); 217 rc = -EINVAL; 218 goto invalid; 219 } 220 221 rc = spdk_vhost_scsi_ctrlr_add_dev(req.ctrlr, req.scsi_dev_num, req.lun_name); 222 if (rc < 0) { 223 goto invalid; 224 } 225 226 free_rpc_add_vhost_scsi_ctrlr_lun(&req); 227 228 w = spdk_jsonrpc_begin_result(conn, id); 229 spdk_json_write_bool(w, true); 230 spdk_jsonrpc_end_result(conn, w); 231 return; 232 invalid: 233 free_rpc_add_vhost_scsi_ctrlr_lun(&req); 234 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, strerror(-rc)); 235 } 236 SPDK_RPC_REGISTER("add_vhost_scsi_lun", spdk_rpc_add_vhost_scsi_lun) 237