LCOV - code coverage report
Current view: top level - spdk/test/nvme/startup - startup.c (source / functions) Hit Total Coverage
Test: Combined Lines: 48 80 60.0 %
Date: 2024-07-15 18:10:46 Functions: 4 6 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 24 72 33.3 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2019 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : 
       8                 :            : #include "spdk/nvme.h"
       9                 :            : #include "spdk/env.h"
      10                 :            : #include "spdk/string.h"
      11                 :            : 
      12                 :            : struct ctrlr_entry {
      13                 :            :         struct spdk_nvme_ctrlr          *ctrlr;
      14                 :            :         TAILQ_ENTRY(ctrlr_entry)        link;
      15                 :            :         char                            name[1024];
      16                 :            : };
      17                 :            : 
      18                 :            : struct ns_entry {
      19                 :            :         struct spdk_nvme_ctrlr  *ctrlr;
      20                 :            :         struct spdk_nvme_ns     *ns;
      21                 :            :         TAILQ_ENTRY(ns_entry)   link;
      22                 :            :         struct spdk_nvme_qpair  *qpair;
      23                 :            : };
      24                 :            : 
      25                 :            : static TAILQ_HEAD(, ctrlr_entry) g_controllers = TAILQ_HEAD_INITIALIZER(g_controllers);
      26                 :            : static TAILQ_HEAD(, ns_entry) g_namespaces = TAILQ_HEAD_INITIALIZER(g_namespaces);
      27                 :            : static int g_startup_time = 0;
      28                 :            : 
      29                 :            : static bool
      30                 :          0 : probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
      31                 :            :          struct spdk_nvme_ctrlr_opts *opts)
      32                 :            : {
      33         [ #  # ]:          0 :         printf("Attaching to %s\n", trid->traddr);
      34                 :            : 
      35                 :          0 :         return true;
      36                 :            : }
      37                 :            : 
      38                 :            : static void
      39                 :         10 : attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
      40                 :            :           struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
      41                 :            : {
      42                 :            : 
      43                 :            :         struct ctrlr_entry *entry;
      44                 :            :         const struct spdk_nvme_ctrlr_data *cdata;
      45                 :            : 
      46                 :         10 :         entry = malloc(sizeof(struct ctrlr_entry));
      47         [ -  + ]:         10 :         if (entry == NULL) {
      48                 :          0 :                 perror("ctrlr_entry malloc");
      49                 :          0 :                 exit(1);
      50                 :            :         }
      51                 :            : 
      52         [ -  + ]:         10 :         printf("Attached to %s\n", trid->traddr);
      53                 :            : 
      54                 :            :         /*
      55                 :            :          * spdk_nvme_ctrlr is the logical abstraction in SPDK for an NVMe
      56                 :            :          *  controller.  During initialization, the IDENTIFY data for the
      57                 :            :          *  controller is read using an NVMe admin command, and that data
      58                 :            :          *  can be retrieved using spdk_nvme_ctrlr_get_data() to get
      59                 :            :          *  detailed information on the controller.  Refer to the NVMe
      60                 :            :          *  specification for more details on IDENTIFY for NVMe controllers.
      61                 :            :          */
      62                 :         10 :         cdata = spdk_nvme_ctrlr_get_data(ctrlr);
      63                 :            : 
      64         [ -  + ]:         10 :         snprintf(entry->name, sizeof(entry->name), "%-20.20s (%-20.20s)", cdata->mn, cdata->sn);
      65                 :            : 
      66                 :         10 :         entry->ctrlr = ctrlr;
      67                 :         10 :         TAILQ_INSERT_TAIL(&g_controllers, entry, link);
      68                 :         10 : }
      69                 :            : 
      70                 :            : static void
      71                 :          6 : cleanup(void)
      72                 :            : {
      73                 :            :         struct ns_entry *ns_entry, *tmp_ns_entry;
      74                 :            :         struct ctrlr_entry *ctrlr_entry, *tmp_ctrlr_entry;
      75                 :          6 :         struct spdk_nvme_detach_ctx *detach_ctx = NULL;
      76                 :            : 
      77         [ -  + ]:          6 :         TAILQ_FOREACH_SAFE(ns_entry, &g_namespaces, link, tmp_ns_entry) {
      78         [ #  # ]:          0 :                 TAILQ_REMOVE(&g_namespaces, ns_entry, link);
      79                 :          0 :                 free(ns_entry);
      80                 :            :         }
      81                 :            : 
      82         [ +  + ]:         16 :         TAILQ_FOREACH_SAFE(ctrlr_entry, &g_controllers, link, tmp_ctrlr_entry) {
      83         [ +  + ]:         10 :                 TAILQ_REMOVE(&g_controllers, ctrlr_entry, link);
      84                 :         10 :                 spdk_nvme_detach_async(ctrlr_entry->ctrlr, &detach_ctx);
      85                 :         10 :                 free(ctrlr_entry);
      86                 :            :         }
      87                 :            : 
      88         [ -  + ]:          6 :         if (detach_ctx) {
      89                 :          0 :                 spdk_nvme_detach_poll(detach_ctx);
      90                 :            :         }
      91                 :          6 : }
      92                 :            : 
      93                 :            : static void
      94                 :          0 : usage(const char *program_name)
      95                 :            : {
      96         [ #  # ]:          0 :         printf("%s [options]", program_name);
      97                 :          0 :         printf("\n");
      98         [ #  # ]:          0 :         printf("options:\n");
      99         [ #  # ]:          0 :         printf(" -t         The maximum time needed for startup. The unit is us. The value should be bigger than 0.\n");
     100                 :          0 : }
     101                 :            : 
     102                 :            : static int
     103                 :          6 : parse_args(int argc, char **argv)
     104                 :            : {
     105                 :            :         int op;
     106                 :            : 
     107   [ -  +  -  +  :         12 :         while ((op = getopt(argc, argv, "t:")) != -1) {
                   +  + ]
     108         [ +  - ]:          6 :                 switch (op) {
     109                 :          6 :                 case 't':
     110                 :          6 :                         g_startup_time = spdk_strtol(optarg, 10);
     111         [ -  + ]:          6 :                         if (g_startup_time < 0) {
     112   [ #  #  #  # ]:          0 :                                 fprintf(stderr, "Invalid nvme startup time\n");
     113                 :          0 :                                 return g_startup_time;
     114                 :            :                         }
     115                 :          6 :                         break;
     116                 :          0 :                 default:
     117                 :          0 :                         usage(argv[0]);
     118                 :          0 :                         return 1;
     119                 :            :                 }
     120                 :            :         }
     121                 :            : 
     122                 :          6 :         return 0;
     123                 :            : }
     124                 :            : 
     125                 :            : int
     126                 :          6 : main(int argc, char **argv)
     127                 :            : {
     128                 :            :         int rc;
     129                 :          6 :         struct spdk_env_opts opts;
     130                 :            :         uint64_t start_tsc, end_tsc, tsc_diff;
     131                 :            :         float  time_used_in_usec;
     132                 :            : 
     133                 :          6 :         rc = parse_args(argc, argv);
     134         [ -  + ]:          6 :         if (rc != 0) {
     135                 :          0 :                 return rc;
     136                 :            :         }
     137                 :            : 
     138         [ -  + ]:          6 :         if (g_startup_time == 0) {
     139                 :          0 :                 usage(argv[0]);
     140                 :          0 :                 return 1;
     141                 :            :         }
     142                 :            : 
     143                 :          6 :         start_tsc = spdk_get_ticks();
     144                 :            :         /*
     145                 :            :          * SPDK relies on an abstraction around the local environment
     146                 :            :          * named env that handles memory allocation and PCI device operations.
     147                 :            :          * This library must be initialized first.
     148                 :            :          *
     149                 :            :          */
     150                 :          6 :         spdk_env_opts_init(&opts);
     151                 :          6 :         opts.name = "startup";
     152                 :          6 :         opts.shm_id = 0;
     153         [ -  + ]:          6 :         if (spdk_env_init(&opts) < 0) {
     154   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Unable to initialize SPDK env\n");
     155                 :          0 :                 return 1;
     156                 :            :         }
     157                 :            : 
     158         [ -  + ]:          6 :         printf("Initializing NVMe Controllers\n");
     159                 :            : 
     160                 :            : 
     161                 :            :         /*
     162                 :            :          * Start the SPDK NVMe enumeration process.  probe_cb will be called
     163                 :            :          *  for each NVMe controller found, giving our application a choice on
     164                 :            :          *  whether to attach to each controller.  attach_cb will then be
     165                 :            :          *  called for each controller after the SPDK NVMe driver has completed
     166                 :            :          *  initializing the controller we chose to attach.
     167                 :            :          */
     168                 :          6 :         rc = spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL);
     169         [ -  + ]:          6 :         if (rc != 0) {
     170   [ #  #  #  # ]:          0 :                 fprintf(stderr, "spdk_nvme_probe() failed\n");
     171                 :          0 :                 cleanup();
     172                 :          0 :                 return 1;
     173                 :            :         }
     174                 :            : 
     175         [ -  + ]:          6 :         if (TAILQ_EMPTY(&g_controllers)) {
     176   [ #  #  #  # ]:          0 :                 fprintf(stderr, "no NVMe controllers found\n");
     177                 :          0 :                 return 0;
     178                 :            :         }
     179                 :            : 
     180                 :          6 :         end_tsc = spdk_get_ticks();
     181                 :          6 :         tsc_diff = end_tsc - start_tsc;
     182                 :          6 :         time_used_in_usec = ((float)tsc_diff) * 1000 * 1000 / spdk_get_ticks_hz();
     183         [ -  + ]:          6 :         printf("Initialization complete.\n");
     184         [ -  + ]:          6 :         printf("Time used:%-16.3f(us).\n", time_used_in_usec);
     185         [ -  + ]:          6 :         if (time_used_in_usec > g_startup_time) {
     186   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Too long time for initialization.\n");
     187                 :          0 :                 cleanup();
     188                 :          0 :                 return 1;
     189                 :            :         }
     190                 :          6 :         cleanup();
     191                 :          6 :         return 0;
     192                 :            : }

Generated by: LCOV version 1.14