LCOV - code coverage report
Current view: top level - spdk/lib/nvme - nvme_ns_cmd.c (source / functions) Hit Total Coverage
Test: Combined Lines: 499 579 86.2 %
Date: 2024-07-13 11:15:58 Functions: 42 42 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 227 318 71.4 %

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

Generated by: LCOV version 1.14