LCOV - code coverage report
Current view: top level - include/spdk - nvmf_transport.h (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 21 24 87.5 %
Date: 2024-11-05 10:06:02 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2020 Intel Corporation. All rights reserved.
       3             :  *   Copyright (c) 2019, 2021 Mellanox Technologies LTD. All rights reserved.
       4             :  */
       5             : 
       6             : /** \file
       7             :  * NVMe-oF Target transport plugin API
       8             :  */
       9             : 
      10             : #ifndef SPDK_NVMF_TRANSPORT_H_
      11             : #define SPDK_NVMF_TRANSPORT_H_
      12             : 
      13             : #include "spdk/bdev.h"
      14             : #include "spdk/thread.h"
      15             : #include "spdk/nvme_spec.h"
      16             : #include "spdk/nvmf.h"
      17             : #include "spdk/nvmf_cmd.h"
      18             : #include "spdk/nvmf_spec.h"
      19             : #include "spdk/memory.h"
      20             : #include "spdk/trace.h"
      21             : 
      22             : #ifdef __cplusplus
      23             : extern "C" {
      24             : #endif
      25             : 
      26             : #define SPDK_NVMF_MAX_SGL_ENTRIES       16
      27             : 
      28             : /* The maximum number of buffers per request */
      29             : #define NVMF_REQ_MAX_BUFFERS    (SPDK_NVMF_MAX_SGL_ENTRIES * 2 + 1)
      30             : 
      31             : /* Maximum pending AERs that can be migrated */
      32             : #define SPDK_NVMF_MIGR_MAX_PENDING_AERS 256
      33             : 
      34             : #define SPDK_NVMF_MAX_ASYNC_EVENTS 4
      35             : 
      36             : /* Some backends require 4K aligned buffers. The iobuf library gives us that
      37             :  * naturally, but there are buffers allocated other ways that need to use this.
      38             :  */
      39             : #define NVMF_DATA_BUFFER_ALIGNMENT      VALUE_4KB
      40             : #define NVMF_DATA_BUFFER_MASK           (NVMF_DATA_BUFFER_ALIGNMENT - 1LL)
      41             : 
      42             : #define SPDK_NVMF_DEFAULT_ACCEPT_POLL_RATE_US 10000
      43             : 
      44             : union nvmf_h2c_msg {
      45             :         struct spdk_nvmf_capsule_cmd                    nvmf_cmd;
      46             :         struct spdk_nvme_cmd                            nvme_cmd;
      47             :         struct spdk_nvmf_fabric_prop_set_cmd            prop_set_cmd;
      48             :         struct spdk_nvmf_fabric_prop_get_cmd            prop_get_cmd;
      49             :         struct spdk_nvmf_fabric_connect_cmd             connect_cmd;
      50             :         struct spdk_nvmf_fabric_auth_send_cmd           auth_send_cmd;
      51             :         struct spdk_nvmf_fabric_auth_recv_cmd           auth_recv_cmd;
      52             : };
      53             : SPDK_STATIC_ASSERT(sizeof(union nvmf_h2c_msg) == 64, "Incorrect size");
      54             : 
      55             : union nvmf_c2h_msg {
      56             :         struct spdk_nvme_cpl                            nvme_cpl;
      57             :         struct spdk_nvmf_fabric_prop_get_rsp            prop_get_rsp;
      58             :         struct spdk_nvmf_fabric_connect_rsp             connect_rsp;
      59             : };
      60             : SPDK_STATIC_ASSERT(sizeof(union nvmf_c2h_msg) == 16, "Incorrect size");
      61             : 
      62             : struct spdk_nvmf_dif_info {
      63             :         struct spdk_dif_ctx                     dif_ctx;
      64             :         uint32_t                                elba_length;
      65             :         uint32_t                                orig_length;
      66             : };
      67             : 
      68             : struct spdk_nvmf_stripped_data {
      69             :         uint32_t                        iovcnt;
      70             :         struct iovec                    iov[NVMF_REQ_MAX_BUFFERS];
      71             : };
      72             : 
      73             : enum spdk_nvmf_zcopy_phase {
      74             :         NVMF_ZCOPY_PHASE_NONE,        /* Request is not using ZCOPY */
      75             :         NVMF_ZCOPY_PHASE_INIT,        /* Requesting Buffers */
      76             :         NVMF_ZCOPY_PHASE_EXECUTE,     /* Got buffers processing commands */
      77             :         NVMF_ZCOPY_PHASE_END_PENDING, /* Releasing buffers */
      78             :         NVMF_ZCOPY_PHASE_COMPLETE,    /* Buffers Released */
      79             :         NVMF_ZCOPY_PHASE_INIT_FAILED  /* Failed to get the buffers */
      80             : };
      81             : 
      82             : struct spdk_nvmf_request {
      83             :         struct spdk_nvmf_qpair          *qpair;
      84             :         uint32_t                        length;
      85             :         uint8_t                         xfer; /* type enum spdk_nvme_data_transfer */
      86             :         union {
      87             :                 uint8_t raw;
      88             :                 struct {
      89             :                         uint8_t data_from_pool          : 1;
      90             :                         uint8_t dif_enabled             : 1;
      91             :                         uint8_t first_fused             : 1;
      92             :                         uint8_t rsvd                    : 5;
      93             :                 };
      94             :         };
      95             :         uint8_t                         zcopy_phase; /* type enum spdk_nvmf_zcopy_phase */
      96             :         uint8_t                         iovcnt;
      97             :         union nvmf_h2c_msg              *cmd;
      98             :         union nvmf_c2h_msg              *rsp;
      99             :         STAILQ_ENTRY(spdk_nvmf_request) buf_link;
     100             :         TAILQ_ENTRY(spdk_nvmf_request)  link;
     101             : 
     102             :         /* Memory domain which describes payload in this request. If the bdev doesn't support memory
     103             :          * domains, bdev layer will do the necessary push or pull operation. */
     104             :         struct spdk_memory_domain       *memory_domain;
     105             :         /* Context to be passed to memory domain operations. */
     106             :         void                            *memory_domain_ctx;
     107             :         struct spdk_accel_sequence      *accel_sequence;
     108             : 
     109             :         struct iovec                    iov[NVMF_REQ_MAX_BUFFERS];
     110             : 
     111             :         struct spdk_nvmf_stripped_data  *stripped_data;
     112             : 
     113             :         struct spdk_nvmf_dif_info       dif;
     114             : 
     115             :         struct spdk_bdev_io_wait_entry  bdev_io_wait;
     116             :         spdk_nvmf_nvme_passthru_cmd_cb  cmd_cb_fn;
     117             :         struct spdk_nvmf_request        *first_fused_req;
     118             :         struct spdk_nvmf_request        *req_to_abort;
     119             :         struct spdk_poller              *poller;
     120             :         struct spdk_bdev_io             *zcopy_bdev_io; /* Contains the bdev_io when using ZCOPY */
     121             : 
     122             :         /* Internal state that keeps track of the iobuf allocation progress */
     123             :         struct {
     124             :                 struct spdk_iobuf_entry entry;
     125             :                 uint32_t                remaining_length;
     126             :         } iobuf;
     127             : 
     128             :         /* Timeout tracked for connect and abort flows. */
     129             :         uint64_t timeout_tsc;
     130             :         uint32_t                        orig_nsid;
     131             : };
     132             : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_request) == 816, "Incorrect size");
     133             : 
     134             : enum spdk_nvmf_qpair_state {
     135             :         SPDK_NVMF_QPAIR_UNINITIALIZED = 0,
     136             :         SPDK_NVMF_QPAIR_CONNECTING,
     137             :         SPDK_NVMF_QPAIR_AUTHENTICATING,
     138             :         SPDK_NVMF_QPAIR_ENABLED,
     139             :         SPDK_NVMF_QPAIR_DEACTIVATING,
     140             :         SPDK_NVMF_QPAIR_ERROR,
     141             : };
     142             : 
     143             : typedef void (*spdk_nvmf_state_change_done)(void *cb_arg, int status);
     144             : 
     145             : struct spdk_nvmf_qpair_auth;
     146             : 
     147             : struct spdk_nvmf_qpair {
     148             :         uint8_t                                 state; /* ref spdk_nvmf_qpair_state */
     149             :         uint8_t                                 rsvd;
     150             :         uint16_t                                qid;
     151             :         uint16_t                                sq_head;
     152             :         uint16_t                                sq_head_max;
     153             : 
     154             :         struct spdk_nvmf_transport              *transport;
     155             :         struct spdk_nvmf_ctrlr                  *ctrlr;
     156             :         struct spdk_nvmf_poll_group             *group;
     157             : 
     158             :         union {
     159             :                 struct spdk_nvmf_request        *first_fused_req;
     160             :                 struct spdk_nvmf_request        *connect_req;
     161             :         };
     162             : 
     163             :         TAILQ_HEAD(, spdk_nvmf_request)         outstanding;
     164             :         TAILQ_ENTRY(spdk_nvmf_qpair)            link;
     165             : 
     166             :         spdk_nvmf_state_change_done             state_cb;
     167             :         void                                    *state_cb_arg;
     168             : 
     169             :         bool                                    connect_received;
     170             :         bool                                    disconnect_started;
     171             : 
     172             :         uint16_t                                trace_id;
     173             : 
     174             :         /* Number of IO outstanding at transport level */
     175             :         uint16_t                                queue_depth;
     176             : 
     177             :         struct spdk_nvmf_qpair_auth             *auth;
     178             : 
     179             :         struct {
     180             :                 /* Indicates whether numa.id is valid, needed for numa.id == 0 case */
     181             :                 uint32_t                        id_valid : 1;
     182             :                 int32_t                         id : 31;
     183             :         } numa;
     184             : };
     185             : 
     186             : static inline int32_t
     187             : spdk_nvmf_qpair_get_numa_id(struct spdk_nvmf_qpair *qpair)
     188             : {
     189             :         return qpair->numa.id_valid ? qpair->numa.id : SPDK_ENV_NUMA_ID_ANY;
     190             : }
     191             : 
     192             : struct spdk_nvmf_transport_poll_group {
     193             :         struct spdk_nvmf_transport                                      *transport;
     194             :         /* Requests that are waiting to obtain a data buffer */
     195             :         STAILQ_HEAD(, spdk_nvmf_request)                                pending_buf_queue;
     196             :         struct spdk_iobuf_channel                                       *buf_cache;
     197             :         struct spdk_nvmf_poll_group                                     *group;
     198             :         TAILQ_ENTRY(spdk_nvmf_transport_poll_group)                     link;
     199             : };
     200             : 
     201             : struct spdk_nvmf_poll_group {
     202             :         struct spdk_thread                              *thread;
     203             :         struct spdk_poller                              *poller;
     204             : 
     205             :         TAILQ_HEAD(, spdk_nvmf_transport_poll_group)    tgroups;
     206             : 
     207             :         /* Array of poll groups indexed by subsystem id (sid) */
     208             :         struct spdk_nvmf_subsystem_poll_group           *sgroups;
     209             :         uint32_t                                        num_sgroups;
     210             : 
     211             :         /* Protected by mutex. Counts qpairs that have connected at a
     212             :          * transport level, but are not associated with a subsystem
     213             :          * or controller yet (because the CONNECT capsule hasn't
     214             :          * been received). */
     215             :         uint32_t                                        current_unassociated_qpairs;
     216             : 
     217             :         /* All of the queue pairs that belong to this poll group */
     218             :         TAILQ_HEAD(, spdk_nvmf_qpair)                   qpairs;
     219             : 
     220             :         /* Statistics */
     221             :         struct spdk_nvmf_poll_group_stat                stat;
     222             : 
     223             :         spdk_nvmf_poll_group_destroy_done_fn            destroy_cb_fn;
     224             :         void                                            *destroy_cb_arg;
     225             : 
     226             :         struct spdk_nvmf_tgt                            *tgt;
     227             : 
     228             :         TAILQ_ENTRY(spdk_nvmf_poll_group)               link;
     229             : 
     230             :         pthread_mutex_t                                 mutex;
     231             : };
     232             : 
     233             : struct spdk_nvmf_listener {
     234             :         struct spdk_nvme_transport_id   trid;
     235             :         uint32_t                        ref;
     236             :         char                            *sock_impl;
     237             :         TAILQ_ENTRY(spdk_nvmf_listener) link;
     238             : };
     239             : 
     240             : /**
     241             :  * A subset of struct spdk_nvme_ctrlr_data that are emulated by a fabrics device.
     242             :  */
     243             : struct spdk_nvmf_ctrlr_data {
     244             :         uint8_t aerl;
     245             :         uint16_t kas;
     246             :         /** pci vendor id */
     247             :         uint16_t vid;
     248             :         /** pci subsystem vendor id */
     249             :         uint16_t ssvid;
     250             :         /** ieee oui identifier */
     251             :         uint8_t ieee[3];
     252             :         struct spdk_nvme_cdata_oacs oacs;
     253             :         struct spdk_nvme_cdata_oncs oncs;
     254             :         struct spdk_nvme_cdata_fuses fuses;
     255             :         struct spdk_nvme_cdata_sgls sgls;
     256             :         struct spdk_nvme_cdata_nvmf_specific nvmf_specific;
     257             : };
     258             : 
     259             : #define MAX_MEMPOOL_NAME_LENGTH 40
     260             : 
     261             : /* abidiff has a problem with changes in spdk_nvmf_transport_opts, so spdk_nvmf_transport had to be
     262             :  * added to the suppression list, so if spdk_nvmf_transport is changed, we need to remove the
     263             :  * suppression and bump up the major version.
     264             :  */
     265             : struct spdk_nvmf_transport {
     266             :         struct spdk_nvmf_tgt                    *tgt;
     267             :         const struct spdk_nvmf_transport_ops    *ops;
     268             :         struct spdk_nvmf_transport_opts         opts;
     269             : 
     270             :         char                                    iobuf_name[MAX_MEMPOOL_NAME_LENGTH];
     271             : 
     272             :         TAILQ_HEAD(, spdk_nvmf_listener)        listeners;
     273             :         TAILQ_ENTRY(spdk_nvmf_transport)        link;
     274             : 
     275             :         pthread_mutex_t                         mutex;
     276             : };
     277             : 
     278             : typedef void (*spdk_nvmf_transport_qpair_fini_cb)(void *cb_arg);
     279             : 
     280             : struct spdk_nvmf_transport_ops {
     281             :         /**
     282             :          * Transport name
     283             :          */
     284             :         char name[SPDK_NVMF_TRSTRING_MAX_LEN];
     285             : 
     286             :         /**
     287             :          * Transport type
     288             :          */
     289             :         enum spdk_nvme_transport_type type;
     290             : 
     291             :         /**
     292             :          * Initialize transport options to default value
     293             :          */
     294             :         void (*opts_init)(struct spdk_nvmf_transport_opts *opts);
     295             : 
     296             :         /**
     297             :          * Create a transport for the given transport opts. Either synchronous
     298             :          * or asynchronous version shall be implemented.
     299             :          */
     300             :         struct spdk_nvmf_transport *(*create)(struct spdk_nvmf_transport_opts *opts);
     301             :         int (*create_async)(struct spdk_nvmf_transport_opts *opts, spdk_nvmf_transport_create_done_cb cb_fn,
     302             :                             void *cb_arg);
     303             : 
     304             :         /**
     305             :          * Dump transport-specific opts into JSON
     306             :          */
     307             :         void (*dump_opts)(struct spdk_nvmf_transport *transport,
     308             :                           struct spdk_json_write_ctx *w);
     309             : 
     310             :         /**
     311             :          * Destroy the transport
     312             :          */
     313             :         int (*destroy)(struct spdk_nvmf_transport *transport,
     314             :                        spdk_nvmf_transport_destroy_done_cb cb_fn, void *cb_arg);
     315             : 
     316             :         /**
     317             :           * Instruct the transport to accept new connections at the address
     318             :           * provided. This may be called multiple times.
     319             :           */
     320             :         int (*listen)(struct spdk_nvmf_transport *transport, const struct spdk_nvme_transport_id *trid,
     321             :                       struct spdk_nvmf_listen_opts *opts);
     322             : 
     323             :         /**
     324             :          * Dump transport-specific listen opts into JSON
     325             :          */
     326             :         void (*listen_dump_opts)(struct spdk_nvmf_transport *transport,
     327             :                                  const struct spdk_nvme_transport_id *trid, struct spdk_json_write_ctx *w);
     328             : 
     329             :         /**
     330             :           * Stop accepting new connections at the given address.
     331             :           */
     332             :         void (*stop_listen)(struct spdk_nvmf_transport *transport,
     333             :                             const struct spdk_nvme_transport_id *trid);
     334             : 
     335             :         /**
     336             :          * It is a notification that a listener is being associated with the subsystem.
     337             :          * Most transports will not need to take any action here, as the enforcement
     338             :          * of the association is done in the generic code.
     339             :          *
     340             :          * Returns a negated errno code to block the association. 0 to allow.
     341             :          */
     342             :         int (*listen_associate)(struct spdk_nvmf_transport *transport,
     343             :                                 const struct spdk_nvmf_subsystem *subsystem,
     344             :                                 const struct spdk_nvme_transport_id *trid);
     345             : 
     346             :         /**
     347             :          * It is a notification that a namespace is being added to the subsystem.
     348             :          * Most transports will not need to take any action here.
     349             :          *
     350             :          * Returns a negated errno code to block the attachment. 0 to allow.
     351             :          */
     352             :         int (*subsystem_add_ns)(struct spdk_nvmf_transport *transport,
     353             :                                 const struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ns *ns);
     354             : 
     355             :         /**
     356             :          * It is a notification that a namespace has been removed from the subsystem.
     357             :          * Most transports will not need to take any action here.
     358             :          */
     359             :         void (*subsystem_remove_ns)(struct spdk_nvmf_transport *transport,
     360             :                                     const struct spdk_nvmf_subsystem *subsystem, uint32_t nsid);
     361             : 
     362             :         /**
     363             :          * Initialize subset of identify controller data.
     364             :          */
     365             :         void (*cdata_init)(struct spdk_nvmf_transport *transport, struct spdk_nvmf_subsystem *subsystem,
     366             :                            struct spdk_nvmf_ctrlr_data *cdata);
     367             : 
     368             :         /**
     369             :          * Fill out a discovery log entry for a specific listen address.
     370             :          */
     371             :         void (*listener_discover)(struct spdk_nvmf_transport *transport,
     372             :                                   struct spdk_nvme_transport_id *trid,
     373             :                                   struct spdk_nvmf_discovery_log_page_entry *entry);
     374             : 
     375             :         /**
     376             :          * Create a new poll group
     377             :          */
     378             :         struct spdk_nvmf_transport_poll_group *(*poll_group_create)(struct spdk_nvmf_transport *transport,
     379             :                         struct spdk_nvmf_poll_group *group);
     380             : 
     381             :         /**
     382             :          * Get the polling group of the queue pair optimal for the specific transport
     383             :          */
     384             :         struct spdk_nvmf_transport_poll_group *(*get_optimal_poll_group)(struct spdk_nvmf_qpair *qpair);
     385             : 
     386             :         /**
     387             :          * Destroy a poll group
     388             :          */
     389             :         void (*poll_group_destroy)(struct spdk_nvmf_transport_poll_group *group);
     390             : 
     391             :         /**
     392             :          * Add a qpair to a poll group
     393             :          */
     394             :         int (*poll_group_add)(struct spdk_nvmf_transport_poll_group *group,
     395             :                               struct spdk_nvmf_qpair *qpair);
     396             : 
     397             :         /**
     398             :          * Remove a qpair from a poll group
     399             :          */
     400             :         int (*poll_group_remove)(struct spdk_nvmf_transport_poll_group *group,
     401             :                                  struct spdk_nvmf_qpair *qpair);
     402             : 
     403             :         /**
     404             :          * Poll the group to process I/O
     405             :          */
     406             :         int (*poll_group_poll)(struct spdk_nvmf_transport_poll_group *group);
     407             : 
     408             :         /*
     409             :          * Free the request without sending a response
     410             :          * to the originator. Release memory tied to this request.
     411             :          */
     412             :         int (*req_free)(struct spdk_nvmf_request *req);
     413             : 
     414             :         /*
     415             :          * Signal request completion, which sends a response
     416             :          * to the originator.
     417             :          */
     418             :         int (*req_complete)(struct spdk_nvmf_request *req);
     419             : 
     420             :         /**
     421             :          * Callback for the iobuf based queuing of requests awaiting free buffers.
     422             :          * Called when all requested buffers are allocated for the given request.
     423             :          * Used only if initial spdk_iobuf_get() call didn't allocate all buffers at once
     424             :          * and request was queued internally in the iobuf until free buffers become available.
     425             :          * This callback is optional and not all transports need to implement it.
     426             :          * If not set then transport implementation must queue such requests internally.
     427             :          */
     428             :         void (*req_get_buffers_done)(struct spdk_nvmf_request *req);
     429             : 
     430             :         /*
     431             :          * Deinitialize a connection.
     432             :          */
     433             :         void (*qpair_fini)(struct spdk_nvmf_qpair *qpair,
     434             :                            spdk_nvmf_transport_qpair_fini_cb cb_fn,
     435             :                            void *cb_args);
     436             : 
     437             :         /*
     438             :          * Get the peer transport ID for the queue pair.
     439             :          */
     440             :         int (*qpair_get_peer_trid)(struct spdk_nvmf_qpair *qpair,
     441             :                                    struct spdk_nvme_transport_id *trid);
     442             : 
     443             :         /*
     444             :          * Get the local transport ID for the queue pair.
     445             :          */
     446             :         int (*qpair_get_local_trid)(struct spdk_nvmf_qpair *qpair,
     447             :                                     struct spdk_nvme_transport_id *trid);
     448             : 
     449             :         /*
     450             :          * Get the listener transport ID that accepted this qpair originally.
     451             :          */
     452             :         int (*qpair_get_listen_trid)(struct spdk_nvmf_qpair *qpair,
     453             :                                      struct spdk_nvme_transport_id *trid);
     454             : 
     455             :         /*
     456             :          * Abort the request which the abort request specifies.
     457             :          * This function can complete synchronously or asynchronously, but
     458             :          * is expected to call spdk_nvmf_request_complete() in the end
     459             :          * for both cases.
     460             :          */
     461             :         void (*qpair_abort_request)(struct spdk_nvmf_qpair *qpair,
     462             :                                     struct spdk_nvmf_request *req);
     463             : 
     464             :         /*
     465             :          * Dump transport poll group statistics into JSON.
     466             :          */
     467             :         void (*poll_group_dump_stat)(struct spdk_nvmf_transport_poll_group *group,
     468             :                                      struct spdk_json_write_ctx *w);
     469             : 
     470             :         /*
     471             :          * A notification that a subsystem has been configured to allow access
     472             :          * from the given host.
     473             :          * This callback is optional and not all transports need to implement it.
     474             :          */
     475             :         int (*subsystem_add_host)(struct spdk_nvmf_transport *transport,
     476             :                                   const struct spdk_nvmf_subsystem *subsystem,
     477             :                                   const char *hostnqn,
     478             :                                   const struct spdk_json_val *transport_specific);
     479             : 
     480             :         /*
     481             :          * A notification that a subsystem is no longer configured to allow access
     482             :          * from the given host.
     483             :          * This callback is optional and not all transports need to implement it.
     484             :          */
     485             :         void (*subsystem_remove_host)(struct spdk_nvmf_transport *transport,
     486             :                                       const struct spdk_nvmf_subsystem *subsystem,
     487             :                                       const char *hostnqn);
     488             : 
     489             :         /*
     490             :          * A callback used to dump subsystem's host data for a specific transport.
     491             :          * This callback is optional and not all transports need to implement it.
     492             :          */
     493             :         void (*subsystem_dump_host)(struct spdk_nvmf_transport *transport,
     494             :                                     const struct spdk_nvmf_subsystem *subsystem,
     495             :                                     const char *hostnqn, struct spdk_json_write_ctx *w);
     496             :         /*
     497             :          * A notification that a referral has been configured to allow access
     498             :          * from the given host.
     499             :          * This callback is optional and not all transports need to implement it.
     500             :          */
     501             :         int (*referral_add_host)(struct spdk_nvmf_transport *transport,
     502             :                                  const struct spdk_nvmf_referral *referral,
     503             :                                  const char *hostnqn,
     504             :                                  const struct spdk_json_val *transport_specific);
     505             : 
     506             :         /*
     507             :          * A notification that a referral is no longer configured to allow access
     508             :          * from the given host.
     509             :          * This callback is optional and not all transports need to implement it.
     510             :          */
     511             :         void (*referral_remove_host)(struct spdk_nvmf_transport *transport,
     512             :                                      const struct spdk_nvmf_referral *referral,
     513             :                                      const char *hostnqn);
     514             : 
     515             :         /*
     516             :          * A callback used to dump referral's host data for a specific transport.
     517             :          * This callback is optional and not all transports need to implement it.
     518             :          */
     519             :         void (*referral_dump_host)(struct spdk_nvmf_transport *transport,
     520             :                                    const struct spdk_nvmf_referral *referral,
     521             :                                    const char *hostnqn, struct spdk_json_write_ctx *w);
     522             : };
     523             : 
     524             : /**
     525             :  * Register the operations for a given transport type.
     526             :  *
     527             :  * This function should be invoked by referencing the macro
     528             :  * SPDK_NVMF_TRANSPORT_REGISTER macro in the transport's .c file.
     529             :  *
     530             :  * \param ops The operations associated with an NVMe-oF transport.
     531             :  */
     532             : void spdk_nvmf_transport_register(const struct spdk_nvmf_transport_ops *ops);
     533             : 
     534             : int spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req);
     535             : 
     536             : /**
     537             :  * Function to be called for each newly discovered qpair.
     538             :  *
     539             :  * \param tgt The nvmf target
     540             :  * \param qpair The newly discovered qpair.
     541             :  */
     542             : void spdk_nvmf_tgt_new_qpair(struct spdk_nvmf_tgt *tgt, struct spdk_nvmf_qpair *qpair);
     543             : 
     544             : static inline bool
     545          54 : spdk_nvmf_qpair_is_active(struct spdk_nvmf_qpair *qpair)
     546             : {
     547          54 :         return qpair->state == SPDK_NVMF_QPAIR_CONNECTING ||
     548          96 :                qpair->state == SPDK_NVMF_QPAIR_AUTHENTICATING ||
     549          42 :                qpair->state == SPDK_NVMF_QPAIR_ENABLED;
     550             : }
     551             : 
     552             : /**
     553             :  * A subset of struct spdk_nvme_registers that are emulated by a fabrics device.
     554             :  */
     555             : struct spdk_nvmf_registers {
     556             :         union spdk_nvme_cap_register    cap;
     557             :         union spdk_nvme_vs_register     vs;
     558             :         union spdk_nvme_cc_register     cc;
     559             :         union spdk_nvme_csts_register   csts;
     560             :         union spdk_nvme_aqa_register    aqa;
     561             :         uint64_t                        asq;
     562             :         uint64_t                        acq;
     563             : };
     564             : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_registers) == 40, "Incorrect size");
     565             : 
     566             : const struct spdk_nvmf_registers *spdk_nvmf_ctrlr_get_regs(struct spdk_nvmf_ctrlr *ctrlr);
     567             : 
     568             : void spdk_nvmf_request_free_buffers(struct spdk_nvmf_request *req,
     569             :                                     struct spdk_nvmf_transport_poll_group *group,
     570             :                                     struct spdk_nvmf_transport *transport);
     571             : int spdk_nvmf_request_get_buffers(struct spdk_nvmf_request *req,
     572             :                                   struct spdk_nvmf_transport_poll_group *group,
     573             :                                   struct spdk_nvmf_transport *transport,
     574             :                                   uint32_t length);
     575             : 
     576             : bool spdk_nvmf_request_get_dif_ctx(struct spdk_nvmf_request *req, struct spdk_dif_ctx *dif_ctx);
     577             : 
     578             : void spdk_nvmf_request_exec(struct spdk_nvmf_request *req);
     579             : int spdk_nvmf_request_free(struct spdk_nvmf_request *req);
     580             : int spdk_nvmf_request_complete(struct spdk_nvmf_request *req);
     581             : void spdk_nvmf_request_zcopy_start(struct spdk_nvmf_request *req);
     582             : void spdk_nvmf_request_zcopy_end(struct spdk_nvmf_request *req, bool commit);
     583             : 
     584             : static inline bool
     585           8 : spdk_nvmf_request_using_zcopy(const struct spdk_nvmf_request *req)
     586             : {
     587           8 :         return req->zcopy_phase != NVMF_ZCOPY_PHASE_NONE;
     588             : }
     589             : 
     590             : /**
     591             :  * Remove the given qpair from the poll group.
     592             :  *
     593             :  * \param qpair The qpair to remove.
     594             :  */
     595             : void spdk_nvmf_poll_group_remove(struct spdk_nvmf_qpair *qpair);
     596             : 
     597             : /**
     598             :  * Get the NVMe-oF subsystem associated with this controller.
     599             :  *
     600             :  * \param ctrlr The NVMe-oF controller
     601             :  *
     602             :  * \return The NVMe-oF subsystem
     603             :  */
     604             : struct spdk_nvmf_subsystem *
     605             : spdk_nvmf_ctrlr_get_subsystem(struct spdk_nvmf_ctrlr *ctrlr);
     606             : 
     607             : /**
     608             :  * Get the NVMe-oF controller ID.
     609             :  *
     610             :  * \param ctrlr The NVMe-oF controller
     611             :  *
     612             :  * \return The NVMe-oF controller ID
     613             :  */
     614             : uint16_t spdk_nvmf_ctrlr_get_id(struct spdk_nvmf_ctrlr *ctrlr);
     615             : 
     616             : struct spdk_nvmf_ctrlr_feat {
     617             :         union spdk_nvme_feat_arbitration arbitration;
     618             :         union spdk_nvme_feat_power_management power_management;
     619             :         union spdk_nvme_feat_error_recovery error_recovery;
     620             :         union spdk_nvme_feat_volatile_write_cache volatile_write_cache;
     621             :         union spdk_nvme_feat_number_of_queues number_of_queues;
     622             :         union spdk_nvme_feat_interrupt_coalescing interrupt_coalescing;
     623             :         union spdk_nvme_feat_interrupt_vector_configuration interrupt_vector_configuration;
     624             :         union spdk_nvme_feat_write_atomicity write_atomicity;
     625             :         union spdk_nvme_feat_async_event_configuration async_event_configuration;
     626             :         union spdk_nvme_feat_keep_alive_timer keep_alive_timer;
     627             : };
     628             : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_ctrlr_feat) == 40, "Incorrect size");
     629             : 
     630             : /*
     631             :  * Migration data structure used to save & restore a NVMe-oF controller.
     632             :  *
     633             :  * The data structure is experimental.
     634             :  *
     635             :  */
     636             : struct spdk_nvmf_ctrlr_migr_data {
     637             :         /* `data_size` is valid size of `spdk_nvmf_ctrlr_migr_data` without counting `unused`.
     638             :          * We use this field to migrate `spdk_nvmf_ctrlr_migr_data` from source VM and restore
     639             :          * it in destination VM.
     640             :          */
     641             :         uint32_t data_size;
     642             :         /* `regs_size` is valid size of `spdk_nvmf_registers`. */
     643             :         uint32_t regs_size;
     644             :         /* `feat_size` is valid size of `spdk_nvmf_ctrlr_feat`. */
     645             :         uint32_t feat_size;
     646             :         uint32_t reserved;
     647             : 
     648             :         struct spdk_nvmf_registers regs;
     649             :         uint8_t regs_reserved[216];
     650             : 
     651             :         struct spdk_nvmf_ctrlr_feat feat;
     652             :         uint8_t feat_reserved[216];
     653             : 
     654             :         uint16_t cntlid;
     655             :         uint8_t acre;
     656             :         uint8_t num_aer_cids;
     657             :         uint32_t num_async_events;
     658             : 
     659             :         union spdk_nvme_async_event_completion async_events[SPDK_NVMF_MIGR_MAX_PENDING_AERS];
     660             :         uint16_t aer_cids[SPDK_NVMF_MAX_ASYNC_EVENTS];
     661             :         uint64_t notice_aen_mask;
     662             : 
     663             :         uint8_t unused[2516];
     664             : };
     665             : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
     666             :                             regs) - offsetof(struct spdk_nvmf_ctrlr_migr_data, data_size) == 16, "Incorrect header size");
     667             : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
     668             :                             feat) - offsetof(struct spdk_nvmf_ctrlr_migr_data, regs) == 256, "Incorrect regs size");
     669             : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
     670             :                             cntlid) - offsetof(struct spdk_nvmf_ctrlr_migr_data, feat) == 256, "Incorrect feat size");
     671             : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_ctrlr_migr_data) == 4096, "Incorrect size");
     672             : 
     673             : /**
     674             :  * Save the NVMe-oF controller state and configuration.
     675             :  *
     676             :  * The API is experimental.
     677             :  *
     678             :  * It is allowed to save the data only when the nvmf subsystem is in paused
     679             :  * state i.e. there are no outstanding cmds in nvmf layer (other than aer),
     680             :  * pending async event completions are getting blocked.
     681             :  *
     682             :  * To preserve thread safety this function must be executed on the same thread
     683             :  * the NVMe-OF controller was created.
     684             :  *
     685             :  * \param ctrlr The NVMe-oF controller
     686             :  * \param data The NVMe-oF controller state and configuration to be saved
     687             :  *
     688             :  * \return 0 on success or a negated errno on failure.
     689             :  */
     690             : int spdk_nvmf_ctrlr_save_migr_data(struct spdk_nvmf_ctrlr *ctrlr,
     691             :                                    struct spdk_nvmf_ctrlr_migr_data *data);
     692             : 
     693             : /**
     694             :  * Restore the NVMe-oF controller state and configuration.
     695             :  *
     696             :  * The API is experimental.
     697             :  *
     698             :  * It is allowed to restore the data only when the nvmf subsystem is in paused
     699             :  * state.
     700             :  *
     701             :  * To preserve thread safety this function must be executed on the same thread
     702             :  * the NVMe-OF controller was created.
     703             :  *
     704             :  * AERs shall be restored using spdk_nvmf_request_exec after this function is executed.
     705             :  *
     706             :  * \param ctrlr The NVMe-oF controller
     707             :  * \param data The NVMe-oF controller state and configuration to be restored
     708             :  *
     709             :  * \return 0 on success or a negated errno on failure.
     710             :  */
     711             : int spdk_nvmf_ctrlr_restore_migr_data(struct spdk_nvmf_ctrlr *ctrlr,
     712             :                                       const struct spdk_nvmf_ctrlr_migr_data *data);
     713             : 
     714             : static inline enum spdk_nvme_data_transfer
     715          10 : spdk_nvmf_req_get_xfer(struct spdk_nvmf_request *req) {
     716             :         enum spdk_nvme_data_transfer xfer;
     717          10 :         struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
     718          10 :         struct spdk_nvme_sgl_descriptor *sgl = &cmd->dptr.sgl1;
     719             : 
     720             :         /* Figure out data transfer direction */
     721          10 :         if (cmd->opc == SPDK_NVME_OPC_FABRIC)
     722             :         {
     723           2 :                 xfer = spdk_nvme_opc_get_data_transfer(req->cmd->nvmf_cmd.fctype);
     724             :         } else
     725             :         {
     726           8 :                 xfer = spdk_nvme_opc_get_data_transfer(cmd->opc);
     727             :         }
     728             : 
     729          10 :         if (xfer == SPDK_NVME_DATA_NONE)
     730             :         {
     731           0 :                 return xfer;
     732             :         }
     733             : 
     734             :         /* Even for commands that may transfer data, they could have specified 0 length.
     735             :          * We want those to show up with xfer SPDK_NVME_DATA_NONE.
     736             :          */
     737          10 :         switch (sgl->generic.type)
     738             :         {
     739           4 :         case SPDK_NVME_SGL_TYPE_DATA_BLOCK:
     740             :         case SPDK_NVME_SGL_TYPE_BIT_BUCKET:
     741             :         case SPDK_NVME_SGL_TYPE_SEGMENT:
     742             :         case SPDK_NVME_SGL_TYPE_LAST_SEGMENT:
     743             :         case SPDK_NVME_SGL_TYPE_TRANSPORT_DATA_BLOCK:
     744           4 :                 if (sgl->unkeyed.length == 0) {
     745           0 :                         xfer = SPDK_NVME_DATA_NONE;
     746             :                 }
     747           4 :                 break;
     748           6 :         case SPDK_NVME_SGL_TYPE_KEYED_DATA_BLOCK:
     749           6 :                 if (sgl->keyed.length == 0) {
     750           0 :                         xfer = SPDK_NVME_DATA_NONE;
     751             :                 }
     752           6 :                 break;
     753             :         }
     754             : 
     755          10 :         return xfer;
     756             : }
     757             : 
     758             : /**
     759             :  * Complete Asynchronous Event as Error.
     760             :  *
     761             :  * \param ctrlr Controller whose AER is going to be completed.
     762             :  * \param info Asynchronous Event Error Information to be reported.
     763             :  *
     764             :  * \return int. 0 if it completed successfully, or negative errno if it failed.
     765             :  */
     766             : int spdk_nvmf_ctrlr_async_event_error_event(struct spdk_nvmf_ctrlr *ctrlr,
     767             :                 enum spdk_nvme_async_event_info_error info);
     768             : 
     769             : /**
     770             :  * Abort outstanding Asynchronous Event Requests (AERs).
     771             :  *
     772             :  * Completes AERs with ABORTED_BY_REQUEST status code.
     773             :  *
     774             :  * \param ctrlr Controller whose AERs are going to be aborted.
     775             :  */
     776             : void spdk_nvmf_ctrlr_abort_aer(struct spdk_nvmf_ctrlr *ctrlr);
     777             : 
     778             : /*
     779             :  * Macro used to register new transports.
     780             :  */
     781             : #define SPDK_NVMF_TRANSPORT_REGISTER(name, transport_ops) \
     782             : static void __attribute__((constructor)) _spdk_nvmf_transport_register_##name(void) \
     783             : { \
     784             :         spdk_nvmf_transport_register(transport_ops); \
     785             : }
     786             : 
     787             : #ifdef __cplusplus
     788             : }
     789             : #endif
     790             : 
     791             : #endif

Generated by: LCOV version 1.15