1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2016 Intel Corporation. All rights reserved. 3 * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5 */ 6 7 #ifndef __NVMF_INTERNAL_H__ 8 #define __NVMF_INTERNAL_H__ 9 10 #include "spdk/stdinc.h" 11 12 #include "spdk/keyring.h" 13 #include "spdk/likely.h" 14 #include "spdk/nvmf.h" 15 #include "spdk/nvmf_cmd.h" 16 #include "spdk/nvmf_transport.h" 17 #include "spdk/nvmf_spec.h" 18 #include "spdk/assert.h" 19 #include "spdk/bdev.h" 20 #include "spdk/queue.h" 21 #include "spdk/util.h" 22 #include "spdk/thread.h" 23 #include "spdk/tree.h" 24 #include "spdk/bit_array.h" 25 26 /* The spec reserves cntlid values in the range FFF0h to FFFFh. */ 27 #define NVMF_MIN_CNTLID 1 28 #define NVMF_MAX_CNTLID 0xFFEF 29 30 enum spdk_nvmf_tgt_state { 31 NVMF_TGT_IDLE = 0, 32 NVMF_TGT_RUNNING, 33 NVMF_TGT_PAUSING, 34 NVMF_TGT_PAUSED, 35 NVMF_TGT_RESUMING, 36 }; 37 38 enum spdk_nvmf_subsystem_state { 39 SPDK_NVMF_SUBSYSTEM_INACTIVE = 0, 40 SPDK_NVMF_SUBSYSTEM_ACTIVATING, 41 SPDK_NVMF_SUBSYSTEM_ACTIVE, 42 SPDK_NVMF_SUBSYSTEM_PAUSING, 43 SPDK_NVMF_SUBSYSTEM_PAUSED, 44 SPDK_NVMF_SUBSYSTEM_RESUMING, 45 SPDK_NVMF_SUBSYSTEM_DEACTIVATING, 46 SPDK_NVMF_SUBSYSTEM_NUM_STATES, 47 }; 48 49 RB_HEAD(subsystem_tree, spdk_nvmf_subsystem); 50 51 struct spdk_nvmf_tgt { 52 char name[NVMF_TGT_NAME_MAX_LENGTH]; 53 54 pthread_mutex_t mutex; 55 56 uint64_t discovery_genctr; 57 58 uint32_t max_subsystems; 59 60 uint32_t discovery_filter; 61 62 enum spdk_nvmf_tgt_state state; 63 64 struct spdk_bit_array *subsystem_ids; 65 66 struct subsystem_tree subsystems; 67 68 TAILQ_HEAD(, spdk_nvmf_transport) transports; 69 TAILQ_HEAD(, spdk_nvmf_poll_group) poll_groups; 70 TAILQ_HEAD(, spdk_nvmf_referral) referrals; 71 72 /* Used for round-robin assignment of connections to poll groups */ 73 struct spdk_nvmf_poll_group *next_poll_group; 74 75 spdk_nvmf_tgt_destroy_done_fn *destroy_cb_fn; 76 void *destroy_cb_arg; 77 78 uint16_t crdt[3]; 79 uint16_t num_poll_groups; 80 81 /* Allowed DH-HMAC-CHAP digests/dhgroups */ 82 uint32_t dhchap_digests; 83 uint32_t dhchap_dhgroups; 84 85 TAILQ_ENTRY(spdk_nvmf_tgt) link; 86 }; 87 88 struct spdk_nvmf_host { 89 char nqn[SPDK_NVMF_NQN_MAX_LEN + 1]; 90 struct spdk_key *dhchap_key; 91 struct spdk_key *dhchap_ctrlr_key; 92 TAILQ_ENTRY(spdk_nvmf_host) link; 93 }; 94 95 struct spdk_nvmf_subsystem_listener { 96 struct spdk_nvmf_subsystem *subsystem; 97 spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn; 98 void *cb_arg; 99 struct spdk_nvme_transport_id *trid; 100 struct spdk_nvmf_transport *transport; 101 enum spdk_nvme_ana_state *ana_state; 102 uint64_t ana_state_change_count; 103 uint16_t id; 104 struct spdk_nvmf_listener_opts opts; 105 TAILQ_ENTRY(spdk_nvmf_subsystem_listener) link; 106 }; 107 108 struct spdk_nvmf_referral { 109 /* Discovery Log Page Entry for this referral */ 110 struct spdk_nvmf_discovery_log_page_entry entry; 111 /* Transport ID */ 112 struct spdk_nvme_transport_id trid; 113 TAILQ_ENTRY(spdk_nvmf_referral) link; 114 }; 115 116 struct spdk_nvmf_subsystem_pg_ns_info { 117 struct spdk_io_channel *channel; 118 struct spdk_uuid uuid; 119 /* current reservation key, no reservation if the value is 0 */ 120 uint64_t crkey; 121 /* reservation type */ 122 enum spdk_nvme_reservation_type rtype; 123 /* Host ID which holds the reservation */ 124 struct spdk_uuid holder_id; 125 /* Host ID for the registrants with the namespace */ 126 struct spdk_uuid reg_hostid[SPDK_NVMF_MAX_NUM_REGISTRANTS]; 127 uint64_t num_blocks; 128 129 /* I/O outstanding to this namespace */ 130 uint64_t io_outstanding; 131 enum spdk_nvmf_subsystem_state state; 132 }; 133 134 typedef void(*spdk_nvmf_poll_group_mod_done)(void *cb_arg, int status); 135 136 struct spdk_nvmf_subsystem_poll_group { 137 /* Array of namespace information for each namespace indexed by nsid - 1 */ 138 struct spdk_nvmf_subsystem_pg_ns_info *ns_info; 139 uint32_t num_ns; 140 enum spdk_nvmf_subsystem_state state; 141 142 /* Number of ADMIN and FABRICS requests outstanding */ 143 uint64_t mgmt_io_outstanding; 144 spdk_nvmf_poll_group_mod_done cb_fn; 145 void *cb_arg; 146 147 TAILQ_HEAD(, spdk_nvmf_request) queued; 148 }; 149 150 struct spdk_nvmf_registrant { 151 TAILQ_ENTRY(spdk_nvmf_registrant) link; 152 struct spdk_uuid hostid; 153 /* Registration key */ 154 uint64_t rkey; 155 }; 156 157 struct spdk_nvmf_ns { 158 uint32_t nsid; 159 uint32_t anagrpid; 160 struct spdk_nvmf_subsystem *subsystem; 161 struct spdk_bdev *bdev; 162 struct spdk_bdev_desc *desc; 163 struct spdk_nvmf_ns_opts opts; 164 /* reservation notification mask */ 165 uint32_t mask; 166 /* generation code */ 167 uint32_t gen; 168 /* registrants head */ 169 TAILQ_HEAD(, spdk_nvmf_registrant) registrants; 170 /* current reservation key */ 171 uint64_t crkey; 172 /* reservation type */ 173 enum spdk_nvme_reservation_type rtype; 174 /* current reservation holder, only valid if reservation type can only have one holder */ 175 struct spdk_nvmf_registrant *holder; 176 /* Persist Through Power Loss file which contains the persistent reservation */ 177 char *ptpl_file; 178 /* Persist Through Power Loss feature is enabled */ 179 bool ptpl_activated; 180 /* ZCOPY supported on bdev device */ 181 bool zcopy; 182 /* Command Set Identifier */ 183 enum spdk_nvme_csi csi; 184 /* Make namespace visible to controllers of these hosts */ 185 TAILQ_HEAD(, spdk_nvmf_host) hosts; 186 /* Namespace is always visible to all controllers */ 187 bool always_visible; 188 /* Namespace id of the underlying device, used for passthrough commands */ 189 uint32_t passthrough_nsid; 190 }; 191 192 /* 193 * NVMf reservation notification log page. 194 */ 195 struct spdk_nvmf_reservation_log { 196 struct spdk_nvme_reservation_notification_log log; 197 TAILQ_ENTRY(spdk_nvmf_reservation_log) link; 198 struct spdk_nvmf_ctrlr *ctrlr; 199 }; 200 201 /* 202 * NVMf async event completion. 203 */ 204 struct spdk_nvmf_async_event_completion { 205 union spdk_nvme_async_event_completion event; 206 STAILQ_ENTRY(spdk_nvmf_async_event_completion) link; 207 }; 208 209 /* 210 * This structure represents an NVMe-oF controller, 211 * which is like a "session" in networking terms. 212 */ 213 struct spdk_nvmf_ctrlr { 214 uint16_t cntlid; 215 char hostnqn[SPDK_NVMF_NQN_MAX_LEN + 1]; 216 struct spdk_nvmf_subsystem *subsys; 217 struct spdk_bit_array *visible_ns; 218 219 struct spdk_nvmf_ctrlr_data cdata; 220 221 struct spdk_nvmf_registers vcprop; 222 223 struct spdk_nvmf_ctrlr_feat feat; 224 225 struct spdk_nvmf_qpair *admin_qpair; 226 struct spdk_thread *thread; 227 struct spdk_bit_array *qpair_mask; 228 229 const struct spdk_nvmf_subsystem_listener *listener; 230 231 struct spdk_nvmf_request *aer_req[SPDK_NVMF_MAX_ASYNC_EVENTS]; 232 STAILQ_HEAD(, spdk_nvmf_async_event_completion) async_events; 233 uint64_t notice_aen_mask; 234 uint8_t nr_aer_reqs; 235 struct spdk_uuid hostid; 236 237 uint32_t association_timeout; /* in milliseconds */ 238 uint16_t changed_ns_list_count; 239 struct spdk_nvme_ns_list changed_ns_list; 240 uint64_t log_page_count; 241 uint8_t num_avail_log_pages; 242 TAILQ_HEAD(log_page_head, spdk_nvmf_reservation_log) log_head; 243 244 /* Time to trigger keep-alive--poller_time = now_tick + period */ 245 uint64_t last_keep_alive_tick; 246 struct spdk_poller *keep_alive_poller; 247 248 struct spdk_poller *association_timer; 249 250 struct spdk_poller *cc_timer; 251 uint64_t cc_timeout_tsc; 252 struct spdk_poller *cc_timeout_timer; 253 254 bool dif_insert_or_strip; 255 bool in_destruct; 256 bool disconnect_in_progress; 257 /* valid only when disconnect_in_progress is true */ 258 bool disconnect_is_shn; 259 bool acre_enabled; 260 bool dynamic_ctrlr; 261 /* LBA Format Extension Enabled (LBAFEE) */ 262 bool lbafee_enabled; 263 264 TAILQ_ENTRY(spdk_nvmf_ctrlr) link; 265 }; 266 267 #define NVMF_MAX_LISTENERS_PER_SUBSYSTEM 16 268 269 struct nvmf_subsystem_state_change_ctx { 270 struct spdk_nvmf_subsystem *subsystem; 271 uint16_t nsid; 272 273 enum spdk_nvmf_subsystem_state original_state; 274 enum spdk_nvmf_subsystem_state requested_state; 275 int status; 276 struct spdk_thread *thread; 277 278 spdk_nvmf_subsystem_state_change_done cb_fn; 279 void *cb_arg; 280 TAILQ_ENTRY(nvmf_subsystem_state_change_ctx) link; 281 }; 282 283 struct spdk_nvmf_subsystem { 284 struct spdk_thread *thread; 285 286 uint32_t id; 287 288 enum spdk_nvmf_subsystem_state state; 289 enum spdk_nvmf_subtype subtype; 290 291 uint16_t next_cntlid; 292 struct { 293 uint8_t allow_any_listener : 1; 294 uint8_t ana_reporting : 1; 295 uint8_t reserved : 6; 296 } flags; 297 298 /* Protected against concurrent access by ->mutex */ 299 bool allow_any_host; 300 301 bool destroying; 302 bool async_destroy; 303 304 /* FDP related fields */ 305 bool fdp_supported; 306 307 /* Zoned storage related fields */ 308 uint64_t max_zone_append_size_kib; 309 310 struct spdk_nvmf_tgt *tgt; 311 RB_ENTRY(spdk_nvmf_subsystem) link; 312 313 /* Array of pointers to namespaces of size max_nsid indexed by nsid - 1 */ 314 struct spdk_nvmf_ns **ns; 315 uint32_t max_nsid; 316 317 uint16_t min_cntlid; 318 uint16_t max_cntlid; 319 320 uint64_t max_discard_size_kib; 321 uint64_t max_write_zeroes_size_kib; 322 323 TAILQ_HEAD(, spdk_nvmf_ctrlr) ctrlrs; 324 325 /* This mutex is used to protect fields that aren't touched on the I/O path (e.g. it's 326 * needed for handling things like the CONNECT command) instead of requiring the subsystem 327 * to be paused. It makes it possible to modify those fields (e.g. add/remove hosts) 328 * without affecting outstanding I/O requests. 329 */ 330 pthread_mutex_t mutex; 331 /* Protected against concurrent access by ->mutex */ 332 TAILQ_HEAD(, spdk_nvmf_host) hosts; 333 TAILQ_HEAD(, spdk_nvmf_subsystem_listener) listeners; 334 struct spdk_bit_array *used_listener_ids; 335 336 TAILQ_ENTRY(spdk_nvmf_subsystem) entries; 337 338 nvmf_subsystem_destroy_cb async_destroy_cb; 339 void *async_destroy_cb_arg; 340 341 char sn[SPDK_NVME_CTRLR_SN_LEN + 1]; 342 char mn[SPDK_NVME_CTRLR_MN_LEN + 1]; 343 char subnqn[SPDK_NVMF_NQN_MAX_LEN + 1]; 344 345 /* Array of namespace count per ANA group of size max_nsid indexed anagrpid - 1 346 * It will be enough for ANA group to use the same size as namespaces. 347 */ 348 uint32_t *ana_group; 349 /* Queue of a state change requests */ 350 TAILQ_HEAD(, nvmf_subsystem_state_change_ctx) state_changes; 351 /* In-band authentication sequence number, protected by ->mutex */ 352 uint32_t auth_seqnum; 353 bool passthrough; 354 }; 355 356 static int 357 subsystem_cmp(struct spdk_nvmf_subsystem *subsystem1, struct spdk_nvmf_subsystem *subsystem2) 358 { 359 return strncmp(subsystem1->subnqn, subsystem2->subnqn, sizeof(subsystem1->subnqn)); 360 } 361 362 RB_GENERATE_STATIC(subsystem_tree, spdk_nvmf_subsystem, link, subsystem_cmp); 363 364 int nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group, 365 struct spdk_nvmf_subsystem *subsystem); 366 int nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group, 367 struct spdk_nvmf_subsystem *subsystem, 368 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg); 369 void nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, 370 struct spdk_nvmf_subsystem *subsystem, spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg); 371 void nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group, 372 struct spdk_nvmf_subsystem *subsystem, 373 uint32_t nsid, 374 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg); 375 void nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group, 376 struct spdk_nvmf_subsystem *subsystem, spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg); 377 378 void nvmf_update_discovery_log(struct spdk_nvmf_tgt *tgt, const char *hostnqn); 379 void nvmf_get_discovery_log_page(struct spdk_nvmf_tgt *tgt, const char *hostnqn, struct iovec *iov, 380 uint32_t iovcnt, uint64_t offset, uint32_t length, 381 struct spdk_nvme_transport_id *cmd_source_trid); 382 383 void nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr); 384 int nvmf_ctrlr_process_admin_cmd(struct spdk_nvmf_request *req); 385 int nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req); 386 bool nvmf_ctrlr_dsm_supported(struct spdk_nvmf_ctrlr *ctrlr); 387 bool nvmf_ctrlr_write_zeroes_supported(struct spdk_nvmf_ctrlr *ctrlr); 388 bool nvmf_ctrlr_copy_supported(struct spdk_nvmf_ctrlr *ctrlr); 389 void nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid); 390 bool nvmf_ctrlr_use_zcopy(struct spdk_nvmf_request *req); 391 392 void nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *nsdata, 393 bool dif_insert_or_strip); 394 void nvmf_bdev_ctrlr_identify_iocs_nvm(struct spdk_nvmf_ns *ns, 395 struct spdk_nvme_nvm_ns_data *nsdata_nvm); 396 int nvmf_bdev_ctrlr_read_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 397 struct spdk_io_channel *ch, struct spdk_nvmf_request *req); 398 int nvmf_bdev_ctrlr_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 399 struct spdk_io_channel *ch, struct spdk_nvmf_request *req); 400 int nvmf_bdev_ctrlr_compare_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 401 struct spdk_io_channel *ch, struct spdk_nvmf_request *req); 402 int nvmf_bdev_ctrlr_compare_and_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 403 struct spdk_io_channel *ch, struct spdk_nvmf_request *cmp_req, struct spdk_nvmf_request *write_req); 404 int nvmf_bdev_ctrlr_write_zeroes_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 405 struct spdk_io_channel *ch, struct spdk_nvmf_request *req); 406 int nvmf_bdev_ctrlr_flush_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 407 struct spdk_io_channel *ch, struct spdk_nvmf_request *req); 408 int nvmf_bdev_ctrlr_dsm_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 409 struct spdk_io_channel *ch, struct spdk_nvmf_request *req); 410 int nvmf_bdev_ctrlr_copy_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 411 struct spdk_io_channel *ch, struct spdk_nvmf_request *req); 412 int nvmf_bdev_ctrlr_nvme_passthru_io(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 413 struct spdk_io_channel *ch, struct spdk_nvmf_request *req); 414 bool nvmf_bdev_ctrlr_get_dif_ctx(struct spdk_bdev *bdev, struct spdk_nvme_cmd *cmd, 415 struct spdk_dif_ctx *dif_ctx); 416 bool nvmf_bdev_zcopy_enabled(struct spdk_bdev *bdev); 417 418 int nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, 419 struct spdk_nvmf_ctrlr *ctrlr); 420 void nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem, 421 struct spdk_nvmf_ctrlr *ctrlr); 422 void nvmf_subsystem_remove_all_listeners(struct spdk_nvmf_subsystem *subsystem, 423 bool stop); 424 struct spdk_nvmf_ctrlr *nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, 425 uint16_t cntlid); 426 bool nvmf_subsystem_host_auth_required(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn); 427 enum nvmf_auth_key_type { 428 NVMF_AUTH_KEY_HOST, 429 NVMF_AUTH_KEY_CTRLR, 430 }; 431 struct spdk_key *nvmf_subsystem_get_dhchap_key(struct spdk_nvmf_subsystem *subsys, const char *nqn, 432 enum nvmf_auth_key_type type); 433 struct spdk_nvmf_subsystem_listener *nvmf_subsystem_find_listener( 434 struct spdk_nvmf_subsystem *subsystem, 435 const struct spdk_nvme_transport_id *trid); 436 bool nvmf_subsystem_zone_append_supported(struct spdk_nvmf_subsystem *subsystem); 437 struct spdk_nvmf_listener *nvmf_transport_find_listener( 438 struct spdk_nvmf_transport *transport, 439 const struct spdk_nvme_transport_id *trid); 440 void nvmf_transport_dump_opts(struct spdk_nvmf_transport *transport, struct spdk_json_write_ctx *w, 441 bool named); 442 void nvmf_transport_listen_dump_trid(const struct spdk_nvme_transport_id *trid, 443 struct spdk_json_write_ctx *w); 444 445 int nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr); 446 int nvmf_ctrlr_async_event_ana_change_notice(struct spdk_nvmf_ctrlr *ctrlr); 447 void nvmf_ctrlr_async_event_discovery_log_change_notice(void *ctx); 448 void nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr); 449 450 void nvmf_ns_reservation_request(void *ctx); 451 void nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr, 452 struct spdk_nvmf_ns *ns, 453 enum spdk_nvme_reservation_notification_log_page_type type); 454 455 bool nvmf_ns_is_ptpl_capable(const struct spdk_nvmf_ns *ns); 456 457 static inline struct spdk_nvmf_host * 458 nvmf_ns_find_host(struct spdk_nvmf_ns *ns, const char *hostnqn) 459 { 460 struct spdk_nvmf_host *host = NULL; 461 462 TAILQ_FOREACH(host, &ns->hosts, link) { 463 if (strcmp(hostnqn, host->nqn) == 0) { 464 return host; 465 } 466 } 467 468 return NULL; 469 } 470 471 /* 472 * Abort zero-copy requests that already got the buffer (received zcopy_start cb), but haven't 473 * started zcopy_end. These requests are kept on the outstanding queue, but are not waiting for a 474 * completion from the bdev layer, so, when a qpair is being disconnected, we need to kick them to 475 * force their completion. 476 */ 477 void nvmf_qpair_abort_pending_zcopy_reqs(struct spdk_nvmf_qpair *qpair); 478 479 /* 480 * Free aer simply frees the rdma resources for the aer without informing the host. 481 * This function should be called when deleting a qpair when one wants to make sure 482 * the qpair is completely empty before freeing the request. The reason we free the 483 * AER without sending a completion is to prevent the host from sending another AER. 484 */ 485 void nvmf_qpair_free_aer(struct spdk_nvmf_qpair *qpair); 486 487 int nvmf_ctrlr_abort_request(struct spdk_nvmf_request *req); 488 489 void nvmf_ctrlr_set_fatal_status(struct spdk_nvmf_ctrlr *ctrlr); 490 491 static inline bool 492 nvmf_ctrlr_ns_is_visible(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid) 493 { 494 return spdk_bit_array_get(ctrlr->visible_ns, nsid - 1); 495 } 496 497 static inline struct spdk_nvmf_ns * 498 _nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) 499 { 500 /* NOTE: This implicitly also checks for 0, since 0 - 1 wraps around to UINT32_MAX. */ 501 if (spdk_unlikely(nsid - 1 >= subsystem->max_nsid)) { 502 return NULL; 503 } 504 505 return subsystem->ns[nsid - 1]; 506 } 507 508 static inline struct spdk_nvmf_ns * 509 nvmf_ctrlr_get_ns(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid) 510 { 511 struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys; 512 struct spdk_nvmf_ns *ns = _nvmf_subsystem_get_ns(subsystem, nsid); 513 514 return ns && nvmf_ctrlr_ns_is_visible(ctrlr, nsid) ? ns : NULL; 515 } 516 517 static inline bool 518 nvmf_qpair_is_admin_queue(struct spdk_nvmf_qpair *qpair) 519 { 520 return qpair->qid == 0; 521 } 522 523 void nvmf_qpair_set_state(struct spdk_nvmf_qpair *qpair, enum spdk_nvmf_qpair_state state); 524 525 int nvmf_qpair_auth_init(struct spdk_nvmf_qpair *qpair); 526 void nvmf_qpair_auth_destroy(struct spdk_nvmf_qpair *qpair); 527 void nvmf_qpair_auth_dump(struct spdk_nvmf_qpair *qpair, struct spdk_json_write_ctx *w); 528 529 int nvmf_auth_request_exec(struct spdk_nvmf_request *req); 530 bool nvmf_auth_is_supported(void); 531 532 static inline bool 533 nvmf_request_is_fabric_connect(struct spdk_nvmf_request *req) 534 { 535 return req->cmd->nvmf_cmd.opcode == SPDK_NVME_OPC_FABRIC && 536 req->cmd->nvmf_cmd.fctype == SPDK_NVMF_FABRIC_COMMAND_CONNECT; 537 } 538 539 /* 540 * Tests whether a given string represents a valid NQN. 541 */ 542 bool nvmf_nqn_is_valid(const char *nqn); 543 544 /* 545 * Tests whether a given NQN describes a discovery subsystem. 546 */ 547 bool nvmf_nqn_is_discovery(const char *nqn); 548 549 /** 550 * Initiates a zcopy start operation 551 * 552 * \param bdev The \ref spdk_bdev 553 * \param desc The \ref spdk_bdev_desc 554 * \param ch The \ref spdk_io_channel 555 * \param req The \ref spdk_nvmf_request passed to the bdev for processing 556 * 557 * \return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE if the command was completed immediately or 558 * SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS if the command was submitted and will be 559 * completed asynchronously. Asynchronous completions are notified through 560 * spdk_nvmf_request_complete(). 561 */ 562 int nvmf_bdev_ctrlr_zcopy_start(struct spdk_bdev *bdev, 563 struct spdk_bdev_desc *desc, 564 struct spdk_io_channel *ch, 565 struct spdk_nvmf_request *req); 566 567 /** 568 * Ends a zcopy operation 569 * 570 * \param req The NVMe-oF request 571 * \param commit Flag indicating whether the buffers should be committed 572 */ 573 void nvmf_bdev_ctrlr_zcopy_end(struct spdk_nvmf_request *req, bool commit); 574 575 /** 576 * Publishes the mDNS PRR (Pull Registration Request) for the NVMe-oF target. 577 * 578 * \param tgt The NVMe-oF target 579 * 580 * \return 0 on success, negative errno on failure 581 */ 582 int nvmf_publish_mdns_prr(struct spdk_nvmf_tgt *tgt); 583 584 /** 585 * Stops the mDNS PRR (Pull Registration Request) for the NVMe-oF target. 586 * 587 * \param tgt The NVMe-oF target 588 */ 589 void nvmf_tgt_stop_mdns_prr(struct spdk_nvmf_tgt *tgt); 590 591 /** 592 * Updates the listener list in the mDNS PRR (Pull Registration Request) for the NVMe-oF target. 593 * 594 * \param tgt The NVMe-oF target 595 * 596 * \return 0 on success, negative errno on failure 597 */ 598 int nvmf_tgt_update_mdns_prr(struct spdk_nvmf_tgt *tgt); 599 600 static inline struct spdk_nvmf_transport_poll_group * 601 nvmf_get_transport_poll_group(struct spdk_nvmf_poll_group *group, 602 struct spdk_nvmf_transport *transport) 603 { 604 struct spdk_nvmf_transport_poll_group *tgroup; 605 606 TAILQ_FOREACH(tgroup, &group->tgroups, link) { 607 if (tgroup->transport == transport) { 608 return tgroup; 609 } 610 } 611 612 return NULL; 613 } 614 615 /** 616 * Generates a new NVMF controller id 617 * 618 * \param subsystem The subsystem 619 * 620 * \return unique controller id or 0xFFFF when all controller ids are in use 621 */ 622 uint16_t nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem); 623 624 #endif /* __NVMF_INTERNAL_H__ */ 625