LCOV - code coverage report
Current view: top level - lib/nvme - nvme_ns.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 237 305 77.7 %
Date: 2024-12-14 14:12:17 Functions: 38 40 95.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2015 Intel Corporation. All rights reserved.
       3             :  *   Copyright (c) 2020, 2021 Mellanox Technologies LTD. All rights reserved.
       4             :  */
       5             : 
       6             : #include "nvme_internal.h"
       7             : 
       8             : static inline struct spdk_nvme_ns_data *
       9          58 : _nvme_ns_get_data(struct spdk_nvme_ns *ns)
      10             : {
      11          58 :         return &ns->nsdata;
      12             : }
      13             : 
      14             : /**
      15             :  * Update Namespace flags based on Identify Controller
      16             :  * and Identify Namespace.  This can be also used for
      17             :  * Namespace Attribute Notice events and Namespace
      18             :  * operations such as Attach/Detach.
      19             :  */
      20             : void
      21          13 : nvme_ns_set_identify_data(struct spdk_nvme_ns *ns)
      22             : {
      23             :         struct spdk_nvme_ns_data        *nsdata;
      24             :         struct spdk_nvme_nvm_ns_data    *nsdata_nvm;
      25             :         uint32_t                        format_index;
      26             : 
      27          13 :         nsdata = _nvme_ns_get_data(ns);
      28          13 :         nsdata_nvm = ns->nsdata_nvm;
      29             : 
      30          13 :         ns->flags = 0x0000;
      31          13 :         format_index = spdk_nvme_ns_get_format_index(nsdata);
      32             : 
      33          13 :         ns->sector_size = 1 << nsdata->lbaf[format_index].lbads;
      34          13 :         ns->extended_lba_size = ns->sector_size;
      35             : 
      36          13 :         ns->md_size = nsdata->lbaf[format_index].ms;
      37          13 :         if (nsdata->flbas.extended) {
      38           2 :                 ns->flags |= SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED;
      39           2 :                 ns->extended_lba_size += ns->md_size;
      40             :         }
      41             : 
      42          13 :         ns->sectors_per_max_io = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->extended_lba_size;
      43          13 :         ns->sectors_per_max_io_no_md = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->sector_size;
      44          13 :         if (ns->ctrlr->quirks & NVME_QUIRK_MDTS_EXCLUDE_MD) {
      45           1 :                 ns->sectors_per_max_io = ns->sectors_per_max_io_no_md;
      46             :         }
      47             : 
      48          13 :         if (nsdata->noiob) {
      49           2 :                 ns->sectors_per_stripe = nsdata->noiob;
      50           2 :                 SPDK_DEBUGLOG(nvme, "ns %u optimal IO boundary %" PRIu32 " blocks\n",
      51             :                               ns->id, ns->sectors_per_stripe);
      52          11 :         } else if (ns->ctrlr->quirks & NVME_INTEL_QUIRK_STRIPING &&
      53           0 :                    ns->ctrlr->cdata.vs[3] != 0) {
      54           0 :                 ns->sectors_per_stripe = (1ULL << ns->ctrlr->cdata.vs[3]) * ns->ctrlr->min_page_size /
      55           0 :                                          ns->sector_size;
      56           0 :                 SPDK_DEBUGLOG(nvme, "ns %u stripe size quirk %" PRIu32 " blocks\n",
      57             :                               ns->id, ns->sectors_per_stripe);
      58             :         } else {
      59          11 :                 ns->sectors_per_stripe = 0;
      60             :         }
      61             : 
      62          13 :         if (ns->ctrlr->cdata.oncs.dsm) {
      63           2 :                 ns->flags |= SPDK_NVME_NS_DEALLOCATE_SUPPORTED;
      64             :         }
      65             : 
      66          13 :         if (ns->ctrlr->cdata.oncs.compare) {
      67           2 :                 ns->flags |= SPDK_NVME_NS_COMPARE_SUPPORTED;
      68             :         }
      69             : 
      70          13 :         if (ns->ctrlr->cdata.vwc.present) {
      71           2 :                 ns->flags |= SPDK_NVME_NS_FLUSH_SUPPORTED;
      72             :         }
      73             : 
      74          13 :         if (ns->ctrlr->cdata.oncs.write_zeroes) {
      75           2 :                 ns->flags |= SPDK_NVME_NS_WRITE_ZEROES_SUPPORTED;
      76             :         }
      77             : 
      78          13 :         if (ns->ctrlr->cdata.oncs.write_unc) {
      79           2 :                 ns->flags |= SPDK_NVME_NS_WRITE_UNCORRECTABLE_SUPPORTED;
      80             :         }
      81             : 
      82          13 :         if (nsdata->nsrescap.raw) {
      83           2 :                 ns->flags |= SPDK_NVME_NS_RESERVATION_SUPPORTED;
      84             :         }
      85             : 
      86          13 :         ns->pi_type = SPDK_NVME_FMT_NVM_PROTECTION_DISABLE;
      87          13 :         if (nsdata->lbaf[format_index].ms && nsdata->dps.pit) {
      88           2 :                 ns->flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
      89           2 :                 ns->pi_type = nsdata->dps.pit;
      90           2 :                 if (nsdata_nvm != NULL && ns->ctrlr->cdata.ctratt.bits.elbas) {
      91             :                         /* We may have nsdata_nvm for other purposes but
      92             :                          * the elbaf array is only valid when elbas is 1.
      93             :                          */
      94           0 :                         ns->pi_format = nsdata_nvm->elbaf[format_index].pif;
      95             :                 } else {
      96           2 :                         ns->pi_format = SPDK_NVME_16B_GUARD_PI;
      97             :                 }
      98             :         }
      99          13 : }
     100             : 
     101             : static int
     102          11 : nvme_ctrlr_identify_ns(struct spdk_nvme_ns *ns)
     103             : {
     104             :         struct nvme_completion_poll_status      *status;
     105             :         struct spdk_nvme_ns_data                *nsdata;
     106             :         int                                     rc;
     107             : 
     108          11 :         status = calloc(1, sizeof(*status));
     109          11 :         if (!status) {
     110           0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
     111           0 :                 return -ENOMEM;
     112             :         }
     113             : 
     114          11 :         nsdata = _nvme_ns_get_data(ns);
     115          11 :         rc = nvme_ctrlr_cmd_identify(ns->ctrlr, SPDK_NVME_IDENTIFY_NS, 0, ns->id, 0,
     116             :                                      nsdata, sizeof(*nsdata),
     117             :                                      nvme_completion_poll_cb, status);
     118          11 :         if (rc != 0) {
     119           0 :                 free(status);
     120           0 :                 return rc;
     121             :         }
     122             : 
     123          11 :         if (nvme_wait_for_completion_robust_lock(ns->ctrlr->adminq, status,
     124          11 :                         &ns->ctrlr->ctrlr_lock)) {
     125           0 :                 if (!status->timed_out) {
     126           0 :                         free(status);
     127             :                 }
     128             :                 /* This can occur if the namespace is not active. Simply zero the
     129             :                  * namespace data and continue. */
     130           0 :                 nvme_ns_destruct(ns);
     131           0 :                 return 0;
     132             :         }
     133          11 :         free(status);
     134             : 
     135          11 :         nvme_ns_set_identify_data(ns);
     136             : 
     137          11 :         return 0;
     138             : }
     139             : 
     140             : static int
     141           1 : nvme_ctrlr_identify_ns_zns_specific(struct spdk_nvme_ns *ns)
     142             : {
     143             :         struct nvme_completion_poll_status *status;
     144           1 :         struct spdk_nvme_ctrlr *ctrlr = ns->ctrlr;
     145             :         struct spdk_nvme_zns_ns_data *nsdata_zns;
     146             :         int rc;
     147             : 
     148           1 :         nvme_ns_free_zns_specific_data(ns);
     149             : 
     150           1 :         nsdata_zns = spdk_zmalloc(sizeof(*nsdata_zns), 64, NULL, SPDK_ENV_NUMA_ID_ANY,
     151             :                                   SPDK_MALLOC_SHARE);
     152           1 :         if (!nsdata_zns) {
     153           0 :                 return -ENOMEM;
     154             :         }
     155             : 
     156           1 :         status = calloc(1, sizeof(*status));
     157           1 :         if (!status) {
     158           0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
     159           0 :                 spdk_free(nsdata_zns);
     160           0 :                 return -ENOMEM;
     161             :         }
     162             : 
     163           1 :         rc = nvme_ctrlr_cmd_identify(ctrlr, SPDK_NVME_IDENTIFY_NS_IOCS, 0, ns->id, ns->csi,
     164             :                                      nsdata_zns, sizeof(*nsdata_zns),
     165             :                                      nvme_completion_poll_cb, status);
     166           1 :         if (rc != 0) {
     167           0 :                 spdk_free(nsdata_zns);
     168           0 :                 free(status);
     169           0 :                 return rc;
     170             :         }
     171             : 
     172           1 :         if (nvme_wait_for_completion_robust_lock(ctrlr->adminq, status, &ctrlr->ctrlr_lock)) {
     173           0 :                 SPDK_ERRLOG("Failed to retrieve Identify IOCS Specific Namespace Data Structure\n");
     174           0 :                 spdk_free(nsdata_zns);
     175           0 :                 if (!status->timed_out) {
     176           0 :                         free(status);
     177             :                 }
     178           0 :                 return -ENXIO;
     179             :         }
     180           1 :         free(status);
     181           1 :         ns->nsdata_zns = nsdata_zns;
     182             : 
     183           1 :         return 0;
     184             : }
     185             : 
     186             : static int
     187           1 : nvme_ctrlr_identify_ns_nvm_specific(struct spdk_nvme_ns *ns)
     188             : {
     189             :         struct nvme_completion_poll_status *status;
     190           1 :         struct spdk_nvme_ctrlr *ctrlr = ns->ctrlr;
     191             :         struct spdk_nvme_nvm_ns_data *nsdata_nvm;
     192             :         int rc;
     193             : 
     194           1 :         nvme_ns_free_zns_specific_data(ns);
     195             : 
     196           1 :         nsdata_nvm = spdk_zmalloc(sizeof(*nsdata_nvm), 64, NULL, SPDK_ENV_NUMA_ID_ANY,
     197             :                                   SPDK_MALLOC_SHARE);
     198           1 :         if (!nsdata_nvm) {
     199           0 :                 return -ENOMEM;
     200             :         }
     201             : 
     202           1 :         status = calloc(1, sizeof(*status));
     203           1 :         if (!status) {
     204           0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
     205           0 :                 spdk_free(nsdata_nvm);
     206           0 :                 return -ENOMEM;
     207             :         }
     208             : 
     209           1 :         rc = nvme_ctrlr_cmd_identify(ctrlr, SPDK_NVME_IDENTIFY_NS_IOCS, 0, ns->id, ns->csi,
     210             :                                      nsdata_nvm, sizeof(*nsdata_nvm),
     211             :                                      nvme_completion_poll_cb, status);
     212           1 :         if (rc != 0) {
     213           0 :                 spdk_free(nsdata_nvm);
     214           0 :                 free(status);
     215           0 :                 return rc;
     216             :         }
     217             : 
     218           1 :         if (nvme_wait_for_completion_robust_lock(ctrlr->adminq, status, &ctrlr->ctrlr_lock)) {
     219           0 :                 SPDK_ERRLOG("Failed to retrieve Identify IOCS Specific Namespace Data Structure\n");
     220           0 :                 spdk_free(nsdata_nvm);
     221           0 :                 if (!status->timed_out) {
     222           0 :                         free(status);
     223             :                 }
     224           0 :                 return -ENXIO;
     225             :         }
     226           1 :         free(status);
     227           1 :         ns->nsdata_nvm = nsdata_nvm;
     228             : 
     229           1 :         return 0;
     230             : }
     231             : 
     232             : static int
     233           2 : nvme_ctrlr_identify_ns_iocs_specific(struct spdk_nvme_ns *ns)
     234             : {
     235           2 :         switch (ns->csi) {
     236           1 :         case SPDK_NVME_CSI_ZNS:
     237           1 :                 return nvme_ctrlr_identify_ns_zns_specific(ns);
     238           1 :         case SPDK_NVME_CSI_NVM:
     239           1 :                 if (ns->ctrlr->cdata.ctratt.bits.elbas) {
     240           1 :                         return nvme_ctrlr_identify_ns_nvm_specific(ns);
     241             :                 }
     242             :         /* fallthrough */
     243             :         default:
     244             :                 /*
     245             :                  * This switch must handle all cases for which
     246             :                  * nvme_ns_has_supported_iocs_specific_data() returns true,
     247             :                  * other cases should never happen.
     248             :                  */
     249           0 :                 assert(0);
     250             :         }
     251             : 
     252             :         return -EINVAL;
     253             : }
     254             : 
     255             : static int
     256           3 : nvme_ctrlr_identify_id_desc(struct spdk_nvme_ns *ns)
     257             : {
     258             :         struct nvme_completion_poll_status      *status;
     259             :         int                                     rc;
     260             : 
     261           3 :         memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list));
     262             : 
     263           3 :         if ((ns->ctrlr->vs.raw < SPDK_NVME_VERSION(1, 3, 0) &&
     264           2 :              !(ns->ctrlr->cap.bits.css & SPDK_NVME_CAP_CSS_IOCS)) ||
     265           1 :             (ns->ctrlr->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
     266           2 :                 SPDK_DEBUGLOG(nvme, "Version < 1.3; not attempting to retrieve NS ID Descriptor List\n");
     267           2 :                 return 0;
     268             :         }
     269             : 
     270           1 :         status = calloc(1, sizeof(*status));
     271           1 :         if (!status) {
     272           0 :                 SPDK_ERRLOG("Failed to allocate status tracker\n");
     273           0 :                 return -ENOMEM;
     274             :         }
     275             : 
     276           1 :         SPDK_DEBUGLOG(nvme, "Attempting to retrieve NS ID Descriptor List\n");
     277           1 :         rc = nvme_ctrlr_cmd_identify(ns->ctrlr, SPDK_NVME_IDENTIFY_NS_ID_DESCRIPTOR_LIST, 0, ns->id,
     278           1 :                                      0, ns->id_desc_list, sizeof(ns->id_desc_list),
     279             :                                      nvme_completion_poll_cb, status);
     280           1 :         if (rc < 0) {
     281           0 :                 free(status);
     282           0 :                 return rc;
     283             :         }
     284             : 
     285           1 :         rc = nvme_wait_for_completion_robust_lock(ns->ctrlr->adminq, status, &ns->ctrlr->ctrlr_lock);
     286           1 :         if (rc != 0) {
     287           0 :                 SPDK_WARNLOG("Failed to retrieve NS ID Descriptor List\n");
     288           0 :                 memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list));
     289             :         }
     290             : 
     291           1 :         if (!status->timed_out) {
     292           1 :                 free(status);
     293             :         }
     294             : 
     295           1 :         nvme_ns_set_id_desc_list_data(ns);
     296             : 
     297           1 :         return rc;
     298             : }
     299             : 
     300             : uint32_t
     301           3 : spdk_nvme_ns_get_id(struct spdk_nvme_ns *ns)
     302             : {
     303           3 :         return ns->id;
     304             : }
     305             : 
     306             : bool
     307          16 : spdk_nvme_ns_is_active(struct spdk_nvme_ns *ns)
     308             : {
     309          16 :         const struct spdk_nvme_ns_data *nsdata = NULL;
     310             : 
     311             :         /*
     312             :          * According to the spec, valid NS has non-zero id.
     313             :          */
     314          16 :         if (ns->id == 0) {
     315           1 :                 return false;
     316             :         }
     317             : 
     318          15 :         nsdata = _nvme_ns_get_data(ns);
     319             : 
     320             :         /*
     321             :          * According to the spec, Identify Namespace will return a zero-filled structure for
     322             :          *  inactive namespace IDs.
     323             :          * Check NCAP since it must be nonzero for an active namespace.
     324             :          */
     325          15 :         return nsdata->ncap != 0;
     326             : }
     327             : 
     328             : struct spdk_nvme_ctrlr *
     329           1 : spdk_nvme_ns_get_ctrlr(struct spdk_nvme_ns *ns)
     330             : {
     331           1 :         return ns->ctrlr;
     332             : }
     333             : 
     334             : uint32_t
     335          28 : spdk_nvme_ns_get_max_io_xfer_size(struct spdk_nvme_ns *ns)
     336             : {
     337          28 :         return ns->ctrlr->max_xfer_size;
     338             : }
     339             : 
     340             : uint32_t
     341           3 : spdk_nvme_ns_get_sector_size(struct spdk_nvme_ns *ns)
     342             : {
     343           3 :         return ns->sector_size;
     344             : }
     345             : 
     346             : uint32_t
     347           2 : spdk_nvme_ns_get_extended_sector_size(struct spdk_nvme_ns *ns)
     348             : {
     349           2 :         return ns->extended_lba_size;
     350             : }
     351             : 
     352             : uint64_t
     353           4 : spdk_nvme_ns_get_num_sectors(struct spdk_nvme_ns *ns)
     354             : {
     355           4 :         return _nvme_ns_get_data(ns)->nsze;
     356             : }
     357             : 
     358             : uint64_t
     359           1 : spdk_nvme_ns_get_size(struct spdk_nvme_ns *ns)
     360             : {
     361           1 :         return spdk_nvme_ns_get_num_sectors(ns) * spdk_nvme_ns_get_sector_size(ns);
     362             : }
     363             : 
     364             : uint32_t
     365           9 : spdk_nvme_ns_get_flags(struct spdk_nvme_ns *ns)
     366             : {
     367           9 :         return ns->flags;
     368             : }
     369             : 
     370             : enum spdk_nvme_pi_type
     371           2 : spdk_nvme_ns_get_pi_type(struct spdk_nvme_ns *ns) {
     372           2 :         return ns->pi_type;
     373             : }
     374             : 
     375             : enum spdk_nvme_pi_format
     376           1 : spdk_nvme_ns_get_pi_format(struct spdk_nvme_ns *ns) {
     377           1 :         return ns->pi_format;
     378             : }
     379             : 
     380             : bool
     381           2 : spdk_nvme_ns_supports_extended_lba(struct spdk_nvme_ns *ns)
     382             : {
     383           2 :         return (ns->flags & SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED) ? true : false;
     384             : }
     385             : 
     386             : bool
     387           2 : spdk_nvme_ns_supports_compare(struct spdk_nvme_ns *ns)
     388             : {
     389           2 :         return (ns->flags & SPDK_NVME_NS_COMPARE_SUPPORTED) ? true : false;
     390             : }
     391             : 
     392             : uint32_t
     393           2 : spdk_nvme_ns_get_md_size(struct spdk_nvme_ns *ns)
     394             : {
     395           2 :         return ns->md_size;
     396             : }
     397             : 
     398             : uint32_t
     399          13 : spdk_nvme_ns_get_format_index(const struct spdk_nvme_ns_data *nsdata)
     400             : {
     401          13 :         if (nsdata->nlbaf < 16) {
     402          13 :                 return nsdata->flbas.format;
     403             :         } else {
     404           0 :                 return ((nsdata->flbas.msb_format << 4) + nsdata->flbas.format);
     405             :         }
     406             : }
     407             : 
     408             : const struct spdk_nvme_ns_data *
     409           5 : spdk_nvme_ns_get_data(struct spdk_nvme_ns *ns)
     410             : {
     411           5 :         return _nvme_ns_get_data(ns);
     412             : }
     413             : 
     414             : const struct spdk_nvme_nvm_ns_data *
     415           0 : spdk_nvme_nvm_ns_get_data(struct spdk_nvme_ns *ns)
     416             : {
     417           0 :         return ns->nsdata_nvm;
     418             : }
     419             : 
     420             : /* We have to use the typedef in the function declaration to appease astyle. */
     421             : typedef enum spdk_nvme_dealloc_logical_block_read_value
     422             : spdk_nvme_dealloc_logical_block_read_value_t;
     423             : 
     424             : spdk_nvme_dealloc_logical_block_read_value_t
     425           2 : spdk_nvme_ns_get_dealloc_logical_block_read_value(
     426             :         struct spdk_nvme_ns *ns)
     427             : {
     428           2 :         struct spdk_nvme_ctrlr *ctrlr = ns->ctrlr;
     429           2 :         const struct spdk_nvme_ns_data *data = spdk_nvme_ns_get_data(ns);
     430             : 
     431           2 :         if (ctrlr->quirks & NVME_QUIRK_READ_ZERO_AFTER_DEALLOCATE) {
     432           1 :                 return SPDK_NVME_DEALLOC_READ_00;
     433             :         } else {
     434           1 :                 return data->dlfeat.bits.read_value;
     435             :         }
     436             : }
     437             : 
     438             : uint32_t
     439           2 : spdk_nvme_ns_get_optimal_io_boundary(struct spdk_nvme_ns *ns)
     440             : {
     441           2 :         return ns->sectors_per_stripe;
     442             : }
     443             : 
     444             : static const void *
     445          13 : nvme_ns_find_id_desc(const struct spdk_nvme_ns *ns, enum spdk_nvme_nidt type, size_t *length)
     446             : {
     447             :         const struct spdk_nvme_ns_id_desc *desc;
     448             :         size_t offset;
     449             : 
     450          13 :         offset = 0;
     451          17 :         while (offset + 4 < sizeof(ns->id_desc_list)) {
     452          17 :                 desc = (const struct spdk_nvme_ns_id_desc *)&ns->id_desc_list[offset];
     453             : 
     454          17 :                 if (desc->nidl == 0) {
     455             :                         /* End of list */
     456           6 :                         return NULL;
     457             :                 }
     458             : 
     459             :                 /*
     460             :                  * Check if this descriptor fits within the list.
     461             :                  * 4 is the fixed-size descriptor header (not counted in NIDL).
     462             :                  */
     463          11 :                 if (offset + desc->nidl + 4 > sizeof(ns->id_desc_list)) {
     464             :                         /* Descriptor longer than remaining space in list (invalid) */
     465           0 :                         return NULL;
     466             :                 }
     467             : 
     468          11 :                 if (desc->nidt == type) {
     469           7 :                         *length = desc->nidl;
     470           7 :                         return &desc->nid[0];
     471             :                 }
     472             : 
     473           4 :                 offset += 4 + desc->nidl;
     474             :         }
     475             : 
     476           0 :         return NULL;
     477             : }
     478             : 
     479             : const uint8_t *
     480           0 : spdk_nvme_ns_get_nguid(const struct spdk_nvme_ns *ns)
     481             : {
     482             :         const uint8_t *nguid;
     483           0 :         size_t size;
     484             : 
     485           0 :         nguid = nvme_ns_find_id_desc(ns, SPDK_NVME_NIDT_NGUID, &size);
     486           0 :         if (nguid && size != SPDK_SIZEOF_MEMBER(struct spdk_nvme_ns_data, nguid)) {
     487           0 :                 SPDK_WARNLOG("Invalid NIDT_NGUID descriptor length reported: %zu (expected: %zu)\n",
     488             :                              size, SPDK_SIZEOF_MEMBER(struct spdk_nvme_ns_data, nguid));
     489           0 :                 return NULL;
     490             :         }
     491             : 
     492           0 :         return nguid;
     493             : }
     494             : 
     495             : const struct spdk_uuid *
     496           5 : spdk_nvme_ns_get_uuid(const struct spdk_nvme_ns *ns)
     497             : {
     498             :         const struct spdk_uuid *uuid;
     499           5 :         size_t uuid_size;
     500             : 
     501           5 :         uuid = nvme_ns_find_id_desc(ns, SPDK_NVME_NIDT_UUID, &uuid_size);
     502           5 :         if (uuid && uuid_size != sizeof(*uuid)) {
     503           0 :                 SPDK_WARNLOG("Invalid NIDT_UUID descriptor length reported: %zu (expected: %zu)\n",
     504             :                              uuid_size, sizeof(*uuid));
     505           0 :                 return NULL;
     506             :         }
     507             : 
     508           5 :         return uuid;
     509             : }
     510             : 
     511             : static enum spdk_nvme_csi
     512           5 : nvme_ns_get_csi(const struct spdk_nvme_ns *ns) {
     513             :         const uint8_t *csi;
     514           5 :         size_t csi_size;
     515             : 
     516           5 :         csi = nvme_ns_find_id_desc(ns, SPDK_NVME_NIDT_CSI, &csi_size);
     517           5 :         if (csi && csi_size != sizeof(*csi))
     518             :         {
     519           0 :                 SPDK_WARNLOG("Invalid NIDT_CSI descriptor length reported: %zu (expected: %zu)\n",
     520             :                              csi_size, sizeof(*csi));
     521           0 :                 return SPDK_NVME_CSI_NVM;
     522             :         }
     523           5 :         if (!csi)
     524             :         {
     525           2 :                 if (ns->ctrlr->cap.bits.css & SPDK_NVME_CAP_CSS_IOCS) {
     526           1 :                         SPDK_WARNLOG("CSI not reported for NSID: %" PRIu32 "\n", ns->id);
     527             :                 }
     528           2 :                 return SPDK_NVME_CSI_NVM;
     529             :         }
     530             : 
     531           3 :         return *csi;
     532             : }
     533             : 
     534             : void
     535           1 : nvme_ns_set_id_desc_list_data(struct spdk_nvme_ns *ns)
     536             : {
     537           1 :         ns->csi = nvme_ns_get_csi(ns);
     538           1 : }
     539             : 
     540             : enum spdk_nvme_csi
     541           2 : spdk_nvme_ns_get_csi(const struct spdk_nvme_ns *ns) {
     542           2 :         return ns->csi;
     543             : }
     544             : 
     545             : void
     546          13 : nvme_ns_free_zns_specific_data(struct spdk_nvme_ns *ns)
     547             : {
     548          13 :         if (!ns->id) {
     549           0 :                 return;
     550             :         }
     551             : 
     552          13 :         if (ns->nsdata_zns) {
     553           1 :                 spdk_free(ns->nsdata_zns);
     554           1 :                 ns->nsdata_zns = NULL;
     555             :         }
     556             : }
     557             : 
     558             : void
     559          11 : nvme_ns_free_nvm_specific_data(struct spdk_nvme_ns *ns)
     560             : {
     561          11 :         if (!ns->id) {
     562           0 :                 return;
     563             :         }
     564             : 
     565          11 :         if (ns->nsdata_nvm) {
     566           1 :                 spdk_free(ns->nsdata_nvm);
     567           1 :                 ns->nsdata_nvm = NULL;
     568             :         }
     569             : }
     570             : 
     571             : void
     572          10 : nvme_ns_free_iocs_specific_data(struct spdk_nvme_ns *ns)
     573             : {
     574          10 :         nvme_ns_free_zns_specific_data(ns);
     575          10 :         nvme_ns_free_nvm_specific_data(ns);
     576          10 : }
     577             : 
     578             : bool
     579           5 : nvme_ns_has_supported_iocs_specific_data(struct spdk_nvme_ns *ns)
     580             : {
     581           5 :         switch (ns->csi) {
     582           3 :         case SPDK_NVME_CSI_NVM:
     583           3 :                 if (ns->ctrlr->cdata.ctratt.bits.elbas) {
     584           1 :                         return true;
     585             :                 }
     586             : 
     587           2 :                 return false;
     588           1 :         case SPDK_NVME_CSI_ZNS:
     589           1 :                 return true;
     590           1 :         default:
     591           1 :                 SPDK_WARNLOG("Unsupported CSI: %u for NSID: %u\n", ns->csi, ns->id);
     592           1 :                 return false;
     593             :         }
     594             : }
     595             : 
     596             : uint32_t
     597           1 : spdk_nvme_ns_get_ana_group_id(const struct spdk_nvme_ns *ns)
     598             : {
     599           1 :         return ns->ana_group_id;
     600             : }
     601             : 
     602             : enum spdk_nvme_ana_state
     603           1 : spdk_nvme_ns_get_ana_state(const struct spdk_nvme_ns *ns) {
     604           1 :         return ns->ana_state;
     605             : }
     606             : 
     607             : int
     608          11 : nvme_ns_construct(struct spdk_nvme_ns *ns, uint32_t id,
     609             :                   struct spdk_nvme_ctrlr *ctrlr)
     610             : {
     611             :         int     rc;
     612             : 
     613          11 :         assert(id > 0);
     614             : 
     615          11 :         ns->ctrlr = ctrlr;
     616          11 :         ns->id = id;
     617             :         /* This will be overwritten when reading ANA log page. */
     618          11 :         ns->ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
     619             : 
     620          11 :         rc = nvme_ctrlr_identify_ns(ns);
     621          11 :         if (rc != 0) {
     622           0 :                 return rc;
     623             :         }
     624             : 
     625             :         /* skip Identify NS ID Descriptor List for inactive NS */
     626          11 :         if (!spdk_nvme_ns_is_active(ns)) {
     627          10 :                 return 0;
     628             :         }
     629             : 
     630           1 :         rc = nvme_ctrlr_identify_id_desc(ns);
     631           1 :         if (rc != 0) {
     632           0 :                 return rc;
     633             :         }
     634             : 
     635           2 :         if (nvme_ctrlr_multi_iocs_enabled(ctrlr) &&
     636           1 :             nvme_ns_has_supported_iocs_specific_data(ns)) {
     637           0 :                 rc = nvme_ctrlr_identify_ns_iocs_specific(ns);
     638           0 :                 if (rc != 0) {
     639           0 :                         return rc;
     640             :                 }
     641             :         }
     642             : 
     643           1 :         return 0;
     644             : }
     645             : 
     646             : void
     647          10 : nvme_ns_destruct(struct spdk_nvme_ns *ns)
     648             : {
     649             :         struct spdk_nvme_ns_data *nsdata;
     650             : 
     651          10 :         if (!ns->id) {
     652           0 :                 return;
     653             :         }
     654             : 
     655          10 :         nsdata = _nvme_ns_get_data(ns);
     656          10 :         memset(nsdata, 0, sizeof(*nsdata));
     657          10 :         memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list));
     658          10 :         nvme_ns_free_iocs_specific_data(ns);
     659          10 :         ns->sector_size = 0;
     660          10 :         ns->extended_lba_size = 0;
     661          10 :         ns->md_size = 0;
     662          10 :         ns->pi_type = 0;
     663          10 :         ns->sectors_per_max_io = 0;
     664          10 :         ns->sectors_per_max_io_no_md = 0;
     665          10 :         ns->sectors_per_stripe = 0;
     666          10 :         ns->flags = 0;
     667          10 :         ns->csi = SPDK_NVME_CSI_NVM;
     668             : }

Generated by: LCOV version 1.15