LCOV - code coverage report
Current view: top level - spdk/test/nvme/fdp - fdp.c (source / functions) Hit Total Coverage
Test: Combined Lines: 388 506 76.7 %
Date: 2024-07-12 08:23:09 Functions: 22 24 91.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 273 685 39.9 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (c) 2023 Samsung Electronics Co., Ltd.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : #include "spdk/nvme.h"
       8                 :            : #include "spdk/env.h"
       9                 :            : #include "spdk/util.h"
      10                 :            : 
      11                 :            : #define FDP_LOG_PAGE_SIZE               4096
      12                 :            : #define FDP_NR_RUHS_DESC                256
      13                 :            : #define MAX_FDP_EVENTS                  0xFF
      14                 :            : 
      15                 :            : #define SET_EVENT_TYPES ((uint8_t[]){0x0, 0x1, 0x2, 0x3, 0x80, 0x81})
      16                 :            : 
      17                 :            : struct ns_entry {
      18                 :            :         struct spdk_nvme_ctrlr  *ctrlr;
      19                 :            :         struct spdk_nvme_ns     *ns;
      20                 :            :         struct ns_entry         *next;
      21                 :            : };
      22                 :            : 
      23                 :            : static struct ns_entry *g_namespaces = NULL;
      24                 :            : static struct spdk_nvme_transport_id g_trid;
      25                 :            : static bool g_use_trid = false;
      26                 :            : 
      27                 :            : static int g_outstanding_commands;
      28                 :            : static int g_fdp_command_result;
      29                 :            : static uint32_t g_feat_result;
      30                 :            : static uint16_t ph_for_fdp_event;
      31                 :            : static uint8_t rgif;
      32                 :            : static uint8_t fdpci;
      33                 :            : static uint16_t pid_for_ruhu;
      34                 :            : static uint32_t g_spdk_sge_size = 4096;
      35                 :            : 
      36                 :            : static union spdk_nvme_feat_fdp_cdw12 fdp_res;
      37                 :            : static uint8_t g_fdp_cfg_log_page_buf[FDP_LOG_PAGE_SIZE];
      38                 :            : static uint8_t g_fdp_ruhu_log_page_buf[FDP_LOG_PAGE_SIZE];
      39                 :            : static uint8_t g_fdp_events_log_page_buf[FDP_LOG_PAGE_SIZE];
      40                 :            : 
      41                 :            : static struct spdk_nvme_fdp_stats_log_page g_fdp_stats_log_page;
      42                 :            : static struct spdk_nvme_fdp_cfg_log_page *g_fdp_cfg_log_page = (void *)g_fdp_cfg_log_page_buf;
      43                 :            : static struct spdk_nvme_fdp_ruhu_log_page *g_fdp_ruhu_log_page = (void *)g_fdp_ruhu_log_page_buf;
      44                 :            : static struct spdk_nvme_fdp_events_log_page *g_fdp_events_log_page = (void *)
      45                 :            :                 g_fdp_events_log_page_buf;
      46                 :            : 
      47                 :            : struct io_request {
      48                 :            :         void *contig;
      49                 :            :         uint32_t sgl_offset;
      50                 :            :         uint32_t buf_size;
      51                 :            : };
      52                 :            : 
      53                 :            : static void
      54                 :          2 : nvme_req_reset_sgl(void *cb_arg, uint32_t sgl_offset)
      55                 :            : {
      56                 :          2 :         struct io_request *req = (struct io_request *)cb_arg;
      57                 :            : 
      58                 :          2 :         req->sgl_offset = sgl_offset;
      59                 :          2 : }
      60                 :            : 
      61                 :            : static int
      62                 :         16 : nvme_req_next_sge(void *cb_arg, void **address, uint32_t *length)
      63                 :            : {
      64                 :         16 :         struct io_request *req = (struct io_request *)cb_arg;
      65                 :            :         uint32_t iov_len;
      66                 :            : 
      67                 :         16 :         *address = req->contig;
      68                 :            : 
      69         [ +  + ]:         16 :         if (req->sgl_offset) {
      70                 :         14 :                 *address += req->sgl_offset;
      71                 :            :         }
      72                 :            : 
      73                 :         16 :         iov_len = req->buf_size - req->sgl_offset;
      74         [ +  + ]:         16 :         if (iov_len > g_spdk_sge_size) {
      75                 :         14 :                 iov_len = g_spdk_sge_size;
      76                 :            :         }
      77                 :            : 
      78                 :         16 :         req->sgl_offset += iov_len;
      79                 :         16 :         *length = iov_len;
      80                 :            : 
      81                 :         16 :         return 0;
      82                 :            : }
      83                 :            : 
      84                 :            : static void
      85                 :          3 : get_feat_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
      86                 :            : {
      87   [ +  -  -  + ]:          3 :         if (spdk_nvme_cpl_is_error(cpl)) {
      88                 :          0 :                 g_fdp_command_result = -1;
      89                 :            :         } else {
      90                 :          3 :                 g_fdp_command_result = 0;
      91                 :          3 :                 g_feat_result = cpl->cdw0;
      92                 :            :         }
      93                 :            : 
      94                 :          3 :         g_outstanding_commands--;
      95                 :          3 : }
      96                 :            : 
      97                 :            : static void
      98                 :          7 : cmd_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
      99                 :            : {
     100   [ +  -  -  + ]:          7 :         if (spdk_nvme_cpl_is_error(cpl)) {
     101                 :          0 :                 g_fdp_command_result = -1;
     102                 :            :         } else {
     103                 :          7 :                 g_fdp_command_result = 0;
     104                 :            :         }
     105                 :            : 
     106                 :          7 :         g_outstanding_commands--;
     107                 :          7 : }
     108                 :            : 
     109                 :            : static void
     110                 :          0 : print_uint128_hex(uint64_t *v)
     111                 :            : {
     112                 :          0 :         unsigned long long lo = v[0], hi = v[1];
     113         [ #  # ]:          0 :         if (hi) {
     114         [ #  # ]:          0 :                 printf("0x%llX%016llX", hi, lo);
     115                 :            :         } else {
     116         [ #  # ]:          0 :                 printf("0x%llX", lo);
     117                 :            :         }
     118                 :          0 : }
     119                 :            : 
     120                 :            : static void
     121                 :          3 : print_uint128_dec(uint64_t *v)
     122                 :            : {
     123                 :          3 :         unsigned long long lo = v[0], hi = v[1];
     124         [ -  + ]:          3 :         if (hi) {
     125                 :            :                 /* can't handle large (>64-bit) decimal values for now, so fall back to hex */
     126                 :          0 :                 print_uint128_hex(v);
     127                 :            :         } else {
     128         [ -  + ]:          3 :                 printf("%llu", (unsigned long long)lo);
     129                 :            :         }
     130                 :          3 : }
     131                 :            : 
     132                 :            : static int
     133                 :          1 : set_fdp_events(struct spdk_nvme_ns *ns)
     134                 :            : {
     135                 :            :         int ret;
     136                 :          1 :         uint8_t fdp_event_type_list[6] = {};
     137                 :          1 :         uint32_t nfdp_events = 6;
     138                 :            :         uint32_t cdw11, cdw12;
     139                 :          1 :         struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
     140                 :          1 :         int nsid = spdk_nvme_ns_get_id(ns);
     141                 :            : 
     142   [ -  +  -  + ]:          1 :         memcpy(fdp_event_type_list, SET_EVENT_TYPES, nfdp_events);
     143                 :          1 :         g_outstanding_commands = 0;
     144                 :          1 :         g_fdp_command_result = -1;
     145                 :            : 
     146                 :          1 :         cdw11 = (nfdp_events << 16) | ph_for_fdp_event;
     147                 :            :         /* Enable FDP event */
     148                 :          1 :         cdw12 = 1;
     149                 :            : 
     150                 :          1 :         ret = spdk_nvme_ctrlr_cmd_set_feature_ns(ctrlr, SPDK_NVME_FEAT_FDP_EVENTS, cdw11, cdw12,
     151                 :            :                         fdp_event_type_list, nfdp_events,
     152                 :            :                         get_feat_completion, NULL, nsid);
     153         [ -  + ]:          1 :         if (ret) {
     154   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Set Feature (fdp events) failed\n\n");
     155                 :          0 :                 return -1;
     156                 :            :         }
     157                 :            : 
     158                 :          1 :         g_outstanding_commands++;
     159         [ +  + ]:          5 :         while (g_outstanding_commands) {
     160                 :          4 :                 spdk_nvme_ctrlr_process_admin_completions(ctrlr);
     161                 :            :         }
     162                 :            : 
     163         [ -  + ]:          1 :         if (g_fdp_command_result) {
     164   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Set Feature (fdp events) failed\n\n");
     165                 :          0 :                 return -1;
     166                 :            :         }
     167                 :            : 
     168   [ -  +  -  + ]:          1 :         fprintf(stdout, "Set Feature: Enabling FDP events on Placement handle: #%u Success\n\n",
     169                 :            :                 ph_for_fdp_event);
     170                 :          1 :         return 0;
     171                 :            : }
     172                 :            : 
     173                 :            : static int
     174                 :          1 : get_fdp_events(struct spdk_nvme_ns *ns)
     175                 :            : {
     176                 :            :         int ret;
     177                 :            :         uint32_t i, cdw11;
     178                 :          1 :         struct spdk_nvme_fdp_event_desc events[MAX_FDP_EVENTS];
     179                 :            :         struct spdk_nvme_fdp_event_desc *event_desc;
     180                 :          1 :         struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
     181                 :          1 :         int nsid = spdk_nvme_ns_get_id(ns);
     182                 :            : 
     183                 :          1 :         g_outstanding_commands = 0;
     184                 :          1 :         g_fdp_command_result = -1;
     185                 :          1 :         g_feat_result = 0;
     186                 :            : 
     187                 :          1 :         cdw11 = (MAX_FDP_EVENTS << 16) | ph_for_fdp_event;
     188                 :            : 
     189                 :          1 :         ret = spdk_nvme_ctrlr_cmd_get_feature_ns(ctrlr, SPDK_NVME_FEAT_FDP_EVENTS, cdw11,
     190                 :            :                         events, MAX_FDP_EVENTS * sizeof(struct spdk_nvme_fdp_event_desc),
     191                 :            :                         get_feat_completion, NULL, nsid);
     192         [ -  + ]:          1 :         if (ret) {
     193   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Get Feature (fdp events) failed\n\n");
     194                 :          0 :                 return -1;
     195                 :            :         }
     196                 :            : 
     197                 :          1 :         g_outstanding_commands++;
     198         [ +  + ]:          6 :         while (g_outstanding_commands) {
     199                 :          5 :                 spdk_nvme_ctrlr_process_admin_completions(ctrlr);
     200                 :            :         }
     201                 :            : 
     202         [ -  + ]:          1 :         if (g_fdp_command_result) {
     203   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Get Feature (fdp events) failed\n\n");
     204                 :          0 :                 return -1;
     205                 :            :         }
     206                 :            : 
     207   [ -  +  -  + ]:          1 :         fprintf(stdout, "Get Feature: FDP Events for Placement handle: #%u\n", ph_for_fdp_event);
     208   [ -  +  -  + ]:          1 :         fprintf(stdout, "========================\n");
     209   [ -  +  -  + ]:          1 :         fprintf(stdout, "Number of FDP Events: %u\n", g_feat_result);
     210                 :            : 
     211                 :          1 :         event_desc = events;
     212         [ +  + ]:          7 :         for (i = 0; i < g_feat_result; i++) {
     213   [ -  +  -  + ]:          6 :                 fprintf(stdout, "FDP Event: #%u  Type: %s", i,
     214         [ +  + ]:          6 :                         event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_RU_NOT_WRITTEN_CAPACITY ?
     215                 :            :                         "RU Not Written to Capacity   " :
     216                 :          5 :                         event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_RU_TIME_LIMIT_EXCEEDED ?
     217         [ +  + ]:          9 :                         "RU Time Limit Exceeded       " :
     218                 :          4 :                         event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_CTRLR_RESET_MODIFY_RUH ?
     219         [ +  + ]:          7 :                         "Ctrlr Reset Modified RUH's   " :
     220                 :          3 :                         event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_INVALID_PLACEMENT_ID ?
     221         [ +  + ]:          5 :                         "Invalid Placement Identifier " :
     222         [ +  + ]:          3 :                         event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED ? "Media Reallocated            " :
     223                 :          1 :                         event_desc->fdp_etype == SPDK_NVME_FDP_EVENT_IMPLICIT_MODIFIED_RUH ?
     224         [ +  - ]:          1 :                         "Implicitly modified RUH      " :
     225                 :            :                         "Reserved");
     226   [ -  +  -  + ]:          6 :                 fprintf(stdout, "  Enabled: %s\n",
     227         [ +  + ]:          6 :                         event_desc->fdpeta.bits.fdp_ee ? "Yes" : "No");
     228                 :          6 :                 event_desc++;
     229                 :            :         }
     230                 :            : 
     231         [ -  + ]:          1 :         fprintf(stdout, "\n");
     232                 :          1 :         return 0;
     233                 :            : }
     234                 :            : 
     235                 :            : static int
     236                 :          1 : get_fdp(struct spdk_nvme_ns *ns)
     237                 :            : {
     238                 :            :         int ret;
     239                 :            :         uint32_t cdw11;
     240                 :          1 :         struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
     241                 :          1 :         const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
     242                 :            : 
     243                 :          1 :         g_outstanding_commands = 0;
     244                 :          1 :         g_fdp_command_result = -1;
     245                 :          1 :         g_feat_result = 0;
     246                 :            : 
     247                 :          1 :         cdw11 = nsdata->endgid;
     248                 :            : 
     249                 :          1 :         ret = spdk_nvme_ctrlr_cmd_get_feature(ctrlr, SPDK_NVME_FEAT_FDP, cdw11, NULL, 0,
     250                 :            :                                               get_feat_completion, NULL);
     251         [ -  + ]:          1 :         if (ret) {
     252   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Get Feature (fdp) failed\n\n");
     253                 :          0 :                 return -1;
     254                 :            :         }
     255                 :            : 
     256                 :          1 :         g_outstanding_commands++;
     257         [ +  + ]:          5 :         while (g_outstanding_commands) {
     258                 :          4 :                 spdk_nvme_ctrlr_process_admin_completions(ctrlr);
     259                 :            :         }
     260                 :            : 
     261         [ -  + ]:          1 :         if (g_fdp_command_result) {
     262   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Get Feature (fdp) failed\n\n");
     263                 :          0 :                 return -1;
     264                 :            :         }
     265                 :            : 
     266                 :          1 :         fdp_res.raw = g_feat_result;
     267                 :            : 
     268   [ -  +  -  + ]:          1 :         fprintf(stdout, "Get Feature: FDP:\n");
     269   [ -  +  -  + ]:          1 :         fprintf(stdout, "=================\n");
     270   [ -  +  -  + ]:          1 :         fprintf(stdout, "  Enabled:                 %s\n",
     271         [ +  - ]:          1 :                 fdp_res.bits.fdpe ? "Yes" : "No");
     272   [ -  +  -  + ]:          1 :         fprintf(stdout, "  FDP configuration Index: %u\n\n", fdp_res.bits.fdpci);
     273                 :            : 
     274                 :          1 :         return 0;
     275                 :            : }
     276                 :            : 
     277                 :            : static int
     278                 :          1 : check_fdp_write(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
     279                 :            : {
     280                 :            :         int ret;
     281                 :            :         uint32_t sector_size, lba_count;
     282                 :            :         uint64_t lba;
     283                 :            :         struct io_request *req;
     284                 :          1 :         struct spdk_nvme_ns_cmd_ext_io_opts ext_opts;
     285                 :            : 
     286                 :          1 :         g_outstanding_commands = 0;
     287                 :          1 :         g_fdp_command_result = -1;
     288                 :            : 
     289                 :          1 :         ext_opts.size = SPDK_SIZEOF(&ext_opts, cdw13);
     290                 :          1 :         ext_opts.io_flags = SPDK_NVME_IO_FLAGS_DATA_PLACEMENT_DIRECTIVE;
     291                 :          1 :         ext_opts.metadata = NULL;
     292         [ -  + ]:          1 :         ext_opts.cdw13 = (pid_for_ruhu << 16);
     293                 :            : 
     294                 :          1 :         sector_size = spdk_nvme_ns_get_sector_size(ns);
     295                 :            : 
     296                 :          1 :         req = spdk_zmalloc(sizeof(*req), 0, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
     297         [ -  + ]:          1 :         assert(req);
     298                 :            : 
     299                 :          1 :         lba = 0;
     300                 :          1 :         lba_count = 8;
     301                 :          1 :         req->buf_size = sector_size * lba_count;
     302                 :          1 :         req->contig = spdk_zmalloc(req->buf_size, 0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
     303                 :            :                                    SPDK_MALLOC_DMA);
     304         [ -  + ]:          1 :         assert(req->contig);
     305                 :            : 
     306                 :          1 :         ret = spdk_nvme_ns_cmd_writev_ext(ns, qpair, lba, lba_count, cmd_completion, req,
     307                 :            :                                           nvme_req_reset_sgl, nvme_req_next_sge, &ext_opts);
     308                 :            : 
     309         [ -  + ]:          1 :         if (ret) {
     310   [ #  #  #  # ]:          0 :                 fprintf(stderr, "spdk_nvme_ns_cmd_writev_ext failed\n\n");
     311                 :          0 :                 return -1;
     312                 :            :         }
     313                 :            : 
     314                 :          1 :         g_outstanding_commands++;
     315         [ +  + ]:        152 :         while (g_outstanding_commands) {
     316                 :        151 :                 spdk_nvme_qpair_process_completions(qpair, 100);
     317                 :            :         }
     318                 :            : 
     319         [ -  + ]:          1 :         if (g_fdp_command_result) {
     320   [ #  #  #  # ]:          0 :                 fprintf(stderr, "FDP write on placement id: %u failed\n\n", pid_for_ruhu);
     321                 :            :         } else {
     322   [ -  +  -  + ]:          1 :                 fprintf(stdout, "FDP write on placement id: %u success\n\n", pid_for_ruhu);
     323                 :            :         }
     324                 :            : 
     325                 :          1 :         spdk_free(req->contig);
     326                 :          1 :         spdk_free(req);
     327                 :          1 :         return g_fdp_command_result;
     328                 :            : }
     329                 :            : 
     330                 :            : static int
     331                 :          1 : reclaim_unit_handle_update(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
     332                 :            : {
     333                 :            :         int ret;
     334                 :          1 :         uint32_t npids = 1;
     335                 :          1 :         uint16_t pid_list[1] = {};
     336                 :            : 
     337                 :          1 :         memcpy(pid_list, &pid_for_ruhu, sizeof(pid_list));
     338                 :          1 :         g_outstanding_commands = 0;
     339                 :          1 :         g_fdp_command_result = -1;
     340                 :            : 
     341                 :          1 :         ret = spdk_nvme_ns_cmd_io_mgmt_send(ns, qpair, pid_list, npids * sizeof(uint16_t),
     342                 :          1 :                                             SPDK_NVME_FDP_IO_MGMT_SEND_RUHU, npids - 1, cmd_completion, NULL);
     343         [ -  + ]:          1 :         if (ret) {
     344   [ #  #  #  # ]:          0 :                 fprintf(stderr, "IO management send: RUH update failed\n\n");
     345                 :          0 :                 return -1;
     346                 :            :         }
     347                 :            : 
     348                 :          1 :         g_outstanding_commands++;
     349         [ +  + ]:         22 :         while (g_outstanding_commands) {
     350                 :         21 :                 spdk_nvme_qpair_process_completions(qpair, 100);
     351                 :            :         }
     352                 :            : 
     353         [ -  + ]:          1 :         if (g_fdp_command_result) {
     354   [ #  #  #  # ]:          0 :                 fprintf(stderr, "IO management send: RUH update failed\n\n");
     355                 :          0 :                 return -1;
     356                 :            :         }
     357                 :            : 
     358   [ -  +  -  + ]:          1 :         fprintf(stdout, "IO mgmt send: RUH update for Placement ID: #%u Success\n\n",
     359                 :            :                 pid_for_ruhu);
     360                 :          1 :         return 0;
     361                 :            : }
     362                 :            : 
     363                 :            : static int
     364                 :          1 : reclaim_unit_handle_status(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
     365                 :            : {
     366                 :            :         int ret;
     367                 :            :         uint32_t i;
     368                 :            :         size_t fdp_ruhs_size;
     369                 :            :         struct spdk_nvme_fdp_ruhs *fdp_ruhs;
     370                 :            :         struct spdk_nvme_fdp_ruhs_desc *ruhs_desc;
     371                 :            : 
     372                 :          1 :         g_outstanding_commands = 0;
     373                 :          1 :         g_fdp_command_result = -1;
     374                 :            : 
     375                 :          1 :         fdp_ruhs_size = sizeof(struct spdk_nvme_fdp_ruhs) +
     376                 :            :                         FDP_NR_RUHS_DESC * sizeof(struct spdk_nvme_fdp_ruhs_desc);
     377                 :          1 :         fdp_ruhs = calloc(1, fdp_ruhs_size);
     378         [ -  + ]:          1 :         if (fdp_ruhs == NULL) {
     379   [ #  #  #  # ]:          0 :                 fprintf(stderr, "FDP reclaim unit handle status allocation failed!\n\n");
     380                 :          0 :                 return -1;
     381                 :            :         }
     382                 :            : 
     383                 :          1 :         ret = spdk_nvme_ns_cmd_io_mgmt_recv(ns, qpair, fdp_ruhs, fdp_ruhs_size,
     384                 :            :                                             SPDK_NVME_FDP_IO_MGMT_RECV_RUHS, 0, cmd_completion, NULL);
     385         [ -  + ]:          1 :         if (ret) {
     386   [ #  #  #  # ]:          0 :                 fprintf(stderr, "IO management receive: RUH status failed\n\n");
     387                 :          0 :                 free(fdp_ruhs);
     388                 :          0 :                 return -1;
     389                 :            :         }
     390                 :            : 
     391                 :          1 :         g_outstanding_commands++;
     392         [ +  + ]:         15 :         while (g_outstanding_commands) {
     393                 :         14 :                 spdk_nvme_qpair_process_completions(qpair, 100);
     394                 :            :         }
     395                 :            : 
     396         [ -  + ]:          1 :         if (g_fdp_command_result) {
     397   [ #  #  #  # ]:          0 :                 fprintf(stderr, "IO management receive: RUH status failed\n\n");
     398                 :          0 :                 free(fdp_ruhs);
     399                 :          0 :                 return -1;
     400                 :            :         }
     401                 :            : 
     402   [ -  +  -  + ]:          1 :         fprintf(stdout, "FDP Reclaim unit handle status\n");
     403   [ -  +  -  + ]:          1 :         fprintf(stdout, "==============================\n");
     404                 :            : 
     405   [ -  +  -  + ]:          1 :         fprintf(stdout, "Number of RUHS descriptors:   %u\n", fdp_ruhs->nruhsd);
     406         [ +  + ]:          3 :         for (i = 0; i < fdp_ruhs->nruhsd; i++) {
     407                 :          2 :                 ruhs_desc = &fdp_ruhs->ruhs_desc[i];
     408                 :            : 
     409         [ -  + ]:          4 :                 fprintf(stdout,
     410                 :            :                         "RUHS Desc: #%04u  PID: 0x%04x  RUHID: 0x%04x  ERUT: 0x%08x  RUAMW: 0x%016"PRIx64"\n",
     411         [ -  + ]:          2 :                         i, ruhs_desc->pid, ruhs_desc->ruhid, ruhs_desc->earutr, ruhs_desc->ruamw);
     412                 :            :         }
     413         [ -  + ]:          1 :         fprintf(stdout, "\n");
     414                 :            : 
     415                 :            :         /* Use this Placement Identifier for Reclaim unit handle Update */
     416                 :          1 :         pid_for_ruhu = (&fdp_ruhs->ruhs_desc[0])->pid;
     417                 :            : 
     418                 :            :         /* Use this Placement Handle to enable FDP events */
     419         [ -  + ]:          1 :         ph_for_fdp_event = pid_for_ruhu & ((1 << (16 - rgif)) - 1);
     420                 :            : 
     421                 :          1 :         free(fdp_ruhs);
     422                 :          1 :         return 0;
     423                 :            : }
     424                 :            : 
     425                 :            : static int
     426                 :          1 : get_fdp_cfg_log_page(struct spdk_nvme_ns *ns)
     427                 :            : {
     428                 :            :         uint32_t i, j;
     429                 :            :         struct spdk_nvme_fdp_cfg_descriptor *cfg_desc;
     430                 :          1 :         struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
     431                 :          1 :         const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
     432                 :            :         void *log;
     433                 :            : 
     434                 :          1 :         g_outstanding_commands = 0;
     435                 :          1 :         g_fdp_command_result = -1;
     436                 :            : 
     437                 :            :         /* Fetch the FDP configurations log page for only 4096 bytes */
     438         [ +  - ]:          1 :         if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_CONFIGURATIONS, 0,
     439         [ -  + ]:          1 :                         g_fdp_cfg_log_page, FDP_LOG_PAGE_SIZE, 0, 0, (nsdata->endgid << 16),
     440                 :            :                         0, cmd_completion, NULL) == 0) {
     441                 :          1 :                 g_outstanding_commands++;
     442                 :            :         } else {
     443   [ #  #  #  # ]:          0 :                 fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP config) failed\n\n");
     444                 :          0 :                 return -1;
     445                 :            :         }
     446                 :            : 
     447         [ +  + ]:          6 :         while (g_outstanding_commands) {
     448                 :          5 :                 spdk_nvme_ctrlr_process_admin_completions(ctrlr);
     449                 :            :         }
     450                 :            : 
     451         [ -  + ]:          1 :         if (g_fdp_command_result) {
     452   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Failed to get FDP configuration log page\n\n");
     453                 :          0 :                 return -1;
     454                 :            :         }
     455                 :            : 
     456   [ -  +  -  + ]:          1 :         fprintf(stdout, "FDP configurations log page\n");
     457   [ -  +  -  + ]:          1 :         fprintf(stdout, "===========================\n");
     458                 :            : 
     459   [ -  +  -  + ]:          1 :         fprintf(stdout, "Number of FDP configurations:         %u\n", g_fdp_cfg_log_page->ncfg + 1);
     460   [ -  +  -  + ]:          1 :         fprintf(stdout, "Version:                              %u\n", g_fdp_cfg_log_page->version);
     461   [ -  +  -  + ]:          1 :         fprintf(stdout, "Size:                                 %u\n", g_fdp_cfg_log_page->size);
     462                 :            : 
     463                 :          1 :         log = g_fdp_cfg_log_page->cfg_desc;
     464         [ +  + ]:          2 :         for (i = 0; i <= g_fdp_cfg_log_page->ncfg; i++) {
     465                 :          1 :                 cfg_desc = log;
     466   [ -  +  -  + ]:          1 :                 fprintf(stdout, "FDP Configuration Descriptor:         %u\n", i);
     467   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Descriptor Size:                    %u\n", cfg_desc->ds);
     468         [ -  + ]:          1 :                 fprintf(stdout, "  Reclaim Group Identifier format:    %u\n",
     469         [ -  + ]:          1 :                         cfg_desc->fdpa.bits.rgif);
     470   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  FDP Volatile Write Cache:           %s\n",
     471         [ -  + ]:          1 :                         cfg_desc->fdpa.bits.fdpvwc ? "Present" : "Not Present");
     472   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  FDP Configuration:                  %s\n",
     473         [ +  - ]:          1 :                         cfg_desc->fdpa.bits.fdpcv ? "Valid" : "Invalid");
     474   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Vendor Specific Size:               %u\n", cfg_desc->vss);
     475   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Number of Reclaim Groups:           %u\n", cfg_desc->nrg);
     476   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Number of Recalim Unit Handles:     %u\n", cfg_desc->nruh);
     477   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Max Placement Identifiers:          %u\n", cfg_desc->maxpids + 1);
     478   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Number of Namespaces Suppprted:     %u\n", cfg_desc->nns);
     479   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Reclaim unit Nominal Size:          %" PRIx64 " bytes\n", cfg_desc->runs);
     480   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Estimated Reclaim Unit Time Limit:  ");
     481         [ -  + ]:          1 :                 if (cfg_desc->erutl) {
     482   [ #  #  #  # ]:          0 :                         fprintf(stdout, "%u seconds\n", cfg_desc->erutl);
     483                 :            :                 } else {
     484   [ -  +  -  + ]:          1 :                         fprintf(stdout, "Not Reported\n");
     485                 :            :                 }
     486         [ +  + ]:          9 :                 for (j = 0; j < cfg_desc->nruh; j++) {
     487   [ -  +  -  + ]:          8 :                         fprintf(stdout, "    RUH Desc #%03d:          RUH Type: %s\n", j,
     488         [ -  + ]:          8 :                                 cfg_desc->ruh_desc[j].ruht == SPDK_NVME_FDP_RUHT_INITIALLY_ISOLATED ? "Initially Isolated" :
     489         [ #  # ]:          0 :                                 cfg_desc->ruh_desc[j].ruht == SPDK_NVME_FDP_RUHT_PERSISTENTLY_ISOLATED ? "Persistently Isolated" :
     490                 :            :                                 "Reserved");
     491                 :            :                 }
     492         [ +  - ]:          1 :                 if (i == fdpci) {
     493                 :          1 :                         rgif = cfg_desc->fdpa.bits.rgif;
     494                 :            :                 }
     495                 :          1 :                 log += cfg_desc->ds;
     496                 :            :         }
     497                 :            : 
     498         [ -  + ]:          1 :         fprintf(stdout, "\n");
     499                 :          1 :         return 0;
     500                 :            : }
     501                 :            : 
     502                 :            : static int
     503                 :          1 : get_fdp_ruhu_log_page(struct spdk_nvme_ns *ns)
     504                 :            : {
     505                 :            :         uint32_t i;
     506                 :            :         struct spdk_nvme_fdp_ruhu_descriptor *ruhu_desc;
     507                 :          1 :         struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
     508                 :          1 :         const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
     509                 :            : 
     510                 :          1 :         g_outstanding_commands = 0;
     511                 :          1 :         g_fdp_command_result = -1;
     512                 :            : 
     513         [ +  - ]:          1 :         if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_RECLAIM_UNIT_HANDLE_USAGE, 0,
     514         [ -  + ]:          1 :                         g_fdp_ruhu_log_page, FDP_LOG_PAGE_SIZE, 0, 0, (nsdata->endgid << 16),
     515                 :            :                         0, cmd_completion, NULL) == 0) {
     516                 :          1 :                 g_outstanding_commands++;
     517                 :            :         } else {
     518   [ #  #  #  # ]:          0 :                 fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(RUH usage) failed\n\n");
     519                 :          0 :                 return -1;
     520                 :            :         }
     521                 :            : 
     522         [ +  + ]:          6 :         while (g_outstanding_commands) {
     523                 :          5 :                 spdk_nvme_ctrlr_process_admin_completions(ctrlr);
     524                 :            :         }
     525                 :            : 
     526         [ -  + ]:          1 :         if (g_fdp_command_result) {
     527   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Failed to get Reclaim Unit Handle usage log page\n\n");
     528                 :          0 :                 return -1;
     529                 :            :         }
     530                 :            : 
     531   [ -  +  -  + ]:          1 :         fprintf(stdout, "FDP reclaim unit handle usage log page\n");
     532   [ -  +  -  + ]:          1 :         fprintf(stdout, "======================================\n");
     533                 :            : 
     534   [ -  +  -  + ]:          1 :         fprintf(stdout, "Number of Reclaim Unit Handles:       %u\n", g_fdp_ruhu_log_page->nruh);
     535                 :            : 
     536         [ +  + ]:          9 :         for (i = 0; i < g_fdp_ruhu_log_page->nruh; i++) {
     537                 :          8 :                 ruhu_desc = &g_fdp_ruhu_log_page->ruhu_desc[i];
     538                 :            : 
     539   [ -  +  -  + ]:          8 :                 fprintf(stdout, "  RUH Usage Desc #%03d:   RUH Attributes: %s\n", i,
     540         [ +  + ]:          8 :                         ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_UNUSED ? "Unused" :
     541         [ +  - ]:          2 :                         ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_HOST_SPECIFIED ? "Host Specified" :
     542         [ +  - ]:          1 :                         ruhu_desc->ruha == SPDK_NVME_FDP_RUHA_CTRLR_SPECIFIED ? "Controller Specified" :
     543                 :            :                         "Reserved");
     544                 :            :         }
     545                 :            : 
     546         [ -  + ]:          1 :         fprintf(stdout, "\n");
     547                 :          1 :         return 0;
     548                 :            : }
     549                 :            : 
     550                 :            : static int
     551                 :          1 : get_fdp_stats_log_page(struct spdk_nvme_ns *ns)
     552                 :            : {
     553                 :          1 :         struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
     554                 :          1 :         const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
     555                 :            : 
     556                 :          1 :         g_outstanding_commands = 0;
     557                 :          1 :         g_fdp_command_result = -1;
     558                 :            : 
     559         [ +  - ]:          1 :         if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_STATISTICS, 0,
     560         [ -  + ]:          1 :                         &g_fdp_stats_log_page, 64, 0, 0, (nsdata->endgid << 16), 0,
     561                 :            :                         cmd_completion, NULL) == 0) {
     562                 :          1 :                 g_outstanding_commands++;
     563                 :            :         } else {
     564   [ #  #  #  # ]:          0 :                 fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP stats) failed\n\n");
     565                 :          0 :                 return -1;
     566                 :            :         }
     567                 :            : 
     568         [ +  + ]:          6 :         while (g_outstanding_commands) {
     569                 :          5 :                 spdk_nvme_ctrlr_process_admin_completions(ctrlr);
     570                 :            :         }
     571                 :            : 
     572         [ -  + ]:          1 :         if (g_fdp_command_result) {
     573   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Failed to get FDP statistics log page\n\n");
     574                 :          0 :                 return -1;
     575                 :            :         }
     576                 :            : 
     577   [ -  +  -  + ]:          1 :         fprintf(stdout, "FDP statistics log page\n");
     578   [ -  +  -  + ]:          1 :         fprintf(stdout, "=======================\n");
     579                 :            : 
     580   [ -  +  -  + ]:          1 :         fprintf(stdout, "Host bytes with metadata written:  ");
     581                 :          1 :         print_uint128_dec(g_fdp_stats_log_page.hbmw);
     582         [ -  + ]:          1 :         fprintf(stdout, "\n");
     583   [ -  +  -  + ]:          1 :         fprintf(stdout, "Media bytes with metadata written: ");
     584                 :          1 :         print_uint128_dec(g_fdp_stats_log_page.mbmw);
     585         [ -  + ]:          1 :         fprintf(stdout, "\n");
     586   [ -  +  -  + ]:          1 :         fprintf(stdout, "Media bytes erased:                ");
     587                 :          1 :         print_uint128_dec(g_fdp_stats_log_page.mbe);
     588   [ -  +  -  + ]:          1 :         fprintf(stdout, "\n\n");
     589                 :            : 
     590                 :          1 :         return 0;
     591                 :            : }
     592                 :            : 
     593                 :            : static int
     594                 :          1 : get_fdp_events_log_page(struct spdk_nvme_ns *ns)
     595                 :            : {
     596                 :            :         uint32_t i;
     597                 :            :         struct spdk_nvme_fdp_event *event;
     598                 :            :         struct spdk_nvme_fdp_event_media_reallocated *media_reallocated;
     599                 :          1 :         struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
     600                 :          1 :         const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
     601                 :            : 
     602                 :          1 :         g_outstanding_commands = 0;
     603                 :          1 :         g_fdp_command_result = -1;
     604                 :            : 
     605                 :            :         /* Only fetch FDP host events here */
     606         [ +  - ]:          1 :         if (spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_FDP_EVENTS, 0,
     607                 :            :                         g_fdp_events_log_page, FDP_LOG_PAGE_SIZE, 0,
     608         [ -  + ]:          1 :                         (SPDK_NVME_FDP_REPORT_HOST_EVENTS << 8), (nsdata->endgid << 16),
     609                 :            :                         0, cmd_completion, NULL) == 0) {
     610                 :          1 :                 g_outstanding_commands++;
     611                 :            :         } else {
     612   [ #  #  #  # ]:          0 :                 fprintf(stderr, "spdk_nvme_ctrlr_cmd_get_log_page_ext(FDP events) failed\n\n");
     613                 :          0 :                 return -1;
     614                 :            :         }
     615                 :            : 
     616         [ +  + ]:          6 :         while (g_outstanding_commands) {
     617                 :          5 :                 spdk_nvme_ctrlr_process_admin_completions(ctrlr);
     618                 :            :         }
     619                 :            : 
     620         [ -  + ]:          1 :         if (g_fdp_command_result) {
     621   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Failed to get eventss log page\n\n");
     622                 :          0 :                 return -1;
     623                 :            :         }
     624                 :            : 
     625   [ -  +  -  + ]:          1 :         fprintf(stdout, "FDP events log page\n");
     626   [ -  +  -  + ]:          1 :         fprintf(stdout, "===================\n");
     627   [ -  +  -  + ]:          1 :         fprintf(stdout, "Number of FDP events: %u\n", g_fdp_events_log_page->nevents);
     628                 :            : 
     629         [ +  + ]:          2 :         for (i = 0; i < g_fdp_events_log_page->nevents; i++) {
     630                 :          1 :                 event = &g_fdp_events_log_page->event[i];
     631                 :            : 
     632   [ -  +  -  + ]:          1 :                 fprintf(stdout, "FDP Event #%u:\n", i);
     633   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Event Type:                      %s\n",
     634         [ -  + ]:          1 :                         event->etype == SPDK_NVME_FDP_EVENT_RU_NOT_WRITTEN_CAPACITY ? "RU Not Written to Capacity" :
     635         [ #  # ]:          0 :                         event->etype == SPDK_NVME_FDP_EVENT_RU_TIME_LIMIT_EXCEEDED ? "RU Time Limit Exceeded" :
     636         [ #  # ]:          0 :                         event->etype == SPDK_NVME_FDP_EVENT_CTRLR_RESET_MODIFY_RUH ? "Ctrlr Reset Modified RUH's" :
     637         [ #  # ]:          0 :                         event->etype == SPDK_NVME_FDP_EVENT_INVALID_PLACEMENT_ID ? "Invalid Placement Identifier" :
     638         [ #  # ]:          0 :                         event->etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED ? "Media Reallocated" :
     639         [ #  # ]:          0 :                         event->etype == SPDK_NVME_FDP_EVENT_IMPLICIT_MODIFIED_RUH ? "Implicitly modified RUH" :
     640                 :            :                         "Reserved");
     641   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Placement Identifier:            %s\n",
     642         [ +  - ]:          1 :                         event->fdpef.bits.piv ? "Valid" : "Invalid");
     643   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  NSID:                            %s\n",
     644         [ +  - ]:          1 :                         event->fdpef.bits.nsidv ? "Valid" : "Invalid");
     645   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Location:                        %s\n",
     646         [ +  - ]:          1 :                         event->fdpef.bits.lv ? "Valid" : "Invalid");
     647         [ +  - ]:          1 :                 if (event->fdpef.bits.piv) {
     648   [ -  +  -  + ]:          1 :                         fprintf(stdout, "  Placement Identifier:            %u\n", event->pid);
     649                 :            :                 } else {
     650   [ #  #  #  # ]:          0 :                         fprintf(stdout, "  Placement Identifier:            Reserved\n");
     651                 :            :                 }
     652   [ -  +  -  + ]:          1 :                 fprintf(stdout, "  Event Timestamp:                 %" PRIx64 "\n", event->timestamp);
     653         [ +  - ]:          1 :                 if (event->fdpef.bits.nsidv) {
     654   [ -  +  -  + ]:          1 :                         fprintf(stdout, "  Namespace Identifier:            %u\n", event->nsid);
     655                 :            :                 } else {
     656   [ #  #  #  # ]:          0 :                         fprintf(stdout, "  Namespace Identifier:            Ignore\n");
     657                 :            :                 }
     658                 :            : 
     659         [ -  + ]:          1 :                 if (event->etype == SPDK_NVME_FDP_EVENT_MEDIA_REALLOCATED) {
     660                 :          0 :                         media_reallocated = (struct spdk_nvme_fdp_event_media_reallocated *)&event->event_type_specific;
     661                 :            : 
     662   [ #  #  #  # ]:          0 :                         fprintf(stdout, "  LBA:                             %s\n",
     663         [ #  # ]:          0 :                                 media_reallocated->sef.bits.lbav ? "Valid" : "Invalid");
     664   [ #  #  #  # ]:          0 :                         fprintf(stdout, "  Number of LBA's Moved:           %u\n", media_reallocated->nlbam);
     665         [ #  # ]:          0 :                         if (media_reallocated->sef.bits.lbav) {
     666   [ #  #  #  # ]:          0 :                                 fprintf(stdout, "  Logical Block Address:           %u\n", event->nsid);
     667                 :            :                         } else {
     668   [ #  #  #  # ]:          0 :                                 fprintf(stdout, "  Logical Block Address:           Ignore\n");
     669                 :            :                         }
     670                 :            :                 }
     671                 :            : 
     672         [ +  - ]:          1 :                 if (event->fdpef.bits.lv) {
     673   [ -  +  -  + ]:          1 :                         fprintf(stdout, "  Reclaim Group Identifier:        %u\n", event->rgid);
     674                 :            :                 } else {
     675   [ #  #  #  # ]:          0 :                         fprintf(stdout, "  Reclaim Group Identifier:        Ignore\n");
     676                 :            :                 }
     677         [ +  - ]:          1 :                 if (event->fdpef.bits.lv) {
     678   [ -  +  -  + ]:          1 :                         fprintf(stdout, "  Reclaim Unit Handle Identifier:  %u\n", event->ruhid);
     679                 :            :                 } else {
     680   [ #  #  #  # ]:          0 :                         fprintf(stdout, "  Reclaim Unit Handle Identifier:  Ignore\n");
     681                 :            :                 }
     682                 :            :         }
     683                 :            : 
     684         [ -  + ]:          1 :         fprintf(stdout, "\n");
     685                 :          1 :         return 0;
     686                 :            : }
     687                 :            : 
     688                 :            : static int
     689                 :          1 : fdp_tests(struct spdk_nvme_ns *ns)
     690                 :            : {
     691                 :            :         struct spdk_nvme_qpair *qpair;
     692                 :          1 :         struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
     693                 :            :         int ret, err;
     694                 :            : 
     695                 :          1 :         qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
     696         [ -  + ]:          1 :         if (!qpair) {
     697   [ #  #  #  # ]:          0 :                 fprintf(stderr, "spdk_nvme_ctrlr_alloc_io_qpair() failed\n");
     698                 :          0 :                 return -EIO;
     699                 :            :         }
     700                 :            : 
     701                 :          1 :         ret = 0;
     702                 :            : 
     703   [ -  +  -  + ]:          1 :         fprintf(stdout, "==================================\n");
     704   [ -  +  -  + ]:          1 :         fprintf(stdout, "== FDP tests for Namespace: #%02u ==\n", spdk_nvme_ns_get_id(ns));
     705   [ -  +  -  + ]:          1 :         fprintf(stdout, "==================================\n\n");
     706                 :          1 :         err = get_fdp(ns);
     707         [ -  + ]:          1 :         if (err) {
     708                 :          0 :                 spdk_nvme_ctrlr_free_io_qpair(qpair);
     709                 :          0 :                 return err;
     710                 :            :         }
     711                 :            : 
     712         [ -  + ]:          1 :         if (!fdp_res.bits.fdpe) {
     713   [ #  #  #  # ]:          0 :                 fprintf(stdout, "FDP support disabled\n");
     714                 :          0 :                 spdk_nvme_ctrlr_free_io_qpair(qpair);
     715                 :          0 :                 return 0;
     716                 :            :         }
     717                 :            : 
     718                 :          1 :         fdpci = fdp_res.bits.fdpci;
     719                 :          1 :         err = get_fdp_cfg_log_page(ns);
     720         [ -  + ]:          1 :         if (err) {
     721                 :          0 :                 spdk_nvme_ctrlr_free_io_qpair(qpair);
     722                 :          0 :                 return err;
     723                 :            :         }
     724                 :            : 
     725                 :          1 :         ret += get_fdp_ruhu_log_page(ns);
     726                 :          1 :         ret += get_fdp_stats_log_page(ns);
     727                 :            : 
     728                 :          1 :         err = reclaim_unit_handle_status(ns, qpair);
     729         [ -  + ]:          1 :         if (err) {
     730                 :          0 :                 spdk_nvme_ctrlr_free_io_qpair(qpair);
     731                 :          0 :                 return err;
     732                 :            :         }
     733                 :            : 
     734                 :          1 :         err = check_fdp_write(ns, qpair);
     735         [ -  + ]:          1 :         if (err) {
     736                 :          0 :                 spdk_nvme_ctrlr_free_io_qpair(qpair);
     737                 :          0 :                 return err;
     738                 :            :         }
     739                 :            : 
     740                 :          1 :         ret += set_fdp_events(ns);
     741                 :          1 :         ret += reclaim_unit_handle_update(ns, qpair);
     742                 :            : 
     743                 :          1 :         ret += get_fdp_events(ns);
     744                 :          1 :         ret += get_fdp_events_log_page(ns);
     745                 :            : 
     746                 :          1 :         return ret;
     747                 :            : }
     748                 :            : 
     749                 :            : static void
     750                 :          1 : register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
     751                 :            : {
     752                 :            :         struct ns_entry *entry;
     753                 :          1 :         const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
     754                 :            : 
     755                 :          1 :         entry = malloc(sizeof(struct ns_entry));
     756         [ -  + ]:          1 :         if (entry == NULL) {
     757                 :          0 :                 perror("ns_entry malloc");
     758                 :          0 :                 exit(1);
     759                 :            :         }
     760                 :            : 
     761                 :          1 :         entry->ctrlr = ctrlr;
     762                 :          1 :         entry->ns = ns;
     763                 :          1 :         entry->next = g_namespaces;
     764                 :          1 :         g_namespaces = entry;
     765                 :            : 
     766         [ -  + ]:          1 :         printf("Namespace ID: %d Endurance Group ID: %d\n", spdk_nvme_ns_get_id(ns),
     767                 :          1 :                nsdata->endgid);
     768                 :          1 : }
     769                 :            : 
     770                 :            : static bool
     771                 :          1 : probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
     772                 :            :          struct spdk_nvme_ctrlr_opts *opts)
     773                 :            : {
     774   [ -  +  -  + ]:          1 :         fprintf(stdout, "Attaching to %s\n", trid->traddr);
     775                 :            : 
     776                 :          1 :         return true;
     777                 :            : }
     778                 :            : 
     779                 :            : static void
     780                 :          1 : attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
     781                 :            :           struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
     782                 :            : {
     783                 :            :         int num_ns, nsid;
     784                 :            :         struct spdk_nvme_ns *ns;
     785                 :            :         const struct spdk_nvme_ctrlr_data *cdata;
     786                 :            : 
     787                 :          1 :         cdata = spdk_nvme_ctrlr_get_data(ctrlr);
     788                 :            : 
     789         [ +  - ]:          1 :         if (cdata->ctratt.fdps) {
     790   [ -  +  -  + ]:          1 :                 fprintf(stdout, "Controller supports FDP Attached to %s\n", trid->traddr);
     791                 :          1 :                 num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr);
     792         [ -  + ]:          1 :                 if (num_ns < 1) {
     793         [ #  # ]:          0 :                         printf("No valid namespaces in controller\n");
     794                 :            :                 } else {
     795         [ +  + ]:          2 :                         for (nsid = spdk_nvme_ctrlr_get_first_active_ns(ctrlr); nsid != 0;
     796                 :          1 :                              nsid = spdk_nvme_ctrlr_get_next_active_ns(ctrlr, nsid)) {
     797                 :          1 :                                 ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid);
     798                 :          1 :                                 register_ns(ctrlr, ns);
     799                 :            :                         }
     800                 :            :                 }
     801                 :            :         } else {
     802   [ #  #  #  # ]:          0 :                 fprintf(stdout, "Controller attached to: %s doesn't support FDP\n", trid->traddr);
     803                 :            :         }
     804                 :          1 : }
     805                 :            : 
     806                 :            : static void
     807                 :          1 : cleanup(void)
     808                 :            : {
     809                 :          1 :         struct ns_entry *ns_entry = g_namespaces;
     810                 :          1 :         struct spdk_nvme_detach_ctx *detach_ctx = NULL;
     811                 :            : 
     812         [ +  + ]:          2 :         while (ns_entry) {
     813                 :          1 :                 struct ns_entry *next = ns_entry->next;
     814                 :            : 
     815                 :          1 :                 spdk_nvme_detach_async(ns_entry->ctrlr, &detach_ctx);
     816                 :            : 
     817                 :          1 :                 free(ns_entry);
     818                 :          1 :                 ns_entry = next;
     819                 :            :         }
     820                 :            : 
     821         [ +  - ]:          1 :         if (detach_ctx) {
     822                 :          1 :                 spdk_nvme_detach_poll(detach_ctx);
     823                 :            :         }
     824                 :          1 : }
     825                 :            : 
     826                 :            : static void
     827                 :          0 : usage(const char *program_name)
     828                 :            : {
     829         [ #  # ]:          0 :         printf("%s [options]", program_name);
     830                 :          0 :         printf("\n");
     831         [ #  # ]:          0 :         printf("options:\n");
     832         [ #  # ]:          0 :         printf(" -r trid    remote NVMe over Fabrics target address\n");
     833         [ #  # ]:          0 :         printf("    Format: 'key:value [key:value] ...'\n");
     834         [ #  # ]:          0 :         printf("    Keys:\n");
     835         [ #  # ]:          0 :         printf("     trtype      Transport type (e.g. RDMA)\n");
     836         [ #  # ]:          0 :         printf("     adrfam      Address family (e.g. IPv4, IPv6)\n");
     837         [ #  # ]:          0 :         printf("     traddr      Transport address (e.g. 192.168.100.8)\n");
     838         [ #  # ]:          0 :         printf("     trsvcid     Transport service identifier (e.g. 4420)\n");
     839         [ #  # ]:          0 :         printf("     subnqn      Subsystem NQN (default: %s)\n", SPDK_NVMF_DISCOVERY_NQN);
     840         [ #  # ]:          0 :         printf("    Example: -r 'trtype:RDMA adrfam:IPv4 traddr:192.168.100.8 trsvcid:4420'\n");
     841         [ #  # ]:          0 :         printf(" -h         show this usage\n");
     842                 :          0 : }
     843                 :            : 
     844                 :            : static int
     845                 :          1 : parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
     846                 :            : {
     847                 :            :         int op;
     848                 :            : 
     849                 :          1 :         spdk_nvme_trid_populate_transport(&g_trid, SPDK_NVME_TRANSPORT_PCIE);
     850         [ -  + ]:          1 :         snprintf(g_trid.subnqn, sizeof(g_trid.subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
     851                 :            : 
     852   [ -  +  -  +  :          2 :         while ((op = getopt(argc, argv, "r:h")) != -1) {
                   +  + ]
     853      [ +  -  - ]:          1 :                 switch (op) {
     854                 :          1 :                 case 'r':
     855         [ -  + ]:          1 :                         if (spdk_nvme_transport_id_parse(&g_trid, optarg) != 0) {
     856   [ #  #  #  # ]:          0 :                                 fprintf(stderr, "Error parsing transport address\n");
     857                 :          0 :                                 return 1;
     858                 :            :                         }
     859                 :            : 
     860                 :          1 :                         g_use_trid = true;
     861                 :          1 :                         break;
     862                 :          0 :                 case 'h':
     863                 :          0 :                         usage(argv[0]);
     864                 :          0 :                         exit(EXIT_SUCCESS);
     865                 :          0 :                 default:
     866                 :          0 :                         usage(argv[0]);
     867                 :          0 :                         return 1;
     868                 :            :                 }
     869                 :            :         }
     870                 :            : 
     871                 :          1 :         return 0;
     872                 :            : }
     873                 :            : 
     874                 :            : int
     875                 :          1 : main(int argc, char **argv)
     876                 :            : {
     877                 :            :         int                     rc;
     878                 :          1 :         struct spdk_env_opts    opts;
     879                 :            :         struct ns_entry *ns_entry;
     880                 :            : 
     881                 :          1 :         spdk_env_opts_init(&opts);
     882                 :          1 :         rc = parse_args(argc, argv, &opts);
     883         [ -  + ]:          1 :         if (rc != 0) {
     884                 :          0 :                 return rc;
     885                 :            :         }
     886                 :            : 
     887                 :          1 :         opts.name = "fdp";
     888                 :          1 :         opts.core_mask = "0x1";
     889                 :          1 :         opts.shm_id = 0;
     890         [ -  + ]:          1 :         if (spdk_env_init(&opts) < 0) {
     891   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Unable to initialize SPDK env\n");
     892                 :          0 :                 return 1;
     893                 :            :         }
     894                 :            : 
     895         [ -  + ]:          1 :         printf("Initializing NVMe Controllers\n");
     896                 :            : 
     897   [ -  +  +  - ]:          1 :         rc = spdk_nvme_probe(g_use_trid ? &g_trid : NULL, NULL, probe_cb, attach_cb, NULL);
     898         [ -  + ]:          1 :         if (rc != 0) {
     899   [ #  #  #  # ]:          0 :                 fprintf(stderr, "spdk_nvme_probe() failed\n");
     900                 :          0 :                 return 1;
     901                 :            :         }
     902                 :            : 
     903         [ -  + ]:          1 :         if (g_namespaces == NULL) {
     904   [ #  #  #  # ]:          0 :                 fprintf(stderr, "no NVMe controllers found\n");
     905                 :          0 :                 return 1;
     906                 :            :         }
     907                 :            : 
     908         [ -  + ]:          1 :         printf("Initialization complete.\n\n");
     909                 :            : 
     910                 :          1 :         ns_entry = g_namespaces;
     911         [ +  + ]:          2 :         while (ns_entry != NULL) {
     912                 :          1 :                 rc = fdp_tests(ns_entry->ns);
     913         [ -  + ]:          1 :                 if (rc) {
     914                 :          0 :                         break;
     915                 :            :                 }
     916                 :          1 :                 ns_entry = ns_entry->next;
     917                 :            :         }
     918                 :            : 
     919   [ -  +  -  + ]:          1 :         printf("FDP test %s\n", rc ? "failed" : "passed");
     920                 :          1 :         cleanup();
     921                 :            : 
     922                 :          1 :         return 0;
     923                 :            : }

Generated by: LCOV version 1.14