LCOV - code coverage report
Current view: top level - spdk/lib/nvme - nvme_ns_cmd.c (source / functions) Hit Total Coverage
Test: Combined Lines: 492 586 84.0 %
Date: 2024-07-15 22:31:11 Functions: 46 46 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 218 324 67.3 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2015 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  *   Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved.
       5                 :            :  *   Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
       6                 :            :  *   Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
       7                 :            :  */
       8                 :            : 
       9                 :            : #include "nvme_internal.h"
      10                 :            : 
      11                 :            : static inline struct nvme_request *_nvme_ns_cmd_rw(struct spdk_nvme_ns *ns,
      12                 :            :                 struct spdk_nvme_qpair *qpair,
      13                 :            :                 const struct nvme_payload *payload, uint32_t payload_offset, uint32_t md_offset,
      14                 :            :                 uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn,
      15                 :            :                 void *cb_arg, uint32_t opc, uint32_t io_flags,
      16                 :            :                 uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13, bool check_sgl,
      17                 :            :                 void *accel_sequence, int *rc);
      18                 :            : 
      19                 :            : static bool
      20                 :     170461 : nvme_ns_check_request_length(uint32_t lba_count, uint32_t sectors_per_max_io,
      21                 :            :                              uint32_t sectors_per_stripe, uint32_t qdepth)
      22                 :            : {
      23                 :     170461 :         uint32_t child_per_io = UINT32_MAX;
      24                 :            : 
      25                 :            :         /* After a namespace is destroyed(e.g. hotplug), all the fields associated with the
      26                 :            :          * namespace will be cleared to zero, the function will return TRUE for this case,
      27                 :            :          * and -EINVAL will be returned to caller.
      28                 :            :          */
      29         [ -  + ]:     170461 :         if (sectors_per_stripe > 0) {
      30         [ #  # ]:          0 :                 child_per_io = (lba_count + sectors_per_stripe - 1) / sectors_per_stripe;
      31         [ +  + ]:     170461 :         } else if (sectors_per_max_io > 0) {
      32         [ -  + ]:     119519 :                 child_per_io = (lba_count + sectors_per_max_io - 1) / sectors_per_max_io;
      33                 :            :         }
      34                 :            : 
      35   [ -  +  -  + ]:     170461 :         SPDK_DEBUGLOG(nvme, "checking maximum i/o length %d\n", child_per_io);
      36                 :            : 
      37                 :     170461 :         return child_per_io >= qdepth;
      38                 :            : }
      39                 :            : 
      40                 :            : static inline int
      41                 :     170464 : nvme_ns_map_failure_rc(uint32_t lba_count, uint32_t sectors_per_max_io,
      42                 :            :                        uint32_t sectors_per_stripe, uint32_t qdepth, int rc)
      43                 :            : {
      44         [ -  + ]:     170464 :         assert(rc);
      45   [ +  +  +  + ]:     340925 :         if (rc == -ENOMEM &&
      46                 :     170461 :             nvme_ns_check_request_length(lba_count, sectors_per_max_io, sectors_per_stripe, qdepth)) {
      47                 :      50945 :                 return -EINVAL;
      48                 :            :         }
      49                 :     119519 :         return rc;
      50                 :            : }
      51                 :            : 
      52                 :            : static inline bool
      53                 :  134613685 : _nvme_md_excluded_from_xfer(struct spdk_nvme_ns *ns, uint32_t io_flags)
      54                 :            : {
      55                 :  134613790 :         return (io_flags & SPDK_NVME_IO_FLAGS_PRACT) &&
      56         [ +  + ]:        105 :                (ns->flags & SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED) &&
      57   [ +  +  +  - ]:  134613808 :                (ns->flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) &&
      58         [ +  - ]:         18 :                (ns->md_size == 8);
      59                 :            : }
      60                 :            : 
      61                 :            : static inline uint32_t
      62                 :   67531888 : _nvme_get_host_buffer_sector_size(struct spdk_nvme_ns *ns, uint32_t io_flags)
      63                 :            : {
      64                 :   67531888 :         return _nvme_md_excluded_from_xfer(ns, io_flags) ?
      65         [ +  + ]:   67531888 :                ns->sector_size : ns->extended_lba_size;
      66                 :            : }
      67                 :            : 
      68                 :            : static inline uint32_t
      69                 :   67081807 : _nvme_get_sectors_per_max_io(struct spdk_nvme_ns *ns, uint32_t io_flags)
      70                 :            : {
      71                 :   67081807 :         return _nvme_md_excluded_from_xfer(ns, io_flags) ?
      72         [ +  + ]:   67081807 :                ns->sectors_per_max_io_no_md : ns->sectors_per_max_io;
      73                 :            : }
      74                 :            : 
      75                 :            : static struct nvme_request *
      76                 :   26218346 : _nvme_add_child_request(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
      77                 :            :                         const struct nvme_payload *payload,
      78                 :            :                         uint32_t payload_offset, uint32_t md_offset,
      79                 :            :                         uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc,
      80                 :            :                         uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13,
      81                 :            :                         struct nvme_request *parent, bool check_sgl, int *rc)
      82                 :            : {
      83                 :            :         struct nvme_request     *child;
      84                 :            : 
      85                 :   26218346 :         child = _nvme_ns_cmd_rw(ns, qpair, payload, payload_offset, md_offset, lba, lba_count, cb_fn,
      86                 :            :                                 cb_arg, opc, io_flags, apptag_mask, apptag, cdw13, check_sgl, NULL, rc);
      87         [ +  + ]:   26218346 :         if (child == NULL) {
      88                 :      51122 :                 nvme_request_free_children(parent);
      89                 :      51122 :                 nvme_free_request(parent);
      90                 :      51122 :                 return NULL;
      91                 :            :         }
      92                 :            : 
      93                 :   26167224 :         nvme_request_add_child(parent, child);
      94                 :   26167224 :         return child;
      95                 :            : }
      96                 :            : 
      97                 :            : static struct nvme_request *
      98                 :     193185 : _nvme_ns_cmd_split_request(struct spdk_nvme_ns *ns,
      99                 :            :                            struct spdk_nvme_qpair *qpair,
     100                 :            :                            const struct nvme_payload *payload,
     101                 :            :                            uint32_t payload_offset, uint32_t md_offset,
     102                 :            :                            uint64_t lba, uint32_t lba_count,
     103                 :            :                            spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc,
     104                 :            :                            uint32_t io_flags, struct nvme_request *req,
     105                 :            :                            uint32_t sectors_per_max_io, uint32_t sector_mask,
     106                 :            :                            uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13,
     107                 :            :                            void *accel_sequence, int *rc)
     108                 :            : {
     109                 :     193185 :         uint32_t                sector_size = _nvme_get_host_buffer_sector_size(ns, io_flags);
     110                 :     193185 :         uint32_t                remaining_lba_count = lba_count;
     111                 :            :         struct nvme_request     *child;
     112                 :            : 
     113         [ -  + ]:     193185 :         if (spdk_unlikely(accel_sequence != NULL)) {
     114                 :          0 :                 SPDK_ERRLOG("Splitting requests with accel sequence is unsupported\n");
     115                 :          0 :                 *rc = -EINVAL;
     116                 :          0 :                 return NULL;
     117                 :            :         }
     118                 :            : 
     119         [ +  + ]:   26360231 :         while (remaining_lba_count > 0) {
     120                 :   26218168 :                 lba_count = sectors_per_max_io - (lba & sector_mask);
     121                 :   26218168 :                 lba_count = spdk_min(remaining_lba_count, lba_count);
     122                 :            : 
     123                 :   26218168 :                 child = _nvme_add_child_request(ns, qpair, payload, payload_offset, md_offset,
     124                 :            :                                                 lba, lba_count, cb_fn, cb_arg, opc,
     125                 :            :                                                 io_flags, apptag_mask, apptag, cdw13, req, true, rc);
     126         [ +  + ]:   26218168 :                 if (child == NULL) {
     127                 :      51122 :                         return NULL;
     128                 :            :                 }
     129                 :            : 
     130                 :   26167046 :                 remaining_lba_count -= lba_count;
     131                 :   26167046 :                 lba += lba_count;
     132                 :   26167046 :                 payload_offset += lba_count * sector_size;
     133                 :   26167046 :                 md_offset += lba_count * ns->md_size;
     134                 :            :         }
     135                 :            : 
     136                 :     142063 :         return req;
     137                 :            : }
     138                 :            : 
     139                 :            : static inline bool
     140                 :  108230208 : _is_io_flags_valid(uint32_t io_flags)
     141                 :            : {
     142         [ +  + ]:  108230208 :         if (spdk_unlikely(io_flags & ~SPDK_NVME_IO_FLAGS_VALID_MASK)) {
     143                 :            :                 /* Invalid io_flags */
     144                 :          9 :                 SPDK_ERRLOG("Invalid io_flags 0x%x\n", io_flags);
     145                 :          9 :                 return false;
     146                 :            :         }
     147                 :            : 
     148                 :  108230199 :         return true;
     149                 :            : }
     150                 :            : 
     151                 :            : static inline bool
     152                 :     549603 : _is_accel_sequence_valid(struct spdk_nvme_qpair *qpair, void *seq)
     153                 :            : {
     154                 :            :         /* An accel sequence can only be executed if the controller supports accel and a qpair is
     155                 :            :          * part of a of a poll group */
     156   [ +  +  +  -  :     549603 :         if (spdk_likely(seq == NULL || ((qpair->ctrlr->flags & SPDK_NVME_CTRLR_ACCEL_SEQUENCE_SUPPORTED) &&
             +  -  +  - ]
     157                 :            :                                         qpair->poll_group != NULL))) {
     158                 :     549603 :                 return true;
     159                 :            :         }
     160                 :            : 
     161                 :          0 :         return false;
     162                 :            : }
     163                 :            : 
     164                 :            : static void
     165                 :   66718140 : _nvme_ns_cmd_setup_request(struct spdk_nvme_ns *ns, struct nvme_request *req,
     166                 :            :                            uint32_t opc, uint64_t lba, uint32_t lba_count,
     167                 :            :                            uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag,
     168                 :            :                            uint32_t cdw13)
     169                 :            : {
     170                 :            :         struct spdk_nvme_cmd    *cmd;
     171                 :            : 
     172         [ -  + ]:   66718140 :         assert(_is_io_flags_valid(io_flags));
     173                 :            : 
     174                 :   66718140 :         cmd = &req->cmd;
     175                 :   66718140 :         cmd->opc = opc;
     176                 :   66718140 :         cmd->nsid = ns->id;
     177                 :            : 
     178                 :   66718140 :         *(uint64_t *)&cmd->cdw10 = lba;
     179                 :            : 
     180         [ +  + ]:   66718140 :         if (ns->flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) {
     181         [ +  + ]:         39 :                 switch (ns->pi_type) {
     182                 :          3 :                 case SPDK_NVME_FMT_NVM_PROTECTION_TYPE1:
     183                 :            :                 case SPDK_NVME_FMT_NVM_PROTECTION_TYPE2:
     184                 :          3 :                         cmd->cdw14 = (uint32_t)lba;
     185                 :          3 :                         break;
     186                 :            :                 }
     187                 :    1628892 :         }
     188                 :            : 
     189                 :   66718140 :         cmd->fuse = (io_flags & SPDK_NVME_IO_FLAGS_FUSE_MASK);
     190                 :            : 
     191                 :   66718140 :         cmd->cdw12 = lba_count - 1;
     192                 :   66718140 :         cmd->cdw12 |= (io_flags & SPDK_NVME_IO_FLAGS_CDW12_MASK);
     193                 :            : 
     194                 :   66718140 :         cmd->cdw13 = cdw13;
     195                 :            : 
     196                 :   66718140 :         cmd->cdw15 = apptag_mask;
     197                 :   66718140 :         cmd->cdw15 = (cmd->cdw15 << 16 | apptag);
     198                 :   66718140 : }
     199                 :            : 
     200                 :            : static struct nvme_request *
     201                 :     199468 : _nvme_ns_cmd_split_request_prp(struct spdk_nvme_ns *ns,
     202                 :            :                                struct spdk_nvme_qpair *qpair,
     203                 :            :                                const struct nvme_payload *payload,
     204                 :            :                                uint32_t payload_offset, uint32_t md_offset,
     205                 :            :                                uint64_t lba, uint32_t lba_count,
     206                 :            :                                spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc,
     207                 :            :                                uint32_t io_flags, struct nvme_request *req,
     208                 :            :                                uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13,
     209                 :            :                                void *accel_sequence, int *rc)
     210                 :            : {
     211                 :     199468 :         spdk_nvme_req_reset_sgl_cb reset_sgl_fn = req->payload.reset_sgl_fn;
     212                 :     199468 :         spdk_nvme_req_next_sge_cb next_sge_fn = req->payload.next_sge_fn;
     213                 :     199468 :         void *sgl_cb_arg = req->payload.contig_or_cb_arg;
     214                 :            :         bool start_valid, end_valid, last_sge, child_equals_parent;
     215                 :     199468 :         uint64_t child_lba = lba;
     216                 :     199468 :         uint32_t req_current_length = 0;
     217                 :     199468 :         uint32_t child_length = 0;
     218                 :     173126 :         uint32_t sge_length;
     219                 :     199468 :         uint32_t page_size = qpair->ctrlr->page_size;
     220                 :     173126 :         uintptr_t address;
     221                 :            : 
     222                 :     199468 :         reset_sgl_fn(sgl_cb_arg, payload_offset);
     223                 :     199468 :         next_sge_fn(sgl_cb_arg, (void **)&address, &sge_length);
     224         [ +  + ]:    1169835 :         while (req_current_length < req->payload_size) {
     225                 :            : 
     226         [ -  + ]:     970370 :                 if (sge_length == 0) {
     227                 :          0 :                         continue;
     228         [ +  + ]:     970370 :                 } else if (req_current_length + sge_length > req->payload_size) {
     229                 :      55284 :                         sge_length = req->payload_size - req_current_length;
     230                 :            :                 }
     231                 :            : 
     232                 :            :                 /*
     233                 :            :                  * The start of the SGE is invalid if the start address is not page aligned,
     234                 :            :                  *  unless it is the first SGE in the child request.
     235                 :            :                  */
     236   [ +  +  +  - ]:     970370 :                 start_valid = child_length == 0 || _is_page_aligned(address, page_size);
     237                 :            : 
     238                 :            :                 /* Boolean for whether this is the last SGE in the parent request. */
     239                 :     970370 :                 last_sge = (req_current_length + sge_length == req->payload_size);
     240                 :            : 
     241                 :            :                 /*
     242                 :            :                  * The end of the SGE is invalid if the end address is not page aligned,
     243                 :            :                  *  unless it is the last SGE in the parent request.
     244                 :            :                  */
     245   [ +  +  +  + ]:     970370 :                 end_valid = last_sge || _is_page_aligned(address + sge_length, page_size);
     246                 :            : 
     247                 :            :                 /*
     248                 :            :                  * This child request equals the parent request, meaning that no splitting
     249                 :            :                  *  was required for the parent request (the one passed into this function).
     250                 :            :                  *  In this case, we do not create a child request at all - we just send
     251                 :            :                  *  the original request as a single request at the end of this function.
     252                 :            :                  */
     253                 :     970370 :                 child_equals_parent = (child_length + sge_length == req->payload_size);
     254                 :            : 
     255         [ +  - ]:     970370 :                 if (start_valid) {
     256                 :            :                         /*
     257                 :            :                          * The start of the SGE is valid, so advance the length parameters,
     258                 :            :                          *  to include this SGE with previous SGEs for this child request
     259                 :            :                          *  (if any).  If it is not valid, we do not advance the length
     260                 :            :                          *  parameters nor get the next SGE, because we must send what has
     261                 :            :                          *  been collected before this SGE as a child request.
     262                 :            :                          */
     263                 :     970370 :                         child_length += sge_length;
     264                 :     970370 :                         req_current_length += sge_length;
     265         [ +  + ]:     970370 :                         if (req_current_length < req->payload_size) {
     266                 :     770905 :                                 next_sge_fn(sgl_cb_arg, (void **)&address, &sge_length);
     267                 :            :                                 /*
     268                 :            :                                  * If the next SGE is not page aligned, we will need to create a
     269                 :            :                                  *  child request for what we have so far, and then start a new
     270                 :            :                                  *  child request for the next SGE.
     271                 :            :                                  */
     272                 :     770905 :                                 start_valid = _is_page_aligned(address, page_size);
     273                 :            :                         }
     274                 :            :                 }
     275                 :            : 
     276   [ +  +  +  +  :     970370 :                 if (start_valid && end_valid && !last_sge) {
                   +  + ]
     277                 :     770736 :                         continue;
     278                 :            :                 }
     279                 :            : 
     280                 :            :                 /*
     281                 :            :                  * We need to create a split here.  Send what we have accumulated so far as a child
     282                 :            :                  *  request.  Checking if child_equals_parent allows us to *not* create a child request
     283                 :            :                  *  when no splitting is required - in that case we will fall-through and just create
     284                 :            :                  *  a single request with no children for the entire I/O.
     285                 :            :                  */
     286         [ +  + ]:     199634 :                 if (!child_equals_parent) {
     287                 :            :                         struct nvme_request *child;
     288                 :            :                         uint32_t child_lba_count;
     289                 :            : 
     290   [ +  +  +  + ]:        181 :                         if ((child_length % ns->extended_lba_size) != 0) {
     291                 :          3 :                                 SPDK_ERRLOG("child_length %u not even multiple of lba_size %u\n",
     292                 :            :                                             child_length, ns->extended_lba_size);
     293                 :          3 :                                 *rc = -EINVAL;
     294                 :          3 :                                 return NULL;
     295                 :            :                         }
     296         [ -  + ]:        178 :                         if (spdk_unlikely(accel_sequence != NULL)) {
     297                 :          0 :                                 SPDK_ERRLOG("Splitting requests with accel sequence is unsupported\n");
     298                 :          0 :                                 *rc = -EINVAL;
     299                 :          0 :                                 return NULL;
     300                 :            :                         }
     301                 :            : 
     302         [ -  + ]:        178 :                         child_lba_count = child_length / ns->extended_lba_size;
     303                 :            :                         /*
     304                 :            :                          * Note the last parameter is set to "false" - this tells the recursive
     305                 :            :                          *  call to _nvme_ns_cmd_rw() to not bother with checking for SGL splitting
     306                 :            :                          *  since we have already verified it here.
     307                 :            :                          */
     308                 :        178 :                         child = _nvme_add_child_request(ns, qpair, payload, payload_offset, md_offset,
     309                 :            :                                                         child_lba, child_lba_count,
     310                 :            :                                                         cb_fn, cb_arg, opc, io_flags,
     311                 :            :                                                         apptag_mask, apptag, cdw13, req, false, rc);
     312         [ -  + ]:        178 :                         if (child == NULL) {
     313                 :          0 :                                 return NULL;
     314                 :            :                         }
     315                 :        178 :                         payload_offset += child_length;
     316                 :        178 :                         md_offset += child_lba_count * ns->md_size;
     317                 :        178 :                         child_lba += child_lba_count;
     318                 :        178 :                         child_length = 0;
     319                 :            :                 }
     320                 :            :         }
     321                 :            : 
     322         [ +  + ]:     199465 :         if (child_length == req->payload_size) {
     323                 :            :                 /* No splitting was required, so setup the whole payload as one request. */
     324                 :     199453 :                 _nvme_ns_cmd_setup_request(ns, req, opc, lba, lba_count, io_flags, apptag_mask, apptag, cdw13);
     325                 :            :         }
     326                 :            : 
     327                 :     199465 :         return req;
     328                 :            : }
     329                 :            : 
     330                 :            : static struct nvme_request *
     331                 :     345700 : _nvme_ns_cmd_split_request_sgl(struct spdk_nvme_ns *ns,
     332                 :            :                                struct spdk_nvme_qpair *qpair,
     333                 :            :                                const struct nvme_payload *payload,
     334                 :            :                                uint32_t payload_offset, uint32_t md_offset,
     335                 :            :                                uint64_t lba, uint32_t lba_count,
     336                 :            :                                spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc,
     337                 :            :                                uint32_t io_flags, struct nvme_request *req,
     338                 :            :                                uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13,
     339                 :            :                                void *accel_sequence, int *rc)
     340                 :            : {
     341                 :     345700 :         spdk_nvme_req_reset_sgl_cb reset_sgl_fn = req->payload.reset_sgl_fn;
     342                 :     345700 :         spdk_nvme_req_next_sge_cb next_sge_fn = req->payload.next_sge_fn;
     343                 :     345700 :         void *sgl_cb_arg = req->payload.contig_or_cb_arg;
     344                 :     345700 :         uint64_t child_lba = lba;
     345                 :     345700 :         uint32_t req_current_length = 0;
     346                 :     345700 :         uint32_t child_length = 0;
     347                 :     162625 :         uint32_t sge_length;
     348                 :            :         uint16_t max_sges, num_sges;
     349                 :     162625 :         uintptr_t address;
     350                 :            : 
     351                 :     345700 :         max_sges = ns->ctrlr->max_sges;
     352                 :            : 
     353                 :     345700 :         reset_sgl_fn(sgl_cb_arg, payload_offset);
     354                 :     345700 :         num_sges = 0;
     355                 :            : 
     356         [ +  + ]:    1567367 :         while (req_current_length < req->payload_size) {
     357                 :    1221667 :                 next_sge_fn(sgl_cb_arg, (void **)&address, &sge_length);
     358                 :            : 
     359         [ +  + ]:    1221667 :                 if (req_current_length + sge_length > req->payload_size) {
     360                 :        479 :                         sge_length = req->payload_size - req_current_length;
     361                 :            :                 }
     362                 :            : 
     363                 :    1221667 :                 child_length += sge_length;
     364                 :    1221667 :                 req_current_length += sge_length;
     365                 :    1221667 :                 num_sges++;
     366                 :            : 
     367   [ +  +  +  + ]:    1221667 :                 if (num_sges < max_sges && req_current_length < req->payload_size) {
     368                 :     875967 :                         continue;
     369                 :            :                 }
     370                 :            : 
     371                 :            :                 /*
     372                 :            :                  * We need to create a split here.  Send what we have accumulated so far as a child
     373                 :            :                  *  request.  Checking if the child equals the full payload allows us to *not*
     374                 :            :                  *  create a child request when no splitting is required - in that case we will
     375                 :            :                  *  fall-through and just create a single request with no children for the entire I/O.
     376                 :            :                  */
     377         [ -  + ]:     345700 :                 if (child_length != req->payload_size) {
     378                 :            :                         struct nvme_request *child;
     379                 :            :                         uint32_t child_lba_count;
     380                 :            : 
     381   [ #  #  #  # ]:          0 :                         if ((child_length % ns->extended_lba_size) != 0) {
     382                 :          0 :                                 SPDK_ERRLOG("child_length %u not even multiple of lba_size %u\n",
     383                 :            :                                             child_length, ns->extended_lba_size);
     384                 :          0 :                                 *rc = -EINVAL;
     385                 :          0 :                                 return NULL;
     386                 :            :                         }
     387         [ #  # ]:          0 :                         if (spdk_unlikely(accel_sequence != NULL)) {
     388                 :          0 :                                 SPDK_ERRLOG("Splitting requests with accel sequence is unsupported\n");
     389                 :          0 :                                 *rc = -EINVAL;
     390                 :          0 :                                 return NULL;
     391                 :            :                         }
     392                 :            : 
     393         [ #  # ]:          0 :                         child_lba_count = child_length / ns->extended_lba_size;
     394                 :            :                         /*
     395                 :            :                          * Note the last parameter is set to "false" - this tells the recursive
     396                 :            :                          *  call to _nvme_ns_cmd_rw() to not bother with checking for SGL splitting
     397                 :            :                          *  since we have already verified it here.
     398                 :            :                          */
     399                 :          0 :                         child = _nvme_add_child_request(ns, qpair, payload, payload_offset, md_offset,
     400                 :            :                                                         child_lba, child_lba_count,
     401                 :            :                                                         cb_fn, cb_arg, opc, io_flags,
     402                 :            :                                                         apptag_mask, apptag, cdw13, req, false, rc);
     403         [ #  # ]:          0 :                         if (child == NULL) {
     404                 :          0 :                                 return NULL;
     405                 :            :                         }
     406                 :          0 :                         payload_offset += child_length;
     407                 :          0 :                         md_offset += child_lba_count * ns->md_size;
     408                 :          0 :                         child_lba += child_lba_count;
     409                 :          0 :                         child_length = 0;
     410                 :          0 :                         num_sges = 0;
     411                 :            :                 }
     412                 :            :         }
     413                 :            : 
     414         [ +  - ]:     345700 :         if (child_length == req->payload_size) {
     415                 :            :                 /* No splitting was required, so setup the whole payload as one request. */
     416                 :     345700 :                 _nvme_ns_cmd_setup_request(ns, req, opc, lba, lba_count, io_flags, apptag_mask, apptag, cdw13);
     417                 :            :         }
     418                 :            : 
     419                 :     345700 :         return req;
     420                 :            : }
     421                 :            : 
     422                 :            : static inline struct nvme_request *
     423                 :   67081807 : _nvme_ns_cmd_rw(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
     424                 :            :                 const struct nvme_payload *payload, uint32_t payload_offset, uint32_t md_offset,
     425                 :            :                 uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc,
     426                 :            :                 uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13, bool check_sgl,
     427                 :            :                 void *accel_sequence, int *rc)
     428                 :            : {
     429                 :            :         struct nvme_request     *req;
     430                 :   67081807 :         uint32_t                sector_size = _nvme_get_host_buffer_sector_size(ns, io_flags);
     431                 :   67081807 :         uint32_t                sectors_per_max_io = _nvme_get_sectors_per_max_io(ns, io_flags);
     432                 :   67081807 :         uint32_t                sectors_per_stripe = ns->sectors_per_stripe;
     433                 :            : 
     434         [ -  + ]:   67081807 :         assert(rc != NULL);
     435         [ -  + ]:   67081807 :         assert(*rc == 0);
     436                 :            : 
     437                 :   67081807 :         req = nvme_allocate_request(qpair, payload, lba_count * sector_size, lba_count * ns->md_size,
     438                 :            :                                     cb_fn, cb_arg);
     439         [ +  + ]:   67081807 :         if (req == NULL) {
     440                 :     170461 :                 *rc = -ENOMEM;
     441                 :     170461 :                 return NULL;
     442                 :            :         }
     443                 :            : 
     444                 :   66911346 :         req->payload_offset = payload_offset;
     445                 :   66911346 :         req->md_offset = md_offset;
     446                 :   66911346 :         req->accel_sequence = accel_sequence;
     447                 :            : 
     448                 :            :         /* Zone append commands cannot be split. */
     449         [ +  + ]:   66911346 :         if (opc == SPDK_NVME_OPC_ZONE_APPEND) {
     450         [ -  + ]:     256888 :                 assert(ns->csi == SPDK_NVME_CSI_ZNS);
     451                 :            :                 /*
     452                 :            :                  * As long as we disable driver-assisted striping for Zone append commands,
     453                 :            :                  * _nvme_ns_cmd_rw() should never cause a proper request to be split.
     454                 :            :                  * If a request is split, after all, error handling is done in caller functions.
     455                 :            :                  */
     456                 :     256888 :                 sectors_per_stripe = 0;
     457                 :            :         }
     458                 :            : 
     459                 :            :         /*
     460                 :            :          * Intel DC P3*00 NVMe controllers benefit from driver-assisted striping.
     461                 :            :          * If this controller defines a stripe boundary and this I/O spans a stripe
     462                 :            :          *  boundary, split the request into multiple requests and submit each
     463                 :            :          *  separately to hardware.
     464                 :            :          */
     465         [ +  + ]:   66911346 :         if (sectors_per_stripe > 0 &&
     466         [ +  + ]:    7988629 :             (((lba & (sectors_per_stripe - 1)) + lba_count) > sectors_per_stripe)) {
     467                 :      72703 :                 return _nvme_ns_cmd_split_request(ns, qpair, payload, payload_offset, md_offset, lba, lba_count,
     468                 :            :                                                   cb_fn,
     469                 :            :                                                   cb_arg, opc,
     470                 :            :                                                   io_flags, req, sectors_per_stripe, sectors_per_stripe - 1,
     471                 :            :                                                   apptag_mask, apptag, cdw13,  accel_sequence, rc);
     472         [ +  + ]:   66838643 :         } else if (lba_count > sectors_per_max_io) {
     473                 :     120482 :                 return _nvme_ns_cmd_split_request(ns, qpair, payload, payload_offset, md_offset, lba, lba_count,
     474                 :            :                                                   cb_fn,
     475                 :            :                                                   cb_arg, opc,
     476                 :            :                                                   io_flags, req, sectors_per_max_io, 0, apptag_mask,
     477                 :            :                                                   apptag, cdw13, accel_sequence, rc);
     478   [ +  +  +  + ]:   66718152 :         } else if (nvme_payload_type(&req->payload) == NVME_PAYLOAD_TYPE_SGL && check_sgl) {
     479         [ +  + ]:     545168 :                 if (ns->ctrlr->flags & SPDK_NVME_CTRLR_SGL_SUPPORTED) {
     480                 :     345700 :                         return _nvme_ns_cmd_split_request_sgl(ns, qpair, payload, payload_offset, md_offset,
     481                 :            :                                                               lba, lba_count, cb_fn, cb_arg, opc, io_flags,
     482                 :            :                                                               req, apptag_mask, apptag, cdw13,
     483                 :            :                                                               accel_sequence, rc);
     484                 :            :                 } else {
     485                 :     199468 :                         return _nvme_ns_cmd_split_request_prp(ns, qpair, payload, payload_offset, md_offset,
     486                 :            :                                                               lba, lba_count, cb_fn, cb_arg, opc, io_flags,
     487                 :            :                                                               req, apptag_mask, apptag, cdw13,
     488                 :            :                                                               accel_sequence, rc);
     489                 :            :                 }
     490                 :            :         }
     491                 :            : 
     492                 :   66172993 :         _nvme_ns_cmd_setup_request(ns, req, opc, lba, lba_count, io_flags, apptag_mask, apptag, cdw13);
     493                 :   66172993 :         return req;
     494                 :            : }
     495                 :            : 
     496                 :            : int
     497                 :       3075 : spdk_nvme_ns_cmd_compare(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
     498                 :            :                          uint64_t lba,
     499                 :            :                          uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
     500                 :            :                          uint32_t io_flags)
     501                 :            : {
     502                 :            :         struct nvme_request *req;
     503                 :          3 :         struct nvme_payload payload;
     504                 :       3075 :         int rc = 0;
     505                 :            : 
     506         [ -  + ]:       3075 :         if (!_is_io_flags_valid(io_flags)) {
     507                 :          0 :                 return -EINVAL;
     508                 :            :         }
     509                 :            : 
     510                 :       3075 :         payload = NVME_PAYLOAD_CONTIG(buffer, NULL);
     511                 :            : 
     512                 :       3075 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg,
     513                 :            :                               SPDK_NVME_OPC_COMPARE,
     514                 :            :                               io_flags, 0,
     515                 :            :                               0, 0, false, NULL, &rc);
     516         [ +  - ]:       3075 :         if (req != NULL) {
     517                 :       3075 :                 return nvme_qpair_submit_request(qpair, req);
     518                 :            :         } else {
     519                 :          0 :                 return nvme_ns_map_failure_rc(lba_count,
     520                 :            :                                               ns->sectors_per_max_io,
     521                 :            :                                               ns->sectors_per_stripe,
     522                 :          0 :                                               qpair->ctrlr->opts.io_queue_requests,
     523                 :            :                                               rc);
     524                 :            :         }
     525                 :            : }
     526                 :            : 
     527                 :            : int
     528                 :         18 : spdk_nvme_ns_cmd_compare_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
     529                 :            :                                  void *buffer,
     530                 :            :                                  void *metadata,
     531                 :            :                                  uint64_t lba,
     532                 :            :                                  uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
     533                 :            :                                  uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
     534                 :            : {
     535                 :            :         struct nvme_request *req;
     536                 :         18 :         struct nvme_payload payload;
     537                 :         18 :         int rc = 0;
     538                 :            : 
     539         [ -  + ]:         18 :         if (!_is_io_flags_valid(io_flags)) {
     540                 :          0 :                 return -EINVAL;
     541                 :            :         }
     542                 :            : 
     543                 :         18 :         payload = NVME_PAYLOAD_CONTIG(buffer, metadata);
     544                 :            : 
     545                 :         18 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg,
     546                 :            :                               SPDK_NVME_OPC_COMPARE,
     547                 :            :                               io_flags,
     548                 :            :                               apptag_mask, apptag, 0, false, NULL, &rc);
     549         [ +  - ]:         18 :         if (req != NULL) {
     550                 :         18 :                 return nvme_qpair_submit_request(qpair, req);
     551                 :            :         } else {
     552                 :          0 :                 return nvme_ns_map_failure_rc(lba_count,
     553                 :            :                                               ns->sectors_per_max_io,
     554                 :            :                                               ns->sectors_per_stripe,
     555                 :          0 :                                               qpair->ctrlr->opts.io_queue_requests,
     556                 :            :                                               rc);
     557                 :            :         }
     558                 :            : }
     559                 :            : 
     560                 :            : int
     561                 :          6 : spdk_nvme_ns_cmd_comparev(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
     562                 :            :                           uint64_t lba, uint32_t lba_count,
     563                 :            :                           spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
     564                 :            :                           spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
     565                 :            :                           spdk_nvme_req_next_sge_cb next_sge_fn)
     566                 :            : {
     567                 :            :         struct nvme_request *req;
     568                 :          6 :         struct nvme_payload payload;
     569                 :          6 :         int rc = 0;
     570                 :            : 
     571         [ -  + ]:          6 :         if (!_is_io_flags_valid(io_flags)) {
     572                 :          0 :                 return -EINVAL;
     573                 :            :         }
     574                 :            : 
     575   [ +  -  +  + ]:          6 :         if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
     576                 :          3 :                 return -EINVAL;
     577                 :            :         }
     578                 :            : 
     579                 :          3 :         payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL);
     580                 :            : 
     581                 :          3 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg,
     582                 :            :                               SPDK_NVME_OPC_COMPARE,
     583                 :            :                               io_flags, 0, 0, 0, true, NULL, &rc);
     584         [ +  - ]:          3 :         if (req != NULL) {
     585                 :          3 :                 return nvme_qpair_submit_request(qpair, req);
     586                 :            :         } else {
     587                 :          0 :                 return nvme_ns_map_failure_rc(lba_count,
     588                 :            :                                               ns->sectors_per_max_io,
     589                 :            :                                               ns->sectors_per_stripe,
     590                 :          0 :                                               qpair->ctrlr->opts.io_queue_requests,
     591                 :            :                                               rc);
     592                 :            :         }
     593                 :            : }
     594                 :            : 
     595                 :            : int
     596                 :        101 : spdk_nvme_ns_cmd_comparev_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
     597                 :            :                                   uint64_t lba, uint32_t lba_count,
     598                 :            :                                   spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
     599                 :            :                                   spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
     600                 :            :                                   spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
     601                 :            :                                   uint16_t apptag_mask, uint16_t apptag)
     602                 :            : {
     603                 :            :         struct nvme_request *req;
     604                 :         50 :         struct nvme_payload payload;
     605                 :        101 :         int rc = 0;
     606                 :            : 
     607         [ -  + ]:        101 :         if (!_is_io_flags_valid(io_flags)) {
     608                 :          0 :                 return -EINVAL;
     609                 :            :         }
     610                 :            : 
     611   [ +  -  -  + ]:        101 :         if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
     612                 :          0 :                 return -EINVAL;
     613                 :            :         }
     614                 :            : 
     615                 :        101 :         payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, metadata);
     616                 :            : 
     617                 :        101 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg,
     618                 :            :                               SPDK_NVME_OPC_COMPARE, io_flags, apptag_mask, apptag, 0, true,
     619                 :            :                               NULL, &rc);
     620         [ +  - ]:        101 :         if (req != NULL) {
     621                 :        101 :                 return nvme_qpair_submit_request(qpair, req);
     622                 :            :         } else {
     623                 :          0 :                 return nvme_ns_map_failure_rc(lba_count,
     624                 :            :                                               ns->sectors_per_max_io,
     625                 :            :                                               ns->sectors_per_stripe,
     626                 :          0 :                                               qpair->ctrlr->opts.io_queue_requests,
     627                 :            :                                               rc);
     628                 :            :         }
     629                 :            : }
     630                 :            : 
     631                 :            : int
     632                 :    1795591 : spdk_nvme_ns_cmd_read(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
     633                 :            :                       uint64_t lba,
     634                 :            :                       uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
     635                 :            :                       uint32_t io_flags)
     636                 :            : {
     637                 :            :         struct nvme_request *req;
     638                 :     257381 :         struct nvme_payload payload;
     639                 :    1795591 :         int rc = 0;
     640                 :            : 
     641         [ -  + ]:    1795591 :         if (!_is_io_flags_valid(io_flags)) {
     642                 :          0 :                 return -EINVAL;
     643                 :            :         }
     644                 :            : 
     645                 :    1795591 :         payload = NVME_PAYLOAD_CONTIG(buffer, NULL);
     646                 :            : 
     647                 :    1795591 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ,
     648                 :            :                               io_flags, 0,
     649                 :            :                               0, 0, false, NULL, &rc);
     650         [ +  + ]:    1795591 :         if (req != NULL) {
     651                 :    1795588 :                 return nvme_qpair_submit_request(qpair, req);
     652                 :            :         } else {
     653                 :          3 :                 return nvme_ns_map_failure_rc(lba_count,
     654                 :            :                                               ns->sectors_per_max_io,
     655                 :            :                                               ns->sectors_per_stripe,
     656                 :          3 :                                               qpair->ctrlr->opts.io_queue_requests,
     657                 :            :                                               rc);
     658                 :            :         }
     659                 :            : }
     660                 :            : 
     661                 :            : int
     662                 :   20577339 : spdk_nvme_ns_cmd_read_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
     663                 :            :                               void *metadata,
     664                 :            :                               uint64_t lba,
     665                 :            :                               uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
     666                 :            :                               uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
     667                 :            : {
     668                 :            :         struct nvme_request *req;
     669                 :    6083728 :         struct nvme_payload payload;
     670                 :   20577339 :         int rc = 0;
     671                 :            : 
     672         [ -  + ]:   20577339 :         if (!_is_io_flags_valid(io_flags)) {
     673                 :          0 :                 return -EINVAL;
     674                 :            :         }
     675                 :            : 
     676                 :   20577339 :         payload = NVME_PAYLOAD_CONTIG(buffer, metadata);
     677                 :            : 
     678                 :   20577339 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ,
     679                 :            :                               io_flags,
     680                 :            :                               apptag_mask, apptag, 0, false, NULL, &rc);
     681         [ +  + ]:   20577339 :         if (req != NULL) {
     682                 :   20466578 :                 return nvme_qpair_submit_request(qpair, req);
     683                 :            :         } else {
     684                 :     110761 :                 return nvme_ns_map_failure_rc(lba_count,
     685                 :            :                                               ns->sectors_per_max_io,
     686                 :            :                                               ns->sectors_per_stripe,
     687                 :     110761 :                                               qpair->ctrlr->opts.io_queue_requests,
     688                 :            :                                               rc);
     689                 :            :         }
     690                 :            : }
     691                 :            : 
     692                 :            : static int
     693                 :     549596 : nvme_ns_cmd_rw_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
     694                 :            :                    uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
     695                 :            :                    struct spdk_nvme_ns_cmd_ext_io_opts *opts, enum spdk_nvme_nvm_opcode opc)
     696                 :            : {
     697                 :            :         struct nvme_request *req;
     698                 :          0 :         struct nvme_payload payload;
     699                 :            :         void *seq;
     700                 :     549596 :         int rc = 0;
     701                 :            : 
     702   [ +  +  -  + ]:     549596 :         assert(opc == SPDK_NVME_OPC_READ || opc == SPDK_NVME_OPC_WRITE);
     703         [ -  + ]:     549596 :         assert(opts);
     704                 :            : 
     705                 :     549596 :         payload = NVME_PAYLOAD_CONTIG(buffer, opts->metadata);
     706                 :            : 
     707         [ -  + ]:     549596 :         if (spdk_unlikely(!_is_io_flags_valid(opts->io_flags))) {
     708                 :          0 :                 return -EINVAL;
     709                 :            :         }
     710                 :            : 
     711   [ +  -  +  - ]:     549596 :         seq = nvme_ns_cmd_get_ext_io_opt(opts, accel_sequence, NULL);
     712         [ -  + ]:     549596 :         if (spdk_unlikely(!_is_accel_sequence_valid(qpair, seq))) {
     713                 :          0 :                 return -EINVAL;
     714                 :            :         }
     715                 :            : 
     716                 :     549596 :         payload.opts = opts;
     717                 :            : 
     718                 :     549596 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, opc, opts->io_flags,
     719                 :     549596 :                               opts->apptag_mask, opts->apptag, 0, false, seq, &rc);
     720         [ -  + ]:     549596 :         if (spdk_unlikely(req == NULL)) {
     721                 :          0 :                 return nvme_ns_map_failure_rc(lba_count,
     722                 :            :                                               ns->sectors_per_max_io,
     723                 :            :                                               ns->sectors_per_stripe,
     724                 :          0 :                                               qpair->ctrlr->opts.io_queue_requests,
     725                 :            :                                               rc);
     726                 :            :         }
     727                 :            : 
     728                 :     549596 :         return nvme_qpair_submit_request(qpair, req);
     729                 :            : }
     730                 :            : 
     731                 :            : int
     732                 :     355330 : spdk_nvme_ns_cmd_read_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
     733                 :            :                           uint64_t lba,
     734                 :            :                           uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
     735                 :            :                           struct spdk_nvme_ns_cmd_ext_io_opts *opts)
     736                 :            : {
     737                 :     355330 :         return nvme_ns_cmd_rw_ext(ns, qpair, buffer, lba, lba_count, cb_fn, cb_arg, opts,
     738                 :            :                                   SPDK_NVME_OPC_READ);
     739                 :            : }
     740                 :            : 
     741                 :            : int
     742                 :         60 : spdk_nvme_ns_cmd_readv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
     743                 :            :                        uint64_t lba, uint32_t lba_count,
     744                 :            :                        spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
     745                 :            :                        spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
     746                 :            :                        spdk_nvme_req_next_sge_cb next_sge_fn)
     747                 :            : {
     748                 :            :         struct nvme_request *req;
     749                 :         30 :         struct nvme_payload payload;
     750                 :         60 :         int rc = 0;
     751                 :            : 
     752         [ -  + ]:         60 :         if (!_is_io_flags_valid(io_flags)) {
     753                 :          0 :                 return -EINVAL;
     754                 :            :         }
     755                 :            : 
     756   [ +  -  +  + ]:         60 :         if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
     757                 :          3 :                 return -EINVAL;
     758                 :            :         }
     759                 :            : 
     760                 :         57 :         payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL);
     761                 :            : 
     762                 :         57 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ,
     763                 :            :                               io_flags, 0, 0, 0, true, NULL, &rc);
     764         [ +  - ]:         57 :         if (req != NULL) {
     765                 :         57 :                 return nvme_qpair_submit_request(qpair, req);
     766                 :            :         } else {
     767                 :          0 :                 return nvme_ns_map_failure_rc(lba_count,
     768                 :            :                                               ns->sectors_per_max_io,
     769                 :            :                                               ns->sectors_per_stripe,
     770                 :          0 :                                               qpair->ctrlr->opts.io_queue_requests,
     771                 :            :                                               rc);
     772                 :            :         }
     773                 :            : }
     774                 :            : 
     775                 :            : int
     776                 :     194987 : spdk_nvme_ns_cmd_readv_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
     777                 :            :                                uint64_t lba, uint32_t lba_count,
     778                 :            :                                spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
     779                 :            :                                spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
     780                 :            :                                spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
     781                 :            :                                uint16_t apptag_mask, uint16_t apptag)
     782                 :            : {
     783                 :            :         struct nvme_request *req;
     784                 :      86288 :         struct nvme_payload payload;
     785                 :     194987 :         int rc = 0;
     786                 :            : 
     787         [ -  + ]:     194987 :         if (!_is_io_flags_valid(io_flags)) {
     788                 :          0 :                 return -EINVAL;
     789                 :            :         }
     790                 :            : 
     791   [ +  -  +  + ]:     194987 :         if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
     792                 :          3 :                 return -EINVAL;
     793                 :            :         }
     794                 :            : 
     795                 :     194984 :         payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, metadata);
     796                 :            : 
     797                 :     194984 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ,
     798                 :            :                               io_flags, apptag_mask, apptag, 0, true, NULL, &rc);
     799         [ +  + ]:     194984 :         if (req != NULL) {
     800                 :     194799 :                 return nvme_qpair_submit_request(qpair, req);
     801                 :            :         } else {
     802                 :        185 :                 return nvme_ns_map_failure_rc(lba_count,
     803                 :            :                                               ns->sectors_per_max_io,
     804                 :            :                                               ns->sectors_per_stripe,
     805                 :        185 :                                               qpair->ctrlr->opts.io_queue_requests,
     806                 :            :                                               rc);
     807                 :            :         }
     808                 :            : }
     809                 :            : 
     810                 :            : static int
     811                 :         25 : nvme_ns_cmd_rwv_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t lba,
     812                 :            :                     uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
     813                 :            :                     spdk_nvme_req_next_sge_cb next_sge_fn, struct spdk_nvme_ns_cmd_ext_io_opts *opts,
     814                 :            :                     enum spdk_nvme_nvm_opcode opc)
     815                 :            : {
     816                 :            :         struct nvme_request *req;
     817                 :         25 :         struct nvme_payload payload;
     818                 :            :         void *seq;
     819                 :         25 :         int rc = 0;
     820                 :            : 
     821   [ +  +  -  + ]:         25 :         assert(opc == SPDK_NVME_OPC_READ || opc == SPDK_NVME_OPC_WRITE);
     822                 :            : 
     823   [ +  +  +  + ]:         25 :         if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
     824                 :         12 :                 return -EINVAL;
     825                 :            :         }
     826                 :            : 
     827                 :         13 :         payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL);
     828                 :            : 
     829         [ +  - ]:         13 :         if (opts) {
     830         [ +  + ]:         13 :                 if (spdk_unlikely(!_is_io_flags_valid(opts->io_flags))) {
     831                 :          6 :                         return -EINVAL;
     832                 :            :                 }
     833                 :            : 
     834   [ +  -  -  + ]:          7 :                 seq = nvme_ns_cmd_get_ext_io_opt(opts, accel_sequence, NULL);
     835         [ -  + ]:          7 :                 if (spdk_unlikely(!_is_accel_sequence_valid(qpair, seq))) {
     836                 :          0 :                         return -EINVAL;
     837                 :            :                 }
     838                 :            : 
     839                 :          7 :                 payload.opts = opts;
     840                 :          7 :                 payload.md = opts->metadata;
     841                 :         12 :                 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, opc, opts->io_flags,
     842                 :          7 :                                       opts->apptag_mask, opts->apptag, opts->cdw13, true, seq, &rc);
     843                 :            : 
     844                 :            :         } else {
     845                 :          0 :                 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, opc, 0, 0, 0, 0,
     846                 :            :                                       true, NULL, &rc);
     847                 :            :         }
     848                 :            : 
     849         [ -  + ]:          7 :         if (req == NULL) {
     850                 :          0 :                 return nvme_ns_map_failure_rc(lba_count,
     851                 :            :                                               ns->sectors_per_max_io,
     852                 :            :                                               ns->sectors_per_stripe,
     853                 :          0 :                                               qpair->ctrlr->opts.io_queue_requests,
     854                 :            :                                               rc);
     855                 :            :         }
     856                 :            : 
     857                 :          7 :         return nvme_qpair_submit_request(qpair, req);
     858                 :            : }
     859                 :            : 
     860                 :            : int
     861                 :         12 : spdk_nvme_ns_cmd_readv_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
     862                 :            :                            uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn,
     863                 :            :                            void *cb_arg, spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
     864                 :            :                            spdk_nvme_req_next_sge_cb next_sge_fn,
     865                 :            :                            struct spdk_nvme_ns_cmd_ext_io_opts *opts)
     866                 :            : {
     867                 :         12 :         return nvme_ns_cmd_rwv_ext(ns, qpair, lba, lba_count, cb_fn, cb_arg, reset_sgl_fn, next_sge_fn,
     868                 :            :                                    opts, SPDK_NVME_OPC_READ);
     869                 :            : }
     870                 :            : 
     871                 :            : int
     872                 :    2886793 : spdk_nvme_ns_cmd_write(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
     873                 :            :                        void *buffer, uint64_t lba,
     874                 :            :                        uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
     875                 :            :                        uint32_t io_flags)
     876                 :            : {
     877                 :            :         struct nvme_request *req;
     878                 :      16000 :         struct nvme_payload payload;
     879                 :    2886793 :         int rc = 0;
     880                 :            : 
     881         [ +  + ]:    2886793 :         if (!_is_io_flags_valid(io_flags)) {
     882                 :          3 :                 return -EINVAL;
     883                 :            :         }
     884                 :            : 
     885                 :    2886790 :         payload = NVME_PAYLOAD_CONTIG(buffer, NULL);
     886                 :            : 
     887                 :    2886790 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE,
     888                 :            :                               io_flags, 0, 0, 0, false, NULL, &rc);
     889         [ +  - ]:    2886790 :         if (req != NULL) {
     890                 :    2886790 :                 return nvme_qpair_submit_request(qpair, req);
     891                 :            :         } else {
     892                 :          0 :                 return nvme_ns_map_failure_rc(lba_count,
     893                 :            :                                               ns->sectors_per_max_io,
     894                 :            :                                               ns->sectors_per_stripe,
     895                 :          0 :                                               qpair->ctrlr->opts.io_queue_requests,
     896                 :            :                                               rc);
     897                 :            :         }
     898                 :            : }
     899                 :            : 
     900                 :            : static int
     901                 :     256897 : nvme_ns_cmd_check_zone_append(struct spdk_nvme_ns *ns, uint32_t lba_count, uint32_t io_flags)
     902                 :            : {
     903                 :            :         uint32_t sector_size;
     904                 :            : 
     905                 :            :         /* Not all NVMe Zoned Namespaces support the zone append command. */
     906         [ -  + ]:     256897 :         if (!(ns->ctrlr->flags & SPDK_NVME_CTRLR_ZONE_APPEND_SUPPORTED)) {
     907                 :          0 :                 return -EINVAL;
     908                 :            :         }
     909                 :            : 
     910                 :     256897 :         sector_size =  _nvme_get_host_buffer_sector_size(ns, io_flags);
     911                 :            : 
     912                 :            :         /* Fail a too large zone append command early. */
     913         [ +  + ]:     256897 :         if (lba_count * sector_size > ns->ctrlr->max_zone_append_size) {
     914                 :          9 :                 return -EINVAL;
     915                 :            :         }
     916                 :            : 
     917                 :     256888 :         return 0;
     918                 :            : }
     919                 :            : 
     920                 :            : int
     921                 :     256891 : nvme_ns_cmd_zone_append_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
     922                 :            :                                 void *buffer, void *metadata, uint64_t zslba,
     923                 :            :                                 uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
     924                 :            :                                 uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
     925                 :            : {
     926                 :            :         struct nvme_request *req;
     927                 :         12 :         struct nvme_payload payload;
     928                 :     256891 :         int rc = 0;
     929                 :            : 
     930         [ -  + ]:     256891 :         if (!_is_io_flags_valid(io_flags)) {
     931                 :          0 :                 return -EINVAL;
     932                 :            :         }
     933                 :            : 
     934                 :     256891 :         rc = nvme_ns_cmd_check_zone_append(ns, lba_count, io_flags);
     935         [ +  + ]:     256891 :         if (rc) {
     936                 :          6 :                 return rc;
     937                 :            :         }
     938                 :            : 
     939                 :     256885 :         payload = NVME_PAYLOAD_CONTIG(buffer, metadata);
     940                 :            : 
     941                 :     256885 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, zslba, lba_count, cb_fn, cb_arg,
     942                 :            :                               SPDK_NVME_OPC_ZONE_APPEND,
     943                 :            :                               io_flags, apptag_mask, apptag, 0, false, NULL, &rc);
     944         [ +  - ]:     256885 :         if (req != NULL) {
     945                 :            :                 /*
     946                 :            :                  * Zone append commands cannot be split (num_children has to be 0).
     947                 :            :                  * For NVME_PAYLOAD_TYPE_CONTIG, _nvme_ns_cmd_rw() should never cause a split
     948                 :            :                  * to happen, since a too large request would have already been failed by
     949                 :            :                  * nvme_ns_cmd_check_zone_append(), since zasl <= mdts.
     950                 :            :                  */
     951         [ -  + ]:     256885 :                 assert(req->num_children == 0);
     952         [ -  + ]:     256885 :                 if (req->num_children) {
     953                 :          0 :                         nvme_request_free_children(req);
     954                 :          0 :                         nvme_free_request(req);
     955                 :          0 :                         return -EINVAL;
     956                 :            :                 }
     957                 :     256885 :                 return nvme_qpair_submit_request(qpair, req);
     958                 :            :         } else {
     959                 :          0 :                 return nvme_ns_map_failure_rc(lba_count,
     960                 :            :                                               ns->sectors_per_max_io,
     961                 :            :                                               ns->sectors_per_stripe,
     962                 :          0 :                                               qpair->ctrlr->opts.io_queue_requests,
     963                 :            :                                               rc);
     964                 :            :         }
     965                 :            : }
     966                 :            : 
     967                 :            : int
     968                 :          6 : nvme_ns_cmd_zone_appendv_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
     969                 :            :                                  uint64_t zslba, uint32_t lba_count,
     970                 :            :                                  spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
     971                 :            :                                  spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
     972                 :            :                                  spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
     973                 :            :                                  uint16_t apptag_mask, uint16_t apptag)
     974                 :            : {
     975                 :            :         struct nvme_request *req;
     976                 :          6 :         struct nvme_payload payload;
     977                 :          6 :         int rc = 0;
     978                 :            : 
     979         [ -  + ]:          6 :         if (!_is_io_flags_valid(io_flags)) {
     980                 :          0 :                 return -EINVAL;
     981                 :            :         }
     982                 :            : 
     983   [ +  -  -  + ]:          6 :         if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
     984                 :          0 :                 return -EINVAL;
     985                 :            :         }
     986                 :            : 
     987                 :          6 :         rc = nvme_ns_cmd_check_zone_append(ns, lba_count, io_flags);
     988         [ +  + ]:          6 :         if (rc) {
     989                 :          3 :                 return rc;
     990                 :            :         }
     991                 :            : 
     992                 :          3 :         payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, metadata);
     993                 :            : 
     994                 :          3 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, zslba, lba_count, cb_fn, cb_arg,
     995                 :            :                               SPDK_NVME_OPC_ZONE_APPEND,
     996                 :            :                               io_flags, apptag_mask, apptag, 0, true, NULL, &rc);
     997         [ +  - ]:          3 :         if (req != NULL) {
     998                 :            :                 /*
     999                 :            :                  * Zone append commands cannot be split (num_children has to be 0).
    1000                 :            :                  * For NVME_PAYLOAD_TYPE_SGL, _nvme_ns_cmd_rw() can cause a split.
    1001                 :            :                  * However, _nvme_ns_cmd_split_request_sgl() and _nvme_ns_cmd_split_request_prp()
    1002                 :            :                  * do not always cause a request to be split. These functions verify payload size,
    1003                 :            :                  * verify num sge < max_sge, and verify SGE alignment rules (in case of PRPs).
    1004                 :            :                  * If any of the verifications fail, they will split the request.
    1005                 :            :                  * In our case, a split is very unlikely, since we already verified the size using
    1006                 :            :                  * nvme_ns_cmd_check_zone_append(), however, we still need to call these functions
    1007                 :            :                  * in order to perform the verification part. If they do cause a split, we return
    1008                 :            :                  * an error here. For proper requests, these functions will never cause a split.
    1009                 :            :                  */
    1010         [ -  + ]:          3 :                 if (req->num_children) {
    1011                 :          0 :                         nvme_request_free_children(req);
    1012                 :          0 :                         nvme_free_request(req);
    1013                 :          0 :                         return -EINVAL;
    1014                 :            :                 }
    1015                 :          3 :                 return nvme_qpair_submit_request(qpair, req);
    1016                 :            :         } else {
    1017                 :          0 :                 return nvme_ns_map_failure_rc(lba_count,
    1018                 :            :                                               ns->sectors_per_max_io,
    1019                 :            :                                               ns->sectors_per_stripe,
    1020                 :          0 :                                               qpair->ctrlr->opts.io_queue_requests,
    1021                 :            :                                               rc);
    1022                 :            :         }
    1023                 :            : }
    1024                 :            : 
    1025                 :            : int
    1026                 :   14463279 : spdk_nvme_ns_cmd_write_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1027                 :            :                                void *buffer, void *metadata, uint64_t lba,
    1028                 :            :                                uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
    1029                 :            :                                uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
    1030                 :            : {
    1031                 :            :         struct nvme_request *req;
    1032                 :    3154064 :         struct nvme_payload payload;
    1033                 :   14463279 :         int rc = 0;
    1034                 :            : 
    1035         [ -  + ]:   14463279 :         if (!_is_io_flags_valid(io_flags)) {
    1036                 :          0 :                 return -EINVAL;
    1037                 :            :         }
    1038                 :            : 
    1039                 :   14463279 :         payload = NVME_PAYLOAD_CONTIG(buffer, metadata);
    1040                 :            : 
    1041                 :   14463279 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE,
    1042                 :            :                               io_flags, apptag_mask, apptag, 0, false, NULL, &rc);
    1043         [ +  + ]:   14463279 :         if (req != NULL) {
    1044                 :   14403801 :                 return nvme_qpair_submit_request(qpair, req);
    1045                 :            :         } else {
    1046                 :      59478 :                 return nvme_ns_map_failure_rc(lba_count,
    1047                 :            :                                               ns->sectors_per_max_io,
    1048                 :            :                                               ns->sectors_per_stripe,
    1049                 :      59478 :                                               qpair->ctrlr->opts.io_queue_requests,
    1050                 :            :                                               rc);
    1051                 :            :         }
    1052                 :            : }
    1053                 :            : 
    1054                 :            : int
    1055                 :     194266 : spdk_nvme_ns_cmd_write_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1056                 :            :                            void *buffer, uint64_t lba,
    1057                 :            :                            uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
    1058                 :            :                            struct spdk_nvme_ns_cmd_ext_io_opts *opts)
    1059                 :            : {
    1060                 :     194266 :         return nvme_ns_cmd_rw_ext(ns, qpair, buffer, lba, lba_count, cb_fn, cb_arg, opts,
    1061                 :            :                                   SPDK_NVME_OPC_WRITE);
    1062                 :            : }
    1063                 :            : 
    1064                 :            : int
    1065                 :         66 : spdk_nvme_ns_cmd_writev(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1066                 :            :                         uint64_t lba, uint32_t lba_count,
    1067                 :            :                         spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
    1068                 :            :                         spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
    1069                 :            :                         spdk_nvme_req_next_sge_cb next_sge_fn)
    1070                 :            : {
    1071                 :            :         struct nvme_request *req;
    1072                 :         36 :         struct nvme_payload payload;
    1073                 :         66 :         int rc = 0;
    1074                 :            : 
    1075         [ -  + ]:         66 :         if (!_is_io_flags_valid(io_flags)) {
    1076                 :          0 :                 return -EINVAL;
    1077                 :            :         }
    1078                 :            : 
    1079   [ +  +  -  + ]:         66 :         if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
    1080                 :          3 :                 return -EINVAL;
    1081                 :            :         }
    1082                 :            : 
    1083                 :         63 :         payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL);
    1084                 :            : 
    1085                 :         63 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE,
    1086                 :            :                               io_flags, 0, 0, 0, true, NULL, &rc);
    1087         [ +  + ]:         63 :         if (req != NULL) {
    1088                 :         60 :                 return nvme_qpair_submit_request(qpair, req);
    1089                 :            :         } else {
    1090                 :          3 :                 return nvme_ns_map_failure_rc(lba_count,
    1091                 :            :                                               ns->sectors_per_max_io,
    1092                 :            :                                               ns->sectors_per_stripe,
    1093                 :          3 :                                               qpair->ctrlr->opts.io_queue_requests,
    1094                 :            :                                               rc);
    1095                 :            :         }
    1096                 :            : }
    1097                 :            : 
    1098                 :            : int
    1099                 :     135664 : spdk_nvme_ns_cmd_writev_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1100                 :            :                                 uint64_t lba, uint32_t lba_count,
    1101                 :            :                                 spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
    1102                 :            :                                 spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
    1103                 :            :                                 spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
    1104                 :            :                                 uint16_t apptag_mask, uint16_t apptag)
    1105                 :            : {
    1106                 :            :         struct nvme_request *req;
    1107                 :      65445 :         struct nvme_payload payload;
    1108                 :     135664 :         int rc = 0;
    1109                 :            : 
    1110         [ -  + ]:     135664 :         if (!_is_io_flags_valid(io_flags)) {
    1111                 :          0 :                 return -EINVAL;
    1112                 :            :         }
    1113                 :            : 
    1114   [ +  -  -  + ]:     135664 :         if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
    1115                 :          0 :                 return -EINVAL;
    1116                 :            :         }
    1117                 :            : 
    1118                 :     135664 :         payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, metadata);
    1119                 :            : 
    1120                 :     135664 :         req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE,
    1121                 :            :                               io_flags, apptag_mask, apptag, 0, true, NULL, &rc);
    1122         [ +  + ]:     135664 :         if (req != NULL) {
    1123                 :     135630 :                 return nvme_qpair_submit_request(qpair, req);
    1124                 :            :         } else {
    1125                 :         34 :                 return nvme_ns_map_failure_rc(lba_count,
    1126                 :            :                                               ns->sectors_per_max_io,
    1127                 :            :                                               ns->sectors_per_stripe,
    1128                 :         34 :                                               qpair->ctrlr->opts.io_queue_requests,
    1129                 :            :                                               rc);
    1130                 :            :         }
    1131                 :            : }
    1132                 :            : 
    1133                 :            : int
    1134                 :         13 : spdk_nvme_ns_cmd_writev_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t lba,
    1135                 :            :                             uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
    1136                 :            :                             spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
    1137                 :            :                             spdk_nvme_req_next_sge_cb next_sge_fn,
    1138                 :            :                             struct spdk_nvme_ns_cmd_ext_io_opts *opts)
    1139                 :            : {
    1140                 :         13 :         return nvme_ns_cmd_rwv_ext(ns, qpair, lba, lba_count, cb_fn, cb_arg, reset_sgl_fn, next_sge_fn,
    1141                 :            :                                    opts, SPDK_NVME_OPC_WRITE);
    1142                 :            : }
    1143                 :            : 
    1144                 :            : int
    1145                 :     648569 : spdk_nvme_ns_cmd_write_zeroes(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1146                 :            :                               uint64_t lba, uint32_t lba_count,
    1147                 :            :                               spdk_nvme_cmd_cb cb_fn, void *cb_arg,
    1148                 :            :                               uint32_t io_flags)
    1149                 :            : {
    1150                 :            :         struct nvme_request     *req;
    1151                 :            :         struct spdk_nvme_cmd    *cmd;
    1152                 :            :         uint64_t                *tmp_lba;
    1153                 :            : 
    1154         [ -  + ]:     648569 :         if (!_is_io_flags_valid(io_flags)) {
    1155                 :          0 :                 return -EINVAL;
    1156                 :            :         }
    1157                 :            : 
    1158   [ +  -  -  + ]:     648569 :         if (lba_count == 0 || lba_count > UINT16_MAX + 1) {
    1159                 :          0 :                 return -EINVAL;
    1160                 :            :         }
    1161                 :            : 
    1162                 :     648569 :         req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
    1163         [ +  + ]:     648569 :         if (req == NULL) {
    1164                 :         48 :                 return -ENOMEM;
    1165                 :            :         }
    1166                 :            : 
    1167                 :     648521 :         cmd = &req->cmd;
    1168                 :     648521 :         cmd->opc = SPDK_NVME_OPC_WRITE_ZEROES;
    1169                 :     648521 :         cmd->nsid = ns->id;
    1170                 :            : 
    1171                 :     648521 :         tmp_lba = (uint64_t *)&cmd->cdw10;
    1172                 :     648521 :         *tmp_lba = lba;
    1173                 :     648521 :         cmd->cdw12 = lba_count - 1;
    1174                 :     648521 :         cmd->fuse = (io_flags & SPDK_NVME_IO_FLAGS_FUSE_MASK);
    1175                 :     648521 :         cmd->cdw12 |= (io_flags & SPDK_NVME_IO_FLAGS_CDW12_MASK);
    1176                 :            : 
    1177                 :     648521 :         return nvme_qpair_submit_request(qpair, req);
    1178                 :            : }
    1179                 :            : 
    1180                 :            : int
    1181                 :          3 : spdk_nvme_ns_cmd_verify(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1182                 :            :                         uint64_t lba, uint32_t lba_count,
    1183                 :            :                         spdk_nvme_cmd_cb cb_fn, void *cb_arg,
    1184                 :            :                         uint32_t io_flags)
    1185                 :            : {
    1186                 :            :         struct nvme_request     *req;
    1187                 :            :         struct spdk_nvme_cmd    *cmd;
    1188                 :            : 
    1189         [ -  + ]:          3 :         if (!_is_io_flags_valid(io_flags)) {
    1190                 :          0 :                 return -EINVAL;
    1191                 :            :         }
    1192                 :            : 
    1193   [ +  -  -  + ]:          3 :         if (lba_count == 0 || lba_count > UINT16_MAX + 1) {
    1194                 :          0 :                 return -EINVAL;
    1195                 :            :         }
    1196                 :            : 
    1197                 :          3 :         req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
    1198         [ -  + ]:          3 :         if (req == NULL) {
    1199                 :          0 :                 return -ENOMEM;
    1200                 :            :         }
    1201                 :            : 
    1202                 :          3 :         cmd = &req->cmd;
    1203                 :          3 :         cmd->opc = SPDK_NVME_OPC_VERIFY;
    1204                 :          3 :         cmd->nsid = ns->id;
    1205                 :            : 
    1206                 :          3 :         *(uint64_t *)&cmd->cdw10 = lba;
    1207                 :          3 :         cmd->cdw12 = lba_count - 1;
    1208                 :          3 :         cmd->fuse = (io_flags & SPDK_NVME_IO_FLAGS_FUSE_MASK);
    1209                 :          3 :         cmd->cdw12 |= (io_flags & SPDK_NVME_IO_FLAGS_CDW12_MASK);
    1210                 :            : 
    1211                 :          3 :         return nvme_qpair_submit_request(qpair, req);
    1212                 :            : }
    1213                 :            : 
    1214                 :            : int
    1215                 :          3 : spdk_nvme_ns_cmd_write_uncorrectable(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1216                 :            :                                      uint64_t lba, uint32_t lba_count,
    1217                 :            :                                      spdk_nvme_cmd_cb cb_fn, void *cb_arg)
    1218                 :            : {
    1219                 :            :         struct nvme_request     *req;
    1220                 :            :         struct spdk_nvme_cmd    *cmd;
    1221                 :            :         uint64_t                *tmp_lba;
    1222                 :            : 
    1223   [ +  -  -  + ]:          3 :         if (lba_count == 0 || lba_count > UINT16_MAX + 1) {
    1224                 :          0 :                 return -EINVAL;
    1225                 :            :         }
    1226                 :            : 
    1227                 :          3 :         req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
    1228         [ -  + ]:          3 :         if (req == NULL) {
    1229                 :          0 :                 return -ENOMEM;
    1230                 :            :         }
    1231                 :            : 
    1232                 :          3 :         cmd = &req->cmd;
    1233                 :          3 :         cmd->opc = SPDK_NVME_OPC_WRITE_UNCORRECTABLE;
    1234                 :          3 :         cmd->nsid = ns->id;
    1235                 :            : 
    1236                 :          3 :         tmp_lba = (uint64_t *)&cmd->cdw10;
    1237                 :          3 :         *tmp_lba = lba;
    1238                 :          3 :         cmd->cdw12 = lba_count - 1;
    1239                 :            : 
    1240                 :          3 :         return nvme_qpair_submit_request(qpair, req);
    1241                 :            : }
    1242                 :            : 
    1243                 :            : int
    1244                 :      58369 : spdk_nvme_ns_cmd_dataset_management(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1245                 :            :                                     uint32_t type,
    1246                 :            :                                     const struct spdk_nvme_dsm_range *ranges, uint16_t num_ranges,
    1247                 :            :                                     spdk_nvme_cmd_cb cb_fn, void *cb_arg)
    1248                 :            : {
    1249                 :            :         struct nvme_request     *req;
    1250                 :            :         struct spdk_nvme_cmd    *cmd;
    1251                 :            : 
    1252   [ +  +  -  + ]:      58369 :         if (num_ranges == 0 || num_ranges > SPDK_NVME_DATASET_MANAGEMENT_MAX_RANGES) {
    1253                 :          3 :                 return -EINVAL;
    1254                 :            :         }
    1255                 :            : 
    1256         [ -  + ]:      58366 :         if (ranges == NULL) {
    1257                 :          0 :                 return -EINVAL;
    1258                 :            :         }
    1259                 :            : 
    1260                 :      58366 :         req = nvme_allocate_request_user_copy(qpair, (void *)ranges,
    1261                 :            :                                               num_ranges * sizeof(struct spdk_nvme_dsm_range),
    1262                 :            :                                               cb_fn, cb_arg, true);
    1263         [ -  + ]:      58366 :         if (req == NULL) {
    1264                 :          0 :                 return -ENOMEM;
    1265                 :            :         }
    1266                 :            : 
    1267                 :      58366 :         cmd = &req->cmd;
    1268                 :      58366 :         cmd->opc = SPDK_NVME_OPC_DATASET_MANAGEMENT;
    1269                 :      58366 :         cmd->nsid = ns->id;
    1270                 :            : 
    1271                 :      58366 :         cmd->cdw10_bits.dsm.nr = num_ranges - 1;
    1272                 :      58366 :         cmd->cdw11 = type;
    1273                 :            : 
    1274                 :      58366 :         return nvme_qpair_submit_request(qpair, req);
    1275                 :            : }
    1276                 :            : 
    1277                 :            : int
    1278                 :         48 : spdk_nvme_ns_cmd_copy(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1279                 :            :                       const struct spdk_nvme_scc_source_range *ranges,
    1280                 :            :                       uint16_t num_ranges, uint64_t dest_lba,
    1281                 :            :                       spdk_nvme_cmd_cb cb_fn, void *cb_arg)
    1282                 :            : {
    1283                 :            :         struct nvme_request     *req;
    1284                 :            :         struct spdk_nvme_cmd    *cmd;
    1285                 :            : 
    1286         [ +  + ]:         48 :         if (num_ranges == 0) {
    1287                 :          3 :                 return -EINVAL;
    1288                 :            :         }
    1289                 :            : 
    1290         [ -  + ]:         45 :         if (ranges == NULL) {
    1291                 :          0 :                 return -EINVAL;
    1292                 :            :         }
    1293                 :            : 
    1294                 :         45 :         req = nvme_allocate_request_user_copy(qpair, (void *)ranges,
    1295                 :            :                                               num_ranges * sizeof(struct spdk_nvme_scc_source_range),
    1296                 :            :                                               cb_fn, cb_arg, true);
    1297         [ -  + ]:         45 :         if (req == NULL) {
    1298                 :          0 :                 return -ENOMEM;
    1299                 :            :         }
    1300                 :            : 
    1301                 :         45 :         cmd = &req->cmd;
    1302                 :         45 :         cmd->opc = SPDK_NVME_OPC_COPY;
    1303                 :         45 :         cmd->nsid = ns->id;
    1304                 :            : 
    1305                 :         45 :         *(uint64_t *)&cmd->cdw10 = dest_lba;
    1306                 :         45 :         cmd->cdw12 = num_ranges - 1;
    1307                 :            : 
    1308                 :         45 :         return nvme_qpair_submit_request(qpair, req);
    1309                 :            : }
    1310                 :            : 
    1311                 :            : int
    1312                 :          3 : spdk_nvme_ns_cmd_flush(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1313                 :            :                        spdk_nvme_cmd_cb cb_fn, void *cb_arg)
    1314                 :            : {
    1315                 :            :         struct nvme_request     *req;
    1316                 :            :         struct spdk_nvme_cmd    *cmd;
    1317                 :            : 
    1318                 :          3 :         req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
    1319         [ -  + ]:          3 :         if (req == NULL) {
    1320                 :          0 :                 return -ENOMEM;
    1321                 :            :         }
    1322                 :            : 
    1323                 :          3 :         cmd = &req->cmd;
    1324                 :          3 :         cmd->opc = SPDK_NVME_OPC_FLUSH;
    1325                 :          3 :         cmd->nsid = ns->id;
    1326                 :            : 
    1327                 :          3 :         return nvme_qpair_submit_request(qpair, req);
    1328                 :            : }
    1329                 :            : 
    1330                 :            : int
    1331                 :          3 : spdk_nvme_ns_cmd_reservation_register(struct spdk_nvme_ns *ns,
    1332                 :            :                                       struct spdk_nvme_qpair *qpair,
    1333                 :            :                                       struct spdk_nvme_reservation_register_data *payload,
    1334                 :            :                                       bool ignore_key,
    1335                 :            :                                       enum spdk_nvme_reservation_register_action action,
    1336                 :            :                                       enum spdk_nvme_reservation_register_cptpl cptpl,
    1337                 :            :                                       spdk_nvme_cmd_cb cb_fn, void *cb_arg)
    1338                 :            : {
    1339                 :            :         struct nvme_request     *req;
    1340                 :            :         struct spdk_nvme_cmd    *cmd;
    1341                 :            : 
    1342                 :          3 :         req = nvme_allocate_request_user_copy(qpair,
    1343                 :            :                                               payload, sizeof(struct spdk_nvme_reservation_register_data),
    1344                 :            :                                               cb_fn, cb_arg, true);
    1345         [ -  + ]:          3 :         if (req == NULL) {
    1346                 :          0 :                 return -ENOMEM;
    1347                 :            :         }
    1348                 :            : 
    1349                 :          3 :         cmd = &req->cmd;
    1350                 :          3 :         cmd->opc = SPDK_NVME_OPC_RESERVATION_REGISTER;
    1351                 :          3 :         cmd->nsid = ns->id;
    1352                 :            : 
    1353                 :          3 :         cmd->cdw10_bits.resv_register.rrega = action;
    1354                 :          3 :         cmd->cdw10_bits.resv_register.iekey = ignore_key;
    1355                 :          3 :         cmd->cdw10_bits.resv_register.cptpl = cptpl;
    1356                 :            : 
    1357                 :          3 :         return nvme_qpair_submit_request(qpair, req);
    1358                 :            : }
    1359                 :            : 
    1360                 :            : int
    1361                 :          3 : spdk_nvme_ns_cmd_reservation_release(struct spdk_nvme_ns *ns,
    1362                 :            :                                      struct spdk_nvme_qpair *qpair,
    1363                 :            :                                      struct spdk_nvme_reservation_key_data *payload,
    1364                 :            :                                      bool ignore_key,
    1365                 :            :                                      enum spdk_nvme_reservation_release_action action,
    1366                 :            :                                      enum spdk_nvme_reservation_type type,
    1367                 :            :                                      spdk_nvme_cmd_cb cb_fn, void *cb_arg)
    1368                 :            : {
    1369                 :            :         struct nvme_request     *req;
    1370                 :            :         struct spdk_nvme_cmd    *cmd;
    1371                 :            : 
    1372                 :          3 :         req = nvme_allocate_request_user_copy(qpair,
    1373                 :            :                                               payload, sizeof(struct spdk_nvme_reservation_key_data), cb_fn,
    1374                 :            :                                               cb_arg, true);
    1375         [ -  + ]:          3 :         if (req == NULL) {
    1376                 :          0 :                 return -ENOMEM;
    1377                 :            :         }
    1378                 :            : 
    1379                 :          3 :         cmd = &req->cmd;
    1380                 :          3 :         cmd->opc = SPDK_NVME_OPC_RESERVATION_RELEASE;
    1381                 :          3 :         cmd->nsid = ns->id;
    1382                 :            : 
    1383                 :          3 :         cmd->cdw10_bits.resv_release.rrela = action;
    1384                 :          3 :         cmd->cdw10_bits.resv_release.iekey = ignore_key;
    1385                 :          3 :         cmd->cdw10_bits.resv_release.rtype = type;
    1386                 :            : 
    1387                 :          3 :         return nvme_qpair_submit_request(qpair, req);
    1388                 :            : }
    1389                 :            : 
    1390                 :            : int
    1391                 :          3 : spdk_nvme_ns_cmd_reservation_acquire(struct spdk_nvme_ns *ns,
    1392                 :            :                                      struct spdk_nvme_qpair *qpair,
    1393                 :            :                                      struct spdk_nvme_reservation_acquire_data *payload,
    1394                 :            :                                      bool ignore_key,
    1395                 :            :                                      enum spdk_nvme_reservation_acquire_action action,
    1396                 :            :                                      enum spdk_nvme_reservation_type type,
    1397                 :            :                                      spdk_nvme_cmd_cb cb_fn, void *cb_arg)
    1398                 :            : {
    1399                 :            :         struct nvme_request     *req;
    1400                 :            :         struct spdk_nvme_cmd    *cmd;
    1401                 :            : 
    1402                 :          3 :         req = nvme_allocate_request_user_copy(qpair,
    1403                 :            :                                               payload, sizeof(struct spdk_nvme_reservation_acquire_data),
    1404                 :            :                                               cb_fn, cb_arg, true);
    1405         [ -  + ]:          3 :         if (req == NULL) {
    1406                 :          0 :                 return -ENOMEM;
    1407                 :            :         }
    1408                 :            : 
    1409                 :          3 :         cmd = &req->cmd;
    1410                 :          3 :         cmd->opc = SPDK_NVME_OPC_RESERVATION_ACQUIRE;
    1411                 :          3 :         cmd->nsid = ns->id;
    1412                 :            : 
    1413                 :          3 :         cmd->cdw10_bits.resv_acquire.racqa = action;
    1414                 :          3 :         cmd->cdw10_bits.resv_acquire.iekey = ignore_key;
    1415                 :          3 :         cmd->cdw10_bits.resv_acquire.rtype = type;
    1416                 :            : 
    1417                 :          3 :         return nvme_qpair_submit_request(qpair, req);
    1418                 :            : }
    1419                 :            : 
    1420                 :            : int
    1421                 :          3 : spdk_nvme_ns_cmd_reservation_report(struct spdk_nvme_ns *ns,
    1422                 :            :                                     struct spdk_nvme_qpair *qpair,
    1423                 :            :                                     void *payload, uint32_t len,
    1424                 :            :                                     spdk_nvme_cmd_cb cb_fn, void *cb_arg)
    1425                 :            : {
    1426                 :            :         uint32_t                num_dwords;
    1427                 :            :         struct nvme_request     *req;
    1428                 :            :         struct spdk_nvme_cmd    *cmd;
    1429                 :            : 
    1430         [ -  + ]:          3 :         if (len & 0x3) {
    1431                 :          0 :                 return -EINVAL;
    1432                 :            :         }
    1433                 :            : 
    1434                 :          3 :         req = nvme_allocate_request_user_copy(qpair, payload, len, cb_fn, cb_arg, false);
    1435         [ -  + ]:          3 :         if (req == NULL) {
    1436                 :          0 :                 return -ENOMEM;
    1437                 :            :         }
    1438                 :            : 
    1439                 :          3 :         cmd = &req->cmd;
    1440                 :          3 :         cmd->opc = SPDK_NVME_OPC_RESERVATION_REPORT;
    1441                 :          3 :         cmd->nsid = ns->id;
    1442                 :            : 
    1443                 :          3 :         num_dwords = (len >> 2);
    1444                 :          3 :         cmd->cdw10 = num_dwords - 1; /* 0-based */
    1445                 :            : 
    1446                 :          3 :         return nvme_qpair_submit_request(qpair, req);
    1447                 :            : }
    1448                 :            : 
    1449                 :            : int
    1450                 :          8 : spdk_nvme_ns_cmd_io_mgmt_recv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1451                 :            :                               void *payload, uint32_t len, uint8_t mo, uint16_t mos,
    1452                 :            :                               spdk_nvme_cmd_cb cb_fn, void *cb_arg)
    1453                 :            : {
    1454                 :            :         uint32_t                num_dwords;
    1455                 :            :         struct nvme_request     *req;
    1456                 :            :         struct spdk_nvme_cmd    *cmd;
    1457                 :            : 
    1458         [ +  + ]:          8 :         if (len & 0x3) {
    1459                 :          3 :                 return -EINVAL;
    1460                 :            :         }
    1461                 :            : 
    1462                 :          5 :         req = nvme_allocate_request_user_copy(qpair, payload, len, cb_fn, cb_arg, false);
    1463         [ -  + ]:          5 :         if (req == NULL) {
    1464                 :          0 :                 return -ENOMEM;
    1465                 :            :         }
    1466                 :            : 
    1467                 :          5 :         cmd = &req->cmd;
    1468                 :          5 :         cmd->opc = SPDK_NVME_OPC_IO_MANAGEMENT_RECEIVE;
    1469                 :          5 :         cmd->nsid = ns->id;
    1470                 :            : 
    1471                 :          5 :         cmd->cdw10_bits.mgmt_send_recv.mo = mo;
    1472                 :          5 :         cmd->cdw10_bits.mgmt_send_recv.mos = mos;
    1473                 :            : 
    1474                 :          5 :         num_dwords = (len >> 2);
    1475                 :          5 :         cmd->cdw11 = num_dwords - 1; /* 0-based */
    1476                 :            : 
    1477                 :          5 :         return nvme_qpair_submit_request(qpair, req);
    1478                 :            : }
    1479                 :            : 
    1480                 :            : int
    1481                 :          4 : spdk_nvme_ns_cmd_io_mgmt_send(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
    1482                 :            :                               void *payload, uint32_t len, uint8_t mo, uint16_t mos,
    1483                 :            :                               spdk_nvme_cmd_cb cb_fn, void *cb_arg)
    1484                 :            : {
    1485                 :            :         struct nvme_request     *req;
    1486                 :            :         struct spdk_nvme_cmd    *cmd;
    1487                 :            : 
    1488                 :          4 :         req = nvme_allocate_request_user_copy(qpair, payload, len, cb_fn, cb_arg, false);
    1489         [ -  + ]:          4 :         if (req == NULL) {
    1490                 :          0 :                 return -ENOMEM;
    1491                 :            :         }
    1492                 :            : 
    1493                 :          4 :         cmd = &req->cmd;
    1494                 :          4 :         cmd->opc = SPDK_NVME_OPC_IO_MANAGEMENT_SEND;
    1495                 :          4 :         cmd->nsid = ns->id;
    1496                 :            : 
    1497                 :          4 :         cmd->cdw10_bits.mgmt_send_recv.mo = mo;
    1498                 :          4 :         cmd->cdw10_bits.mgmt_send_recv.mos = mos;
    1499                 :            : 
    1500                 :          4 :         return nvme_qpair_submit_request(qpair, req);
    1501                 :            : }

Generated by: LCOV version 1.14