LCOV - code coverage report
Current view: top level - spdk/lib/rpc - rpc.c (source / functions) Hit Total Coverage
Test: Combined Lines: 192 216 88.9 %
Date: 2024-08-12 07:19:58 Functions: 26 26 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 113 156 72.4 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2016 Intel Corporation. All rights reserved.
       3                 :            :  *   Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
       4                 :            :  *   Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <sys/file.h>
       8                 :            : 
       9                 :            : #include "spdk/stdinc.h"
      10                 :            : 
      11                 :            : #include "spdk/queue.h"
      12                 :            : #include "spdk/rpc.h"
      13                 :            : #include "spdk/env.h"
      14                 :            : #include "spdk/log.h"
      15                 :            : #include "spdk/string.h"
      16                 :            : #include "spdk/util.h"
      17                 :            : #include "spdk/version.h"
      18                 :            : 
      19                 :            : static uint32_t g_rpc_state = SPDK_RPC_STARTUP;
      20                 :            : static bool g_rpcs_correct = true;
      21                 :            : static char **g_rpcs_allowlist = NULL;
      22                 :            : 
      23                 :            : struct spdk_rpc_server {
      24                 :            :         struct sockaddr_un listen_addr_unix;
      25                 :            :         char lock_path[sizeof(((struct sockaddr_un *)0)->sun_path) + sizeof(".lock")];
      26                 :            :         int lock_fd;
      27                 :            :         struct spdk_jsonrpc_server *jsonrpc_server;
      28                 :            : };
      29                 :            : 
      30                 :            : static struct spdk_rpc_server g_rpc_server;
      31                 :            : 
      32                 :            : struct spdk_rpc_method {
      33                 :            :         const char *name;
      34                 :            :         spdk_rpc_method_handler func;
      35                 :            :         SLIST_ENTRY(spdk_rpc_method) slist;
      36                 :            :         uint32_t state_mask;
      37                 :            :         bool is_deprecated;
      38                 :            :         struct spdk_rpc_method *is_alias_of;
      39                 :            :         bool deprecation_warning_printed;
      40                 :            : };
      41                 :            : 
      42                 :            : static SLIST_HEAD(, spdk_rpc_method) g_rpc_methods = SLIST_HEAD_INITIALIZER(g_rpc_methods);
      43                 :            : 
      44                 :            : void
      45                 :       2131 : spdk_rpc_set_state(uint32_t state)
      46                 :            : {
      47                 :       2131 :         g_rpc_state = state;
      48                 :       2131 : }
      49                 :            : 
      50                 :            : uint32_t
      51                 :     660162 : spdk_rpc_get_state(void)
      52                 :            : {
      53                 :     660162 :         return g_rpc_state;
      54                 :            : }
      55                 :            : 
      56                 :            : static bool
      57                 :     474635 : rpc_is_allowed(const char *name)
      58                 :            : {
      59                 :            :         size_t i;
      60                 :            : 
      61         [ +  + ]:     474635 :         if (g_rpcs_allowlist == NULL) {
      62                 :     463723 :                 return true;
      63                 :            :         }
      64                 :            : 
      65         [ +  + ]:      32526 :         for (i = 0; g_rpcs_allowlist[i] != NULL; i++) {
      66   [ +  +  -  +  :      21761 :                 if (strcmp(name, g_rpcs_allowlist[i]) == 0) {
                   +  + ]
      67                 :        147 :                         return true;
      68                 :            :                 }
      69                 :            :         }
      70                 :            : 
      71                 :      10765 :         return false;
      72                 :            : }
      73                 :            : 
      74                 :            : 
      75                 :            : static struct spdk_rpc_method *
      76                 :     476063 : _get_rpc_method(const struct spdk_json_val *method)
      77                 :            : {
      78                 :            :         struct spdk_rpc_method *m;
      79                 :            : 
      80         [ +  + ]:   49166598 :         SLIST_FOREACH(m, &g_rpc_methods, slist) {
      81         [ +  + ]:   48744100 :                 if (spdk_json_strequal(method, m->name)) {
      82         [ +  + ]:      53565 :                         if (!rpc_is_allowed(m->name)) {
      83                 :         21 :                                 return NULL;
      84                 :            :                         }
      85                 :      53544 :                         return m;
      86                 :            :                 }
      87                 :            :         }
      88                 :            : 
      89                 :     422498 :         return NULL;
      90                 :            : }
      91                 :            : 
      92                 :            : static struct spdk_rpc_method *
      93                 :     434857 : _get_rpc_method_raw(const char *method)
      94                 :            : {
      95                 :     185102 :         struct spdk_json_val method_val;
      96                 :            : 
      97                 :     434857 :         method_val.type = SPDK_JSON_VAL_STRING;
      98         [ -  + ]:     434857 :         method_val.len = strlen(method);
      99                 :     434857 :         method_val.start = (char *)method;
     100                 :            : 
     101                 :     434857 :         return _get_rpc_method(&method_val);
     102                 :            : }
     103                 :            : 
     104                 :            : static void
     105                 :      41206 : jsonrpc_handler(struct spdk_jsonrpc_request *request,
     106                 :            :                 const struct spdk_json_val *method,
     107                 :            :                 const struct spdk_json_val *params)
     108                 :            : {
     109                 :            :         struct spdk_rpc_method *m;
     110                 :            : 
     111         [ -  + ]:      41206 :         assert(method != NULL);
     112                 :            : 
     113                 :      41206 :         m = _get_rpc_method(method);
     114         [ +  + ]:      41206 :         if (m == NULL) {
     115                 :         26 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_METHOD_NOT_FOUND, "Method not found");
     116                 :         26 :                 return;
     117                 :            :         }
     118                 :            : 
     119         [ +  + ]:      41180 :         if (m->is_alias_of != NULL) {
     120   [ +  +  +  +  :         15 :                 if (m->is_deprecated && !m->deprecation_warning_printed) {
             -  +  +  + ]
     121                 :          5 :                         SPDK_WARNLOG("RPC method %s is deprecated.  Use %s instead.\n", m->name, m->is_alias_of->name);
     122                 :          5 :                         m->deprecation_warning_printed = true;
     123                 :            :                 }
     124                 :         15 :                 m = m->is_alias_of;
     125                 :            :         }
     126                 :            : 
     127         [ +  + ]:      41180 :         if ((m->state_mask & g_rpc_state) == g_rpc_state) {
     128                 :      41170 :                 m->func(request, params);
     129                 :            :         } else {
     130         [ +  + ]:         10 :                 if (g_rpc_state == SPDK_RPC_STARTUP) {
     131                 :          5 :                         spdk_jsonrpc_send_error_response_fmt(request,
     132                 :            :                                                              SPDK_JSONRPC_ERROR_INVALID_STATE,
     133                 :            :                                                              "Method may only be called after "
     134                 :            :                                                              "framework is initialized "
     135                 :            :                                                              "using framework_start_init RPC.");
     136                 :            :                 } else {
     137                 :          5 :                         spdk_jsonrpc_send_error_response_fmt(request,
     138                 :            :                                                              SPDK_JSONRPC_ERROR_INVALID_STATE,
     139                 :            :                                                              "Method may only be called before "
     140                 :            :                                                              "framework is initialized. "
     141                 :            :                                                              "Use --wait-for-rpc command line "
     142                 :            :                                                              "parameter and then issue this RPC "
     143                 :            :                                                              "before the framework_start_init RPC.");
     144                 :            :                 }
     145                 :            :         }
     146                 :            : }
     147                 :            : 
     148                 :            : static int
     149                 :       2602 : _spdk_rpc_listen(const char *listen_addr, struct spdk_rpc_server *server)
     150                 :            : {
     151                 :            :         int rc;
     152                 :            : 
     153         [ -  + ]:       2602 :         assert(listen_addr != NULL);
     154                 :            : 
     155                 :       2602 :         server->listen_addr_unix.sun_family = AF_UNIX;
     156                 :       2602 :         rc = snprintf(server->listen_addr_unix.sun_path,
     157                 :            :                       sizeof(server->listen_addr_unix.sun_path),
     158                 :            :                       "%s", listen_addr);
     159   [ +  -  -  + ]:       2602 :         if (rc < 0 || (size_t)rc >= sizeof(server->listen_addr_unix.sun_path)) {
     160                 :          0 :                 SPDK_ERRLOG("RPC Listen address Unix socket path too long\n");
     161                 :          0 :                 return -1;
     162                 :            :         }
     163                 :            : 
     164                 :       2602 :         rc = snprintf(server->lock_path, sizeof(server->lock_path), "%s.lock",
     165                 :       2602 :                       server->listen_addr_unix.sun_path);
     166   [ +  -  -  + ]:       2602 :         if (rc < 0 || (size_t)rc >= sizeof(server->lock_path)) {
     167                 :          0 :                 SPDK_ERRLOG("RPC lock path too long\n");
     168                 :          0 :                 return -1;
     169                 :            :         }
     170                 :            : 
     171         [ -  + ]:       2602 :         server->lock_fd = open(server->lock_path, O_RDWR | O_CREAT, 0600);
     172         [ -  + ]:       2602 :         if (server->lock_fd == -1) {
     173                 :          0 :                 SPDK_ERRLOG("Cannot open lock file %s: %s\n",
     174                 :            :                             server->lock_path, spdk_strerror(errno));
     175                 :          0 :                 return -1;
     176                 :            :         }
     177                 :            : 
     178                 :       2602 :         rc = flock(server->lock_fd, LOCK_EX | LOCK_NB);
     179         [ +  + ]:       2602 :         if (rc != 0) {
     180                 :         21 :                 SPDK_ERRLOG("RPC Unix domain socket path %s in use. Specify another.\n",
     181                 :            :                             server->listen_addr_unix.sun_path);
     182                 :         21 :                 return -1;
     183                 :            :         }
     184                 :            : 
     185                 :            :         /*
     186                 :            :          * Since we acquired the lock, it is safe to delete the Unix socket file
     187                 :            :          * if it still exists from a previous process.
     188                 :            :          */
     189         [ -  + ]:       2581 :         unlink(server->listen_addr_unix.sun_path);
     190                 :            : 
     191                 :       2856 :         server->jsonrpc_server = spdk_jsonrpc_server_listen(AF_UNIX, 0,
     192                 :       2581 :                                  (struct sockaddr *) & server->listen_addr_unix,
     193                 :            :                                  sizeof(server->listen_addr_unix),
     194                 :            :                                  jsonrpc_handler);
     195         [ -  + ]:       2581 :         if (server->jsonrpc_server == NULL) {
     196                 :          0 :                 SPDK_ERRLOG("spdk_jsonrpc_server_listen() failed\n");
     197                 :          0 :                 close(server->lock_fd);
     198         [ #  # ]:          0 :                 unlink(server->lock_path);
     199                 :          0 :                 return -1;
     200                 :            :         }
     201                 :            : 
     202                 :       2581 :         return 0;
     203                 :            : }
     204                 :            : 
     205         [ -  + ]:       2724 : SPDK_LOG_DEPRECATION_REGISTER(spdk_rpc_listen, "spdk_rpc_listen is deprecated", "v24.09", 0);
     206                 :            : 
     207                 :            : int
     208                 :         26 : spdk_rpc_listen(const char *listen_addr)
     209                 :            : {
     210                 :            :         struct spdk_rpc_server *server;
     211                 :            :         int rc;
     212                 :            : 
     213                 :         26 :         SPDK_LOG_DEPRECATED(spdk_rpc_listen);
     214                 :            : 
     215         [ -  + ]:         26 :         memset(&g_rpc_server.listen_addr_unix, 0, sizeof(g_rpc_server.listen_addr_unix));
     216                 :         26 :         server = &g_rpc_server;
     217                 :            : 
     218                 :         26 :         rc = _spdk_rpc_listen(listen_addr, server);
     219         [ -  + ]:         26 :         if (rc) {
     220                 :          0 :                 server->listen_addr_unix.sun_path[0] = '\0';
     221                 :          0 :                 server->lock_path[0] = '\0';
     222                 :            :         }
     223                 :            : 
     224                 :         26 :         return rc;
     225                 :            : }
     226                 :            : 
     227                 :            : struct spdk_rpc_server *
     228                 :       2576 : spdk_rpc_server_listen(const char *listen_addr)
     229                 :            : {
     230                 :            :         struct spdk_rpc_server *server;
     231                 :            :         int rc;
     232                 :            : 
     233                 :       2576 :         server = calloc(1, sizeof(struct spdk_rpc_server));
     234         [ -  + ]:       2576 :         if (!server) {
     235                 :          0 :                 SPDK_ERRLOG("Could not allocate new RPC server\n");
     236                 :          0 :                 return NULL;
     237                 :            :         }
     238                 :            : 
     239                 :       2576 :         rc = _spdk_rpc_listen(listen_addr, server);
     240         [ +  + ]:       2576 :         if (rc) {
     241                 :         21 :                 free(server);
     242                 :         21 :                 return NULL;
     243                 :            :         }
     244                 :            : 
     245                 :       2555 :         return server;
     246                 :            : }
     247                 :            : 
     248                 :            : void
     249                 :        273 : spdk_rpc_accept(void)
     250                 :            : {
     251                 :        273 :         spdk_jsonrpc_server_poll(g_rpc_server.jsonrpc_server);
     252                 :        273 : }
     253                 :            : 
     254                 :            : void
     255                 :    3768286 : spdk_rpc_server_accept(struct spdk_rpc_server *server)
     256                 :            : {
     257         [ -  + ]:    3768286 :         assert(server != NULL);
     258                 :    3768286 :         spdk_jsonrpc_server_poll(server->jsonrpc_server);
     259                 :    3768286 : }
     260                 :            : 
     261                 :            : void
     262                 :     422493 : spdk_rpc_register_method(const char *method, spdk_rpc_method_handler func, uint32_t state_mask)
     263                 :            : {
     264                 :            :         struct spdk_rpc_method *m;
     265                 :            : 
     266                 :     422493 :         m = _get_rpc_method_raw(method);
     267         [ -  + ]:     422493 :         if (m != NULL) {
     268                 :          0 :                 SPDK_ERRLOG("duplicate RPC %s registered...\n", method);
     269                 :          0 :                 g_rpcs_correct = false;
     270                 :          0 :                 return;
     271                 :            :         }
     272                 :            : 
     273                 :     422493 :         m = calloc(1, sizeof(struct spdk_rpc_method));
     274         [ -  + ]:     422493 :         assert(m != NULL);
     275                 :            : 
     276         [ -  + ]:     422493 :         m->name = strdup(method);
     277         [ -  + ]:     422493 :         assert(m->name != NULL);
     278                 :            : 
     279                 :     422493 :         m->func = func;
     280                 :     422493 :         m->state_mask = state_mask;
     281                 :            : 
     282                 :            :         /* TODO: use a hash table or sorted list */
     283                 :     422493 :         SLIST_INSERT_HEAD(&g_rpc_methods, m, slist);
     284                 :            : }
     285                 :            : 
     286                 :            : void
     287                 :      12364 : spdk_rpc_register_alias_deprecated(const char *method, const char *alias)
     288                 :            : {
     289                 :            :         struct spdk_rpc_method *m, *base;
     290                 :            : 
     291                 :      12364 :         base = _get_rpc_method_raw(method);
     292         [ -  + ]:      12364 :         if (base == NULL) {
     293                 :          0 :                 SPDK_ERRLOG("cannot create alias %s - method %s does not exist\n",
     294                 :            :                             alias, method);
     295                 :          0 :                 g_rpcs_correct = false;
     296                 :          0 :                 return;
     297                 :            :         }
     298                 :            : 
     299         [ -  + ]:      12364 :         if (base->is_alias_of != NULL) {
     300                 :          0 :                 SPDK_ERRLOG("cannot create alias %s of alias %s\n", alias, method);
     301                 :          0 :                 g_rpcs_correct = false;
     302                 :          0 :                 return;
     303                 :            :         }
     304                 :            : 
     305                 :      12364 :         m = calloc(1, sizeof(struct spdk_rpc_method));
     306         [ -  + ]:      12364 :         assert(m != NULL);
     307                 :            : 
     308         [ -  + ]:      12364 :         m->name = strdup(alias);
     309         [ -  + ]:      12364 :         assert(m->name != NULL);
     310                 :            : 
     311                 :      12364 :         m->is_alias_of = base;
     312                 :      12364 :         m->is_deprecated = true;
     313                 :      12364 :         m->state_mask = base->state_mask;
     314                 :            : 
     315                 :            :         /* TODO: use a hash table or sorted list */
     316                 :      12364 :         SLIST_INSERT_HEAD(&g_rpc_methods, m, slist);
     317                 :            : }
     318                 :            : 
     319                 :            : bool
     320                 :       2561 : spdk_rpc_verify_methods(void)
     321                 :            : {
     322         [ -  + ]:       2561 :         return g_rpcs_correct;
     323                 :            : }
     324                 :            : 
     325                 :            : int
     326                 :         15 : spdk_rpc_is_method_allowed(const char *method, uint32_t state_mask)
     327                 :            : {
     328                 :            :         struct spdk_rpc_method *m;
     329                 :            : 
     330         [ -  + ]:         15 :         if (!rpc_is_allowed(method)) {
     331                 :          0 :                 return -ENOENT;
     332                 :            :         }
     333                 :            : 
     334         [ +  + ]:         25 :         SLIST_FOREACH(m, &g_rpc_methods, slist) {
     335   [ +  +  -  +  :         20 :                 if (strcmp(m->name, method) != 0) {
                   +  + ]
     336                 :         10 :                         continue;
     337                 :            :                 }
     338                 :            : 
     339         [ +  + ]:         10 :                 if ((m->state_mask & state_mask) == state_mask) {
     340                 :          5 :                         return 0;
     341                 :            :                 } else {
     342                 :          5 :                         return -EPERM;
     343                 :            :                 }
     344                 :            :         }
     345                 :            : 
     346                 :          5 :         return -ENOENT;
     347                 :            : }
     348                 :            : 
     349                 :            : int
     350                 :       9174 : spdk_rpc_get_method_state_mask(const char *method, uint32_t *state_mask)
     351                 :            : {
     352                 :            :         struct spdk_rpc_method *m;
     353                 :            : 
     354         [ +  + ]:     962994 :         SLIST_FOREACH(m, &g_rpc_methods, slist) {
     355   [ +  +  -  +  :     962989 :                 if (strcmp(m->name, method) == 0) {
                   +  + ]
     356                 :       9169 :                         *state_mask = m->state_mask;
     357                 :       9169 :                         return 0;
     358                 :            :                 }
     359                 :            :         }
     360                 :            : 
     361                 :          5 :         return -ENOENT;
     362                 :            : }
     363                 :            : 
     364                 :            : void
     365                 :       4236 : spdk_rpc_set_allowlist(const char **rpc_allowlist)
     366                 :            : {
     367                 :       4236 :         spdk_strarray_free(g_rpcs_allowlist);
     368                 :            : 
     369         [ +  + ]:       4236 :         if (rpc_allowlist == NULL) {
     370                 :       4194 :                 g_rpcs_allowlist = NULL;
     371                 :       4194 :                 return;
     372                 :            :         }
     373                 :            : 
     374                 :         42 :         g_rpcs_allowlist = spdk_strarray_dup(rpc_allowlist);
     375         [ -  + ]:         42 :         assert(g_rpcs_allowlist != NULL);
     376                 :            : }
     377                 :            : 
     378                 :            : static void
     379                 :       2581 : _spdk_rpc_close(struct spdk_rpc_server *server)
     380                 :            : {
     381         [ -  + ]:       2581 :         assert(server != NULL);
     382         [ -  + ]:       2581 :         assert(server->jsonrpc_server != NULL);
     383                 :            : 
     384         [ +  - ]:       2581 :         if (server->listen_addr_unix.sun_path[0]) {
     385                 :            :                 /* Delete the Unix socket file */
     386         [ -  + ]:       2581 :                 unlink(server->listen_addr_unix.sun_path);
     387                 :       2581 :                 server->listen_addr_unix.sun_path[0] = '\0';
     388                 :            :         }
     389                 :            : 
     390                 :       2581 :         spdk_jsonrpc_server_shutdown(server->jsonrpc_server);
     391                 :       2581 :         server->jsonrpc_server = NULL;
     392                 :            : 
     393         [ +  - ]:       2581 :         if (server->lock_fd != -1) {
     394                 :       2581 :                 close(server->lock_fd);
     395                 :       2581 :                 server->lock_fd = -1;
     396                 :            :         }
     397                 :            : 
     398         [ +  - ]:       2581 :         if (server->lock_path[0]) {
     399         [ -  + ]:       2581 :                 unlink(server->lock_path);
     400                 :       2581 :                 server->lock_path[0] = '\0';
     401                 :            :         }
     402                 :       2581 : }
     403                 :            : 
     404         [ -  + ]:       2724 : SPDK_LOG_DEPRECATION_REGISTER(spdk_rpc_close, "spdk_rpc_close is deprecated", "v24.09", 0);
     405                 :            : 
     406                 :            : void
     407                 :         32 : spdk_rpc_close(void)
     408                 :            : {
     409                 :         32 :         SPDK_LOG_DEPRECATED(spdk_rpc_close);
     410                 :            : 
     411         [ +  + ]:         32 :         if (g_rpc_server.jsonrpc_server) {
     412                 :         26 :                 _spdk_rpc_close(&g_rpc_server);
     413                 :            :         }
     414                 :         32 : }
     415                 :            : 
     416                 :            : void
     417                 :       2555 : spdk_rpc_server_close(struct spdk_rpc_server *server)
     418                 :            : {
     419         [ -  + ]:       2555 :         assert(server != NULL);
     420                 :            : 
     421                 :       2555 :         _spdk_rpc_close(server);
     422                 :            : 
     423                 :       2555 :         free(server);
     424                 :       2555 : }
     425                 :            : 
     426                 :            : struct rpc_get_methods {
     427                 :            :         bool current;
     428                 :            :         bool include_aliases;
     429                 :            : };
     430                 :            : 
     431                 :            : static const struct spdk_json_object_decoder rpc_get_methods_decoders[] = {
     432                 :            :         {"current", offsetof(struct rpc_get_methods, current), spdk_json_decode_bool, true},
     433                 :            :         {"include_aliases", offsetof(struct rpc_get_methods, include_aliases), spdk_json_decode_bool, true},
     434                 :            : };
     435                 :            : 
     436                 :            : static void
     437                 :       1970 : rpc_get_methods(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
     438                 :            : {
     439                 :       1970 :         struct rpc_get_methods req = {};
     440                 :            :         struct spdk_json_write_ctx *w;
     441                 :            :         struct spdk_rpc_method *m;
     442                 :            : 
     443         [ +  + ]:       1970 :         if (params != NULL) {
     444         [ +  + ]:        541 :                 if (spdk_json_decode_object(params, rpc_get_methods_decoders,
     445                 :            :                                             SPDK_COUNTOF(rpc_get_methods_decoders), &req)) {
     446                 :          5 :                         SPDK_ERRLOG("spdk_json_decode_object failed\n");
     447                 :          5 :                         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     448                 :            :                                                          "Invalid parameters");
     449                 :          5 :                         return;
     450                 :            :                 }
     451                 :            :         }
     452                 :            : 
     453                 :       1965 :         w = spdk_jsonrpc_begin_result(request);
     454                 :       1965 :         spdk_json_write_array_begin(w);
     455         [ +  + ]:     423020 :         SLIST_FOREACH(m, &g_rpc_methods, slist) {
     456         [ +  + ]:     421055 :                 if (!rpc_is_allowed(m->name)) {
     457                 :      10744 :                         continue;
     458                 :            :                 }
     459   [ +  +  +  +  :     410311 :                 if (m->is_alias_of != NULL && !req.include_aliases) {
                   +  + ]
     460                 :      10746 :                         continue;
     461                 :            :                 }
     462   [ +  +  +  +  :     399565 :                 if (req.current && ((m->state_mask & g_rpc_state) != g_rpc_state)) {
                   +  + ]
     463                 :      10394 :                         continue;
     464                 :            :                 }
     465                 :     389171 :                 spdk_json_write_string(w, m->name);
     466                 :            :         }
     467                 :       1965 :         spdk_json_write_array_end(w);
     468                 :       1965 :         spdk_jsonrpc_end_result(request, w);
     469                 :            : }
     470                 :       2724 : SPDK_RPC_REGISTER("rpc_get_methods", rpc_get_methods, SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME)
     471                 :            : 
     472                 :            : static void
     473                 :         31 : rpc_spdk_get_version(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
     474                 :            : {
     475                 :            :         struct spdk_json_write_ctx *w;
     476                 :            : 
     477         [ +  + ]:         31 :         if (params != NULL) {
     478                 :          5 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     479                 :            :                                                  "spdk_get_version method requires no parameters");
     480                 :          5 :                 return;
     481                 :            :         }
     482                 :            : 
     483                 :         26 :         w = spdk_jsonrpc_begin_result(request);
     484                 :         26 :         spdk_json_write_object_begin(w);
     485                 :            : 
     486                 :         26 :         spdk_json_write_named_string_fmt(w, "version", "%s", SPDK_VERSION_STRING);
     487                 :         26 :         spdk_json_write_named_object_begin(w, "fields");
     488                 :         26 :         spdk_json_write_named_uint32(w, "major", SPDK_VERSION_MAJOR);
     489                 :         26 :         spdk_json_write_named_uint32(w, "minor", SPDK_VERSION_MINOR);
     490                 :         26 :         spdk_json_write_named_uint32(w, "patch", SPDK_VERSION_PATCH);
     491                 :         26 :         spdk_json_write_named_string_fmt(w, "suffix", "%s", SPDK_VERSION_SUFFIX);
     492                 :            : #ifdef SPDK_GIT_COMMIT
     493                 :         26 :         spdk_json_write_named_string_fmt(w, "commit", "%s", SPDK_GIT_COMMIT_STRING);
     494                 :            : #endif
     495                 :         26 :         spdk_json_write_object_end(w);
     496                 :            : 
     497                 :         26 :         spdk_json_write_object_end(w);
     498                 :         26 :         spdk_jsonrpc_end_result(request, w);
     499                 :            : }
     500                 :       2724 : SPDK_RPC_REGISTER("spdk_get_version", rpc_spdk_get_version,
     501                 :            :                   SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME)

Generated by: LCOV version 1.14