LCOV - code coverage report
Current view: top level - spdk/test/nvme/reserve - reserve.c (source / functions) Hit Total Coverage
Test: Combined Lines: 33 211 15.6 %
Date: 2024-07-12 13:06:24 Functions: 3 12 25.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 16 200 8.0 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2016 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : 
       8                 :            : #include "spdk/endian.h"
       9                 :            : #include "spdk/nvme.h"
      10                 :            : #include "spdk/env.h"
      11                 :            : #include "spdk/log.h"
      12                 :            : 
      13                 :            : #define MAX_DEVS 64
      14                 :            : 
      15                 :            : struct dev {
      16                 :            :         struct spdk_pci_addr                    pci_addr;
      17                 :            :         struct spdk_nvme_ctrlr                  *ctrlr;
      18                 :            :         char                                    name[100];
      19                 :            : };
      20                 :            : 
      21                 :            : static struct dev g_devs[MAX_DEVS];
      22                 :            : static int g_num_devs = 0;
      23                 :            : 
      24                 :            : #define foreach_dev(iter) \
      25                 :            :         for (iter = g_devs; iter - g_devs < g_num_devs; iter++)
      26                 :            : 
      27                 :            : static int g_outstanding_commands;
      28                 :            : static int g_reserve_command_result;
      29                 :            : static bool g_feat_host_id_successful;
      30                 :            : 
      31                 :            : #define HOST_ID         0xABABABABCDCDCDCD
      32                 :            : #define EXT_HOST_ID     ((uint8_t[]){0x0f, 0x97, 0xcd, 0x74, 0x8c, 0x80, 0x41, 0x42, \
      33                 :            :                                      0x99, 0x0f, 0x65, 0xc4, 0xf0, 0x39, 0x24, 0x20})
      34                 :            : 
      35                 :            : #define CR_KEY          0xDEADBEAF5A5A5A5B
      36                 :            : 
      37                 :            : static void
      38                 :          0 : feat_host_id_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
      39                 :            : {
      40   [ #  #  #  # ]:          0 :         if (spdk_nvme_cpl_is_error(cpl)) {
      41   [ #  #  #  # ]:          0 :                 fprintf(stdout, "Get/Set Features - Host Identifier failed\n");
      42                 :          0 :                 g_feat_host_id_successful = false;
      43                 :            :         } else {
      44                 :          0 :                 g_feat_host_id_successful = true;
      45                 :            :         }
      46                 :          0 :         g_outstanding_commands--;
      47                 :          0 : }
      48                 :            : 
      49                 :            : static int
      50                 :          0 : get_host_identifier(struct spdk_nvme_ctrlr *ctrlr)
      51                 :            : {
      52                 :            :         int ret;
      53                 :          0 :         uint8_t host_id[16];
      54                 :            :         uint32_t host_id_size;
      55                 :            :         uint32_t cdw11;
      56                 :            : 
      57         [ #  # ]:          0 :         if (spdk_nvme_ctrlr_get_data(ctrlr)->ctratt.host_id_exhid_supported) {
      58                 :          0 :                 host_id_size = 16;
      59                 :          0 :                 cdw11 = 1;
      60         [ #  # ]:          0 :                 printf("Using 128-bit extended host identifier\n");
      61                 :            :         } else {
      62                 :          0 :                 host_id_size = 8;
      63                 :          0 :                 cdw11 = 0;
      64         [ #  # ]:          0 :                 printf("Using 64-bit host identifier\n");
      65                 :            :         }
      66                 :            : 
      67                 :          0 :         g_outstanding_commands = 0;
      68                 :          0 :         ret = spdk_nvme_ctrlr_cmd_get_feature(ctrlr, SPDK_NVME_FEAT_HOST_IDENTIFIER, cdw11, host_id,
      69                 :            :                                               host_id_size,
      70                 :            :                                               feat_host_id_completion, NULL);
      71         [ #  # ]:          0 :         if (ret) {
      72   [ #  #  #  # ]:          0 :                 fprintf(stdout, "Get Feature: Failed\n");
      73                 :          0 :                 return -1;
      74                 :            :         }
      75                 :            : 
      76                 :          0 :         g_outstanding_commands++;
      77                 :          0 :         g_feat_host_id_successful = false;
      78                 :            : 
      79         [ #  # ]:          0 :         while (g_outstanding_commands) {
      80                 :          0 :                 spdk_nvme_ctrlr_process_admin_completions(ctrlr);
      81                 :            :         }
      82                 :            : 
      83   [ #  #  #  # ]:          0 :         if (g_feat_host_id_successful) {
      84                 :          0 :                 spdk_log_dump(stdout, "Get Feature: Host Identifier:", host_id, host_id_size);
      85                 :          0 :                 return 0;
      86                 :            :         }
      87                 :            : 
      88                 :          0 :         return -1;
      89                 :            : }
      90                 :            : 
      91                 :            : static int
      92                 :          0 : set_host_identifier(struct spdk_nvme_ctrlr *ctrlr)
      93                 :            : {
      94                 :            :         int ret;
      95                 :          0 :         uint8_t host_id[16] = {};
      96                 :            :         uint32_t host_id_size;
      97                 :            :         uint32_t cdw11;
      98                 :            : 
      99         [ #  # ]:          0 :         if (spdk_nvme_ctrlr_get_data(ctrlr)->ctratt.host_id_exhid_supported) {
     100                 :          0 :                 host_id_size = 16;
     101                 :          0 :                 cdw11 = 1;
     102         [ #  # ]:          0 :                 printf("Using 128-bit extended host identifier\n");
     103   [ #  #  #  # ]:          0 :                 memcpy(host_id, EXT_HOST_ID, host_id_size);
     104                 :            :         } else {
     105                 :          0 :                 host_id_size = 8;
     106                 :          0 :                 cdw11 = 0;
     107                 :          0 :                 to_be64(host_id, HOST_ID);
     108         [ #  # ]:          0 :                 printf("Using 64-bit host identifier\n");
     109                 :            :         }
     110                 :            : 
     111                 :          0 :         g_outstanding_commands = 0;
     112                 :          0 :         ret = spdk_nvme_ctrlr_cmd_set_feature(ctrlr, SPDK_NVME_FEAT_HOST_IDENTIFIER, cdw11, 0, host_id,
     113                 :            :                                               host_id_size, feat_host_id_completion, NULL);
     114         [ #  # ]:          0 :         if (ret) {
     115   [ #  #  #  # ]:          0 :                 fprintf(stdout, "Set Feature: Failed\n");
     116                 :          0 :                 return -1;
     117                 :            :         }
     118                 :            : 
     119                 :          0 :         g_outstanding_commands++;
     120                 :          0 :         g_feat_host_id_successful = false;
     121                 :            : 
     122         [ #  # ]:          0 :         while (g_outstanding_commands) {
     123                 :          0 :                 spdk_nvme_ctrlr_process_admin_completions(ctrlr);
     124                 :            :         }
     125                 :            : 
     126   [ #  #  #  # ]:          0 :         if (g_feat_host_id_successful) {
     127                 :          0 :                 spdk_log_dump(stdout, "Set Feature: Host Identifier:", host_id, host_id_size);
     128                 :          0 :                 return 0;
     129                 :            :         }
     130                 :            : 
     131   [ #  #  #  # ]:          0 :         fprintf(stderr, "Set Feature: Host Identifier Failed\n");
     132                 :          0 :         return -1;
     133                 :            : }
     134                 :            : 
     135                 :            : static void
     136                 :          0 : reservation_ns_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
     137                 :            : {
     138   [ #  #  #  # ]:          0 :         if (spdk_nvme_cpl_is_error(cpl)) {
     139                 :          0 :                 g_reserve_command_result = -1;
     140                 :            :         } else {
     141                 :          0 :                 g_reserve_command_result = 0;
     142                 :            :         }
     143                 :            : 
     144                 :          0 :         g_outstanding_commands--;
     145                 :          0 : }
     146                 :            : 
     147                 :            : static int
     148                 :          0 : reservation_ns_register(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair,
     149                 :            :                         uint32_t ns_id, bool reg)
     150                 :            : {
     151                 :            :         int ret;
     152                 :          0 :         struct spdk_nvme_reservation_register_data rr_data;
     153                 :            :         enum spdk_nvme_reservation_register_action action;
     154                 :            :         struct spdk_nvme_ns *ns;
     155                 :            : 
     156                 :          0 :         ns = spdk_nvme_ctrlr_get_ns(ctrlr, ns_id);
     157                 :            : 
     158         [ #  # ]:          0 :         if (reg) {
     159                 :          0 :                 rr_data.crkey = 0;
     160                 :          0 :                 rr_data.nrkey = CR_KEY;
     161                 :          0 :                 action = SPDK_NVME_RESERVE_REGISTER_KEY;
     162                 :            :         } else {
     163                 :          0 :                 rr_data.crkey = CR_KEY;
     164                 :          0 :                 rr_data.nrkey = 0;
     165                 :          0 :                 action = SPDK_NVME_RESERVE_UNREGISTER_KEY;
     166                 :            :         }
     167                 :            : 
     168                 :          0 :         g_outstanding_commands = 0;
     169                 :          0 :         g_reserve_command_result = -1;
     170                 :            : 
     171                 :          0 :         ret = spdk_nvme_ns_cmd_reservation_register(ns, qpair, &rr_data, true,
     172                 :            :                         action,
     173                 :            :                         SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON,
     174                 :            :                         reservation_ns_completion, NULL);
     175         [ #  # ]:          0 :         if (ret) {
     176   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Reservation Register Failed\n");
     177                 :          0 :                 return -1;
     178                 :            :         }
     179                 :            : 
     180                 :          0 :         g_outstanding_commands++;
     181         [ #  # ]:          0 :         while (g_outstanding_commands) {
     182                 :          0 :                 spdk_nvme_qpair_process_completions(qpair, 100);
     183                 :            :         }
     184                 :            : 
     185         [ #  # ]:          0 :         if (g_reserve_command_result) {
     186   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Reservation Register Failed\n");
     187                 :          0 :                 return -1;
     188                 :            :         }
     189                 :            : 
     190                 :          0 :         return 0;
     191                 :            : }
     192                 :            : 
     193                 :            : static int
     194                 :          0 : reservation_ns_report(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair, uint32_t ns_id)
     195                 :            : {
     196                 :            :         int ret, i;
     197                 :            :         uint8_t *payload;
     198                 :            :         struct spdk_nvme_reservation_status_data *status;
     199                 :            :         struct spdk_nvme_registered_ctrlr_data *cdata;
     200                 :            :         struct spdk_nvme_ns *ns;
     201                 :            : 
     202                 :          0 :         ns = spdk_nvme_ctrlr_get_ns(ctrlr, ns_id);
     203                 :            : 
     204                 :          0 :         g_outstanding_commands = 0;
     205                 :          0 :         g_reserve_command_result = -1;
     206                 :            : 
     207                 :          0 :         payload = spdk_dma_zmalloc(0x1000, 0x1000, NULL);
     208         [ #  # ]:          0 :         if (!payload) {
     209   [ #  #  #  # ]:          0 :                 fprintf(stderr, "DMA Buffer Allocation Failed\n");
     210                 :          0 :                 return -1;
     211                 :            :         }
     212                 :            : 
     213                 :          0 :         ret = spdk_nvme_ns_cmd_reservation_report(ns, qpair, payload, 0x1000,
     214                 :            :                         reservation_ns_completion, NULL);
     215         [ #  # ]:          0 :         if (ret) {
     216   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Reservation Report Failed\n");
     217                 :          0 :                 spdk_dma_free(payload);
     218                 :          0 :                 return -1;
     219                 :            :         }
     220                 :            : 
     221                 :          0 :         g_outstanding_commands++;
     222         [ #  # ]:          0 :         while (g_outstanding_commands) {
     223                 :          0 :                 spdk_nvme_qpair_process_completions(qpair, 100);
     224                 :            :         }
     225                 :            : 
     226         [ #  # ]:          0 :         if (g_reserve_command_result) {
     227   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Reservation Report Failed\n");
     228                 :          0 :                 spdk_dma_free(payload);
     229                 :          0 :                 return -1;
     230                 :            :         }
     231                 :            : 
     232                 :          0 :         status = (struct spdk_nvme_reservation_status_data *)payload;
     233   [ #  #  #  # ]:          0 :         fprintf(stdout, "Reservation Generation Counter                  %u\n", status->gen);
     234   [ #  #  #  # ]:          0 :         fprintf(stdout, "Reservation type                                %u\n", status->rtype);
     235   [ #  #  #  # ]:          0 :         fprintf(stdout, "Reservation Number of Registered Controllers    %u\n", status->regctl);
     236   [ #  #  #  # ]:          0 :         fprintf(stdout, "Reservation Persist Through Power Loss State    %u\n", status->ptpls);
     237         [ #  # ]:          0 :         for (i = 0; i < status->regctl; i++) {
     238                 :          0 :                 cdata = (struct spdk_nvme_registered_ctrlr_data *)(payload +
     239                 :          0 :                                 sizeof(struct spdk_nvme_reservation_status_data) +
     240                 :            :                                 sizeof(struct spdk_nvme_registered_ctrlr_data) * i);
     241   [ #  #  #  # ]:          0 :                 fprintf(stdout, "Controller ID                           %u\n", cdata->cntlid);
     242   [ #  #  #  # ]:          0 :                 fprintf(stdout, "Controller Reservation Status           %u\n", cdata->rcsts.status);
     243   [ #  #  #  # ]:          0 :                 fprintf(stdout, "Controller Host ID                      0x%"PRIx64"\n", cdata->hostid);
     244   [ #  #  #  # ]:          0 :                 fprintf(stdout, "Controller Reservation Key              0x%"PRIx64"\n", cdata->rkey);
     245                 :            :         }
     246                 :            : 
     247                 :          0 :         spdk_dma_free(payload);
     248                 :          0 :         return 0;
     249                 :            : }
     250                 :            : 
     251                 :            : static int
     252                 :          0 : reservation_ns_acquire(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair, uint32_t ns_id)
     253                 :            : {
     254                 :            :         int ret;
     255                 :          0 :         struct spdk_nvme_reservation_acquire_data cdata;
     256                 :            :         struct spdk_nvme_ns *ns;
     257                 :            : 
     258                 :          0 :         ns = spdk_nvme_ctrlr_get_ns(ctrlr, ns_id);
     259                 :          0 :         cdata.crkey = CR_KEY;
     260                 :          0 :         cdata.prkey = 0;
     261                 :            : 
     262                 :          0 :         g_outstanding_commands = 0;
     263                 :          0 :         g_reserve_command_result = -1;
     264                 :            : 
     265                 :          0 :         ret = spdk_nvme_ns_cmd_reservation_acquire(ns, qpair, &cdata,
     266                 :            :                         false,
     267                 :            :                         SPDK_NVME_RESERVE_ACQUIRE,
     268                 :            :                         SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
     269                 :            :                         reservation_ns_completion, NULL);
     270         [ #  # ]:          0 :         if (ret) {
     271   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Reservation Acquire Failed\n");
     272                 :          0 :                 return -1;
     273                 :            :         }
     274                 :            : 
     275                 :          0 :         g_outstanding_commands++;
     276         [ #  # ]:          0 :         while (g_outstanding_commands) {
     277                 :          0 :                 spdk_nvme_qpair_process_completions(qpair, 100);
     278                 :            :         }
     279                 :            : 
     280         [ #  # ]:          0 :         if (g_reserve_command_result) {
     281   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Reservation Acquire Failed\n");
     282                 :          0 :                 return -1;
     283                 :            :         }
     284                 :            : 
     285                 :          0 :         return 0;
     286                 :            : }
     287                 :            : 
     288                 :            : static int
     289                 :          0 : reservation_ns_release(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair, uint32_t ns_id)
     290                 :            : {
     291                 :            :         int ret;
     292                 :          0 :         struct spdk_nvme_reservation_key_data cdata;
     293                 :            :         struct spdk_nvme_ns *ns;
     294                 :            : 
     295                 :          0 :         ns = spdk_nvme_ctrlr_get_ns(ctrlr, ns_id);
     296                 :          0 :         cdata.crkey = CR_KEY;
     297                 :            : 
     298                 :          0 :         g_outstanding_commands = 0;
     299                 :          0 :         g_reserve_command_result = -1;
     300                 :            : 
     301                 :          0 :         ret = spdk_nvme_ns_cmd_reservation_release(ns, qpair, &cdata,
     302                 :            :                         false,
     303                 :            :                         SPDK_NVME_RESERVE_RELEASE,
     304                 :            :                         SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
     305                 :            :                         reservation_ns_completion, NULL);
     306         [ #  # ]:          0 :         if (ret) {
     307   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Reservation Release Failed\n");
     308                 :          0 :                 return -1;
     309                 :            :         }
     310                 :            : 
     311                 :          0 :         g_outstanding_commands++;
     312         [ #  # ]:          0 :         while (g_outstanding_commands) {
     313                 :          0 :                 spdk_nvme_qpair_process_completions(qpair, 100);
     314                 :            :         }
     315                 :            : 
     316         [ #  # ]:          0 :         if (g_reserve_command_result) {
     317   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Reservation Release Failed\n");
     318                 :          0 :                 return -1;
     319                 :            :         }
     320                 :            : 
     321                 :          0 :         return 0;
     322                 :            : }
     323                 :            : 
     324                 :            : static int
     325                 :         10 : reserve_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_pci_addr *pci_addr)
     326                 :            : {
     327                 :            :         const struct spdk_nvme_ctrlr_data       *cdata;
     328                 :            :         struct spdk_nvme_qpair                  *qpair;
     329                 :            :         int ret;
     330                 :            : 
     331                 :         10 :         cdata = spdk_nvme_ctrlr_get_data(ctrlr);
     332                 :            : 
     333         [ -  + ]:         10 :         printf("=====================================================\n");
     334                 :         10 :         printf("NVMe Controller at PCI bus %d, device %d, function %d\n",
     335         [ -  + ]:         10 :                pci_addr->bus, pci_addr->dev, pci_addr->func);
     336         [ -  + ]:         10 :         printf("=====================================================\n");
     337                 :            : 
     338         [ -  + ]:         10 :         printf("Reservations:                %s\n",
     339         [ -  + ]:         10 :                cdata->oncs.reservations ? "Supported" : "Not Supported");
     340                 :            : 
     341         [ +  - ]:         10 :         if (!cdata->oncs.reservations) {
     342                 :         10 :                 return 0;
     343                 :            :         }
     344                 :            : 
     345                 :          0 :         qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
     346         [ #  # ]:          0 :         if (!qpair) {
     347   [ #  #  #  # ]:          0 :                 fprintf(stderr, "spdk_nvme_ctrlr_alloc_io_qpair() failed\n");
     348                 :          0 :                 return -EIO;
     349                 :            :         }
     350                 :            : 
     351                 :          0 :         ret = set_host_identifier(ctrlr);
     352         [ #  # ]:          0 :         if (ret) {
     353                 :          0 :                 goto out;
     354                 :            :         }
     355                 :            : 
     356                 :          0 :         ret = get_host_identifier(ctrlr);
     357         [ #  # ]:          0 :         if (ret) {
     358                 :          0 :                 goto out;
     359                 :            :         }
     360                 :            : 
     361                 :            :         /* tested 1 namespace */
     362                 :          0 :         ret += reservation_ns_register(ctrlr, qpair, 1, 1);
     363                 :          0 :         ret += reservation_ns_acquire(ctrlr, qpair, 1);
     364                 :          0 :         ret += reservation_ns_release(ctrlr, qpair, 1);
     365                 :          0 :         ret += reservation_ns_register(ctrlr, qpair, 1, 0);
     366                 :          0 :         ret += reservation_ns_report(ctrlr, qpair, 1);
     367                 :            : 
     368                 :          0 : out:
     369                 :          0 :         spdk_nvme_ctrlr_free_io_qpair(qpair);
     370                 :          0 :         return ret;
     371                 :            : }
     372                 :            : 
     373                 :            : static bool
     374                 :          0 : probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
     375                 :            :          struct spdk_nvme_ctrlr_opts *opts)
     376                 :            : {
     377                 :          0 :         return true;
     378                 :            : }
     379                 :            : 
     380                 :            : static void
     381                 :         10 : attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
     382                 :            :           struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
     383                 :            : {
     384                 :            :         struct dev *dev;
     385                 :            : 
     386                 :            :         /* add to dev list */
     387                 :         10 :         dev = &g_devs[g_num_devs++];
     388                 :         10 :         spdk_pci_addr_parse(&dev->pci_addr, trid->traddr);
     389                 :         10 :         dev->ctrlr = ctrlr;
     390                 :         10 : }
     391                 :            : 
     392                 :            : int
     393                 :          6 : main(int argc, char **argv)
     394                 :            : {
     395                 :            :         struct dev              *iter;
     396                 :          3 :         struct spdk_env_opts    opts;
     397                 :          6 :         int                     ret = 0;
     398                 :          6 :         struct spdk_nvme_detach_ctx *detach_ctx = NULL;
     399                 :            : 
     400                 :          6 :         spdk_env_opts_init(&opts);
     401                 :          6 :         opts.name = "reserve";
     402                 :          6 :         opts.core_mask = "0x1";
     403                 :          6 :         opts.shm_id = 0;
     404         [ -  + ]:          6 :         if (spdk_env_init(&opts) < 0) {
     405   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Unable to initialize SPDK env\n");
     406                 :          0 :                 return 1;
     407                 :            :         }
     408                 :            : 
     409         [ -  + ]:          6 :         if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) {
     410   [ #  #  #  # ]:          0 :                 fprintf(stderr, "spdk_nvme_probe() failed\n");
     411                 :          0 :                 return 1;
     412                 :            :         }
     413                 :            : 
     414         [ +  + ]:         16 :         foreach_dev(iter) {
     415                 :         10 :                 ret = reserve_controller(iter->ctrlr, &iter->pci_addr);
     416         [ -  + ]:         10 :                 if (ret) {
     417                 :          0 :                         break;
     418                 :            :                 }
     419                 :            :         }
     420                 :            : 
     421   [ -  +  -  + ]:          6 :         printf("Reservation test %s\n", ret ? "failed" : "passed");
     422                 :            : 
     423         [ +  + ]:         16 :         foreach_dev(iter) {
     424                 :         10 :                 spdk_nvme_detach_async(iter->ctrlr, &detach_ctx);
     425                 :            :         }
     426                 :            : 
     427         [ -  + ]:          6 :         if (detach_ctx) {
     428                 :          0 :                 spdk_nvme_detach_poll(detach_ctx);
     429                 :            :         }
     430                 :            : 
     431                 :          6 :         return ret;
     432                 :            : }

Generated by: LCOV version 1.14