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

Generated by: LCOV version 1.14