1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 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/conf.h" 37 #include "spdk/io_channel.h" 38 #include "spdk/nvmf.h" 39 #include "spdk/trace.h" 40 41 #include "spdk_internal/log.h" 42 43 #include "nvmf_internal.h" 44 #include "transport.h" 45 46 SPDK_LOG_REGISTER_TRACE_FLAG("nvmf", SPDK_TRACE_NVMF) 47 48 #define MAX_SUBSYSTEMS 4 49 50 #define SPDK_NVMF_DEFAULT_MAX_QUEUE_DEPTH 128 51 #define SPDK_NVMF_DEFAULT_MAX_QPAIRS_PER_CTRLR 64 52 #define SPDK_NVMF_DEFAULT_IN_CAPSULE_DATA_SIZE 4096 53 #define SPDK_NVMF_DEFAULT_MAX_IO_SIZE 131072 54 55 void 56 spdk_nvmf_tgt_opts_init(struct spdk_nvmf_tgt_opts *opts) 57 { 58 opts->max_queue_depth = SPDK_NVMF_DEFAULT_MAX_QUEUE_DEPTH; 59 opts->max_qpairs_per_ctrlr = SPDK_NVMF_DEFAULT_MAX_QPAIRS_PER_CTRLR; 60 opts->in_capsule_data_size = SPDK_NVMF_DEFAULT_IN_CAPSULE_DATA_SIZE; 61 opts->max_io_size = SPDK_NVMF_DEFAULT_MAX_IO_SIZE; 62 } 63 64 struct spdk_nvmf_tgt * 65 spdk_nvmf_tgt_create(struct spdk_nvmf_tgt_opts *opts) 66 { 67 struct spdk_nvmf_tgt *tgt; 68 69 tgt = calloc(1, sizeof(*tgt)); 70 if (!tgt) { 71 return NULL; 72 } 73 74 if (!opts) { 75 spdk_nvmf_tgt_opts_init(&tgt->opts); 76 } else { 77 tgt->opts = *opts; 78 } 79 80 tgt->master_thread = spdk_get_thread(); 81 if (!tgt->master_thread) { 82 free(tgt); 83 SPDK_ERRLOG("Call spdk_allocate_thread() prior to calling spdk_nvmf_tgt_create()\n"); 84 return NULL; 85 } 86 87 tgt->discovery_genctr = 0; 88 tgt->discovery_log_page = NULL; 89 tgt->discovery_log_page_size = 0; 90 TAILQ_INIT(&tgt->subsystems); 91 TAILQ_INIT(&tgt->transports); 92 93 SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Max Queue Pairs Per Controller: %d\n", 94 tgt->opts.max_qpairs_per_ctrlr); 95 SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Max Queue Depth: %d\n", tgt->opts.max_queue_depth); 96 SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Max In Capsule Data: %d bytes\n", 97 tgt->opts.in_capsule_data_size); 98 SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Max I/O Size: %d bytes\n", tgt->opts.max_io_size); 99 100 return tgt; 101 } 102 103 void 104 spdk_nvmf_tgt_destroy(struct spdk_nvmf_tgt *tgt) 105 { 106 struct spdk_nvmf_transport *transport, *transport_tmp; 107 108 TAILQ_FOREACH_SAFE(transport, &tgt->transports, link, transport_tmp) { 109 TAILQ_REMOVE(&tgt->transports, transport, link); 110 spdk_nvmf_transport_destroy(transport); 111 } 112 113 if (tgt->discovery_log_page) { 114 free(tgt->discovery_log_page); 115 } 116 free(tgt); 117 } 118 119 int 120 spdk_nvmf_tgt_listen(struct spdk_nvmf_tgt *tgt, 121 struct spdk_nvme_transport_id *trid) 122 { 123 struct spdk_nvmf_transport *transport; 124 int rc; 125 126 transport = spdk_nvmf_tgt_get_transport(tgt, trid->trtype); 127 if (!transport) { 128 transport = spdk_nvmf_transport_create(tgt, trid->trtype); 129 if (!transport) { 130 SPDK_ERRLOG("Transport initialization failed\n"); 131 return -EINVAL; 132 } 133 TAILQ_INSERT_TAIL(&tgt->transports, transport, link); 134 } 135 136 137 rc = spdk_nvmf_transport_listen(transport, trid); 138 if (rc < 0) { 139 SPDK_ERRLOG("Unable to listen on address '%s'\n", trid->traddr); 140 return -EINVAL; 141 } 142 143 tgt->discovery_genctr++; 144 145 return 0; 146 } 147 148 struct spdk_nvmf_subsystem * 149 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn) 150 { 151 struct spdk_nvmf_subsystem *subsystem; 152 153 if (!subnqn) { 154 return NULL; 155 } 156 157 TAILQ_FOREACH(subsystem, &tgt->subsystems, entries) { 158 if (strcmp(subnqn, subsystem->subnqn) == 0) { 159 return subsystem; 160 } 161 } 162 163 return NULL; 164 } 165 166 struct spdk_nvmf_transport * 167 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, enum spdk_nvme_transport_type type) 168 { 169 struct spdk_nvmf_transport *transport; 170 171 TAILQ_FOREACH(transport, &tgt->transports, link) { 172 if (transport->ops->type == type) { 173 return transport; 174 } 175 } 176 177 return NULL; 178 } 179 180 void 181 spdk_nvmf_tgt_accept(struct spdk_nvmf_tgt *tgt) 182 { 183 struct spdk_nvmf_transport *transport, *tmp; 184 185 TAILQ_FOREACH_SAFE(transport, &tgt->transports, link, tmp) { 186 spdk_nvmf_transport_accept(transport); 187 } 188 } 189 190 struct spdk_nvmf_poll_group * 191 spdk_nvmf_poll_group_create(struct spdk_nvmf_tgt *tgt) 192 { 193 struct spdk_nvmf_poll_group *group; 194 struct spdk_nvmf_transport *transport; 195 struct spdk_nvmf_transport_poll_group *tgroup; 196 197 group = calloc(1, sizeof(*group)); 198 if (!group) { 199 return NULL; 200 } 201 202 TAILQ_INIT(&group->tgroups); 203 204 TAILQ_FOREACH(transport, &tgt->transports, link) { 205 tgroup = spdk_nvmf_transport_poll_group_create(transport); 206 if (!tgroup) { 207 SPDK_ERRLOG("Unable to create poll group for transport\n"); 208 continue; 209 } 210 211 TAILQ_INSERT_TAIL(&group->tgroups, tgroup, link); 212 } 213 214 return group; 215 } 216 217 void 218 spdk_nvmf_poll_group_destroy(struct spdk_nvmf_poll_group *group) 219 { 220 struct spdk_nvmf_transport_poll_group *tgroup, *tmp; 221 222 TAILQ_FOREACH_SAFE(tgroup, &group->tgroups, link, tmp) { 223 TAILQ_REMOVE(&group->tgroups, tgroup, link); 224 spdk_nvmf_transport_poll_group_destroy(tgroup); 225 } 226 227 free(group); 228 } 229 230 int 231 spdk_nvmf_poll_group_add(struct spdk_nvmf_poll_group *group, 232 struct spdk_nvmf_qpair *qpair) 233 { 234 int rc = -1; 235 struct spdk_nvmf_transport_poll_group *tgroup; 236 237 TAILQ_FOREACH(tgroup, &group->tgroups, link) { 238 if (tgroup->transport == qpair->transport) { 239 rc = spdk_nvmf_transport_poll_group_add(tgroup, qpair); 240 break; 241 } 242 } 243 244 return rc; 245 } 246 247 int 248 spdk_nvmf_poll_group_remove(struct spdk_nvmf_poll_group *group, 249 struct spdk_nvmf_qpair *qpair) 250 { 251 int rc = -1; 252 struct spdk_nvmf_transport_poll_group *tgroup; 253 254 TAILQ_FOREACH(tgroup, &group->tgroups, link) { 255 if (tgroup->transport == qpair->transport) { 256 rc = spdk_nvmf_transport_poll_group_remove(tgroup, qpair); 257 break; 258 } 259 } 260 261 return rc; 262 } 263 264 int 265 spdk_nvmf_poll_group_poll(struct spdk_nvmf_poll_group *group) 266 { 267 int rc; 268 int count = 0; 269 struct spdk_nvmf_transport_poll_group *tgroup; 270 271 TAILQ_FOREACH(tgroup, &group->tgroups, link) { 272 rc = spdk_nvmf_transport_poll_group_poll(tgroup); 273 if (rc < 0) { 274 return rc; 275 } 276 count += rc; 277 break; 278 } 279 280 return count; 281 } 282 283 SPDK_TRACE_REGISTER_FN(nvmf_trace) 284 { 285 spdk_trace_register_object(OBJECT_NVMF_IO, 'r'); 286 spdk_trace_register_description("NVMF_IO_START", "", TRACE_NVMF_IO_START, 287 OWNER_NONE, OBJECT_NVMF_IO, 1, 0, 0, ""); 288 spdk_trace_register_description("NVMF_RDMA_READ_START", "", TRACE_RDMA_READ_START, 289 OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, ""); 290 spdk_trace_register_description("NVMF_RDMA_WRITE_START", "", TRACE_RDMA_WRITE_START, 291 OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, ""); 292 spdk_trace_register_description("NVMF_RDMA_READ_COMPLETE", "", TRACE_RDMA_READ_COMPLETE, 293 OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, ""); 294 spdk_trace_register_description("NVMF_RDMA_WRITE_COMPLETE", "", TRACE_RDMA_WRITE_COMPLETE, 295 OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, ""); 296 spdk_trace_register_description("NVMF_LIB_READ_START", "", TRACE_NVMF_LIB_READ_START, 297 OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, ""); 298 spdk_trace_register_description("NVMF_LIB_WRITE_START", "", TRACE_NVMF_LIB_WRITE_START, 299 OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, ""); 300 spdk_trace_register_description("NVMF_LIB_COMPLETE", "", TRACE_NVMF_LIB_COMPLETE, 301 OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, ""); 302 spdk_trace_register_description("NVMF_IO_COMPLETION_DONE", "", TRACE_NVMF_IO_COMPLETE, 303 OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, ""); 304 } 305