LCOV - code coverage report
Current view: top level - spdk/module/bdev/virtio - bdev_virtio_rpc.c (source / functions) Hit Total Coverage
Test: Combined Lines: 72 121 59.5 %
Date: 2024-07-15 14:51:33 Functions: 10 11 90.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 45 86 52.3 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2017 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : 
       8                 :            : #include "spdk/string.h"
       9                 :            : #include "spdk/rpc.h"
      10                 :            : #include "spdk/util.h"
      11                 :            : #include "spdk/log.h"
      12                 :            : #include "spdk/thread.h"
      13                 :            : 
      14                 :            : #include "bdev_virtio.h"
      15                 :            : 
      16                 :            : #define SPDK_VIRTIO_USER_DEFAULT_VQ_COUNT               1
      17                 :            : #define SPDK_VIRTIO_USER_DEFAULT_QUEUE_SIZE             512
      18                 :            : 
      19                 :            : struct rpc_bdev_virtio_blk_hotplug {
      20                 :            :         bool enabled;
      21                 :            :         uint64_t period_us;
      22                 :            : };
      23                 :            : 
      24                 :            : static const struct spdk_json_object_decoder rpc_bdev_virtio_blk_hotplug_decoders[] = {
      25                 :            :         {"enable", offsetof(struct rpc_bdev_virtio_blk_hotplug, enabled), spdk_json_decode_bool, false},
      26                 :            :         {"period_us", offsetof(struct rpc_bdev_virtio_blk_hotplug, period_us), spdk_json_decode_uint64, true},
      27                 :            : };
      28                 :            : 
      29                 :            : static void
      30                 :          0 : rpc_bdev_virtio_blk_set_hotplug(struct spdk_jsonrpc_request *request,
      31                 :            :                                 const struct spdk_json_val *params)
      32                 :            : {
      33                 :          0 :         struct rpc_bdev_virtio_blk_hotplug req = {false, 0};
      34                 :            :         int rc;
      35                 :            : 
      36         [ #  # ]:          0 :         if (spdk_json_decode_object(params, rpc_bdev_virtio_blk_hotplug_decoders,
      37                 :            :                                     SPDK_COUNTOF(rpc_bdev_virtio_blk_hotplug_decoders), &req)) {
      38                 :          0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
      39                 :          0 :                 rc = -EINVAL;
      40                 :          0 :                 goto invalid;
      41                 :            :         }
      42                 :            : 
      43         [ #  # ]:          0 :         rc = bdev_virtio_pci_blk_set_hotplug(req.enabled, req.period_us);
      44         [ #  # ]:          0 :         if (rc) {
      45                 :          0 :                 goto invalid;
      46                 :            :         }
      47                 :            : 
      48                 :          0 :         spdk_jsonrpc_send_bool_response(request, true);
      49                 :          0 :         return;
      50                 :          0 : invalid:
      51                 :          0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc));
      52                 :            : }
      53                 :       1905 : SPDK_RPC_REGISTER("bdev_virtio_blk_set_hotplug", rpc_bdev_virtio_blk_set_hotplug, SPDK_RPC_RUNTIME)
      54                 :            : 
      55                 :            : struct rpc_remove_virtio_dev {
      56                 :            :         char *name;
      57                 :            : };
      58                 :            : 
      59                 :            : static const struct spdk_json_object_decoder rpc_remove_virtio_dev[] = {
      60                 :            :         {"name", offsetof(struct rpc_remove_virtio_dev, name), spdk_json_decode_string },
      61                 :            : };
      62                 :            : 
      63                 :            : static void
      64                 :          6 : rpc_bdev_virtio_detach_controller_cb(void *ctx, int errnum)
      65                 :            : {
      66                 :          6 :         struct spdk_jsonrpc_request *request = ctx;
      67                 :            : 
      68         [ -  + ]:          6 :         if (errnum != 0) {
      69                 :          0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
      70                 :            :                                                  spdk_strerror(-errnum));
      71                 :          0 :                 return;
      72                 :            :         }
      73                 :            : 
      74                 :          6 :         spdk_jsonrpc_send_bool_response(request, true);
      75                 :            : }
      76                 :            : 
      77                 :            : static void
      78                 :          6 : rpc_bdev_virtio_detach_controller(struct spdk_jsonrpc_request *request,
      79                 :            :                                   const struct spdk_json_val *params)
      80                 :            : {
      81                 :          6 :         struct rpc_remove_virtio_dev req = {NULL};
      82                 :          6 :         int rc = 0;
      83                 :            : 
      84         [ -  + ]:          6 :         if (spdk_json_decode_object(params, rpc_remove_virtio_dev,
      85                 :            :                                     SPDK_COUNTOF(rpc_remove_virtio_dev),
      86                 :            :                                     &req)) {
      87                 :          0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
      88                 :            :                                                  "spdk_json_decode_object failed");
      89                 :          0 :                 goto cleanup;
      90                 :            :         }
      91                 :            : 
      92                 :          6 :         rc = bdev_virtio_blk_dev_remove(req.name, rpc_bdev_virtio_detach_controller_cb, request);
      93         [ +  + ]:          6 :         if (rc == -ENODEV) {
      94                 :          3 :                 rc = bdev_virtio_scsi_dev_remove(req.name, rpc_bdev_virtio_detach_controller_cb, request);
      95                 :            :         }
      96                 :            : 
      97         [ +  - ]:          6 :         if (rc != 0) {
      98                 :          0 :                 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
      99                 :            :         }
     100                 :            : 
     101                 :          6 : cleanup:
     102                 :          6 :         free(req.name);
     103                 :          6 : }
     104                 :       1905 : SPDK_RPC_REGISTER("bdev_virtio_detach_controller",
     105                 :            :                   rpc_bdev_virtio_detach_controller, SPDK_RPC_RUNTIME)
     106                 :            : 
     107                 :            : static void
     108                 :        336 : rpc_bdev_virtio_scsi_get_devices(struct spdk_jsonrpc_request *request,
     109                 :            :                                  const struct spdk_json_val *params)
     110                 :            : {
     111                 :            :         struct spdk_json_write_ctx *w;
     112                 :            : 
     113         [ -  + ]:        336 :         if (params != NULL) {
     114                 :          0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     115                 :            :                                                  "bdev_virtio_scsi_get_devices requires no parameters");
     116                 :          0 :                 return;
     117                 :            :         }
     118                 :            : 
     119                 :        336 :         w = spdk_jsonrpc_begin_result(request);
     120                 :        336 :         bdev_virtio_scsi_dev_list(w);
     121                 :        336 :         spdk_jsonrpc_end_result(request, w);
     122                 :            : }
     123                 :       1905 : SPDK_RPC_REGISTER("bdev_virtio_scsi_get_devices",
     124                 :            :                   rpc_bdev_virtio_scsi_get_devices, SPDK_RPC_RUNTIME)
     125                 :            : 
     126                 :            : struct rpc_bdev_virtio_attach_controller_ctx {
     127                 :            :         char *name;
     128                 :            :         char *trtype;
     129                 :            :         char *traddr;
     130                 :            :         char *dev_type;
     131                 :            :         uint32_t vq_count;
     132                 :            :         uint32_t vq_size;
     133                 :            :         struct spdk_jsonrpc_request *request;
     134                 :            : };
     135                 :            : 
     136                 :            : static const struct spdk_json_object_decoder rpc_bdev_virtio_attach_controller_ctx[] = {
     137                 :            :         {"name", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, name), spdk_json_decode_string },
     138                 :            :         {"trtype", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, trtype), spdk_json_decode_string },
     139                 :            :         {"traddr", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, traddr), spdk_json_decode_string },
     140                 :            :         {"dev_type", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, dev_type), spdk_json_decode_string },
     141                 :            :         {"vq_count", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, vq_count), spdk_json_decode_uint32, true },
     142                 :            :         {"vq_size", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, vq_size), spdk_json_decode_uint32, true },
     143                 :            : };
     144                 :            : 
     145                 :            : static void
     146                 :         25 : free_rpc_bdev_virtio_attach_controller_ctx(struct rpc_bdev_virtio_attach_controller_ctx *req)
     147                 :            : {
     148                 :         25 :         free(req->name);
     149                 :         25 :         free(req->trtype);
     150                 :         25 :         free(req->traddr);
     151                 :         25 :         free(req->dev_type);
     152                 :         25 :         free(req);
     153                 :         25 : }
     154                 :            : 
     155                 :            : static void
     156                 :         25 : rpc_create_virtio_dev_cb(void *ctx, int result, struct spdk_bdev **bdevs, size_t cnt)
     157                 :            : {
     158                 :         25 :         struct rpc_bdev_virtio_attach_controller_ctx *req = ctx;
     159                 :            :         struct spdk_json_write_ctx *w;
     160                 :            :         size_t i;
     161                 :            : 
     162         [ -  + ]:         25 :         if (result) {
     163                 :          0 :                 spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     164                 :            :                                                  spdk_strerror(-result));
     165                 :          0 :                 free_rpc_bdev_virtio_attach_controller_ctx(req);
     166                 :          0 :                 return;
     167                 :            :         }
     168                 :            : 
     169                 :         25 :         w = spdk_jsonrpc_begin_result(req->request);
     170                 :         25 :         spdk_json_write_array_begin(w);
     171                 :            : 
     172         [ +  + ]:         62 :         for (i = 0; i < cnt; i++) {
     173                 :         37 :                 spdk_json_write_string(w, spdk_bdev_get_name(bdevs[i]));
     174                 :            :         }
     175                 :            : 
     176                 :         25 :         spdk_json_write_array_end(w);
     177                 :         25 :         spdk_jsonrpc_end_result(req->request, w);
     178                 :            : 
     179                 :         25 :         free_rpc_bdev_virtio_attach_controller_ctx(ctx);
     180                 :            : }
     181                 :            : 
     182                 :            : static void
     183                 :         25 : rpc_bdev_virtio_attach_controller(struct spdk_jsonrpc_request *request,
     184                 :            :                                   const struct spdk_json_val *params)
     185                 :            : {
     186                 :            :         struct rpc_bdev_virtio_attach_controller_ctx *req;
     187                 :         25 :         struct spdk_bdev *bdev = NULL;
     188                 :          2 :         struct spdk_pci_addr pci_addr;
     189                 :         25 :         int rc = 0;
     190                 :            : 
     191                 :         25 :         req = calloc(1, sizeof(*req));
     192         [ -  + ]:         25 :         if (!req) {
     193                 :          0 :                 SPDK_ERRLOG("calloc() failed\n");
     194                 :          0 :                 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
     195                 :         23 :                 return;
     196                 :            :         }
     197                 :            : 
     198         [ -  + ]:         25 :         if (spdk_json_decode_object(params, rpc_bdev_virtio_attach_controller_ctx,
     199                 :            :                                     SPDK_COUNTOF(rpc_bdev_virtio_attach_controller_ctx),
     200                 :            :                                     req)) {
     201                 :          0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     202                 :            :                                                  "spdk_json_decode_object failed");
     203                 :          0 :                 goto cleanup;
     204                 :            :         }
     205                 :            : 
     206   [ -  +  -  + ]:         25 :         if (strcmp(req->trtype, "pci") == 0) {
     207   [ #  #  #  # ]:          0 :                 if (req->vq_count != 0 || req->vq_size != 0) {
     208                 :          0 :                         SPDK_ERRLOG("VQ count or size is not allowed for PCI transport type\n");
     209                 :          0 :                         spdk_jsonrpc_send_error_response(request, EINVAL,
     210                 :            :                                                          "vq_count or vq_size is not allowed for PCI transport type.");
     211                 :          0 :                         goto cleanup;
     212                 :            :                 }
     213                 :            : 
     214         [ #  # ]:          0 :                 if (spdk_pci_addr_parse(&pci_addr, req->traddr) != 0) {
     215                 :          0 :                         SPDK_ERRLOG("Invalid PCI address '%s'\n", req->traddr);
     216                 :          0 :                         spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Invalid PCI address '%s'", req->traddr);
     217                 :          0 :                         goto cleanup;
     218                 :            :                 }
     219   [ -  +  +  + ]:         25 :         } else if (strcmp(req->trtype, "user") == 0) {
     220         [ +  + ]:         23 :                 req->vq_count = req->vq_count == 0 ? SPDK_VIRTIO_USER_DEFAULT_VQ_COUNT : req->vq_count;
     221         [ +  + ]:         23 :                 req->vq_size = req->vq_size == 0 ? SPDK_VIRTIO_USER_DEFAULT_QUEUE_SIZE : req->vq_size;
     222   [ -  +  +  - ]:          2 :         } else if (strcmp(req->trtype, "vfio-user") == 0) {
     223   [ +  -  -  + ]:          2 :                 if (req->vq_count != 0 || req->vq_size != 0) {
     224                 :          0 :                         SPDK_ERRLOG("VQ count or size is not allowed for vfio-user transport type\n");
     225                 :          0 :                         spdk_jsonrpc_send_error_response(request, EINVAL,
     226                 :            :                                                          "vq_count or vq_size is not allowed for vfio-user transport type.");
     227                 :          0 :                         goto cleanup;
     228                 :            :                 }
     229                 :            :         } else {
     230                 :          0 :                 SPDK_ERRLOG("Invalid trtype '%s'\n", req->trtype);
     231                 :          0 :                 spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Invalid trtype '%s'", req->trtype);
     232                 :          0 :                 goto cleanup;
     233                 :            :         }
     234                 :            : 
     235                 :         25 :         req->request = request;
     236   [ -  +  +  + ]:         25 :         if (strcmp(req->dev_type, "blk") == 0) {
     237   [ -  +  -  + ]:         12 :                 if (strcmp(req->trtype, "pci") == 0) {
     238                 :          0 :                         bdev = bdev_virtio_pci_blk_dev_create(req->name, &pci_addr);
     239   [ -  +  +  + ]:         12 :                 } else if (strcmp(req->trtype, "user") == 0) {
     240                 :         11 :                         bdev = bdev_virtio_user_blk_dev_create(req->name, req->traddr, req->vq_count, req->vq_size);
     241   [ -  +  +  - ]:          1 :                 } else if (strcmp(req->trtype, "vfio-user") == 0) {
     242                 :          1 :                         bdev = bdev_virtio_vfio_user_blk_dev_create(req->name, req->traddr);
     243                 :            :                 }
     244                 :            : 
     245                 :            :                 /* Virtio blk doesn't use callback so call it manually to send result. */
     246         [ +  - ]:         12 :                 rc = bdev ? 0 : -EINVAL;
     247                 :         12 :                 rpc_create_virtio_dev_cb(req, rc, &bdev, bdev ? 1 : 0);
     248   [ -  +  +  - ]:         13 :         } else if (strcmp(req->dev_type, "scsi") == 0) {
     249   [ -  +  -  + ]:         13 :                 if (strcmp(req->trtype, "pci") == 0) {
     250                 :          0 :                         rc = bdev_virtio_pci_scsi_dev_create(req->name, &pci_addr, rpc_create_virtio_dev_cb, req);
     251   [ -  +  +  + ]:         13 :                 } else if (strcmp(req->trtype, "user") == 0) {
     252                 :         12 :                         rc = bdev_virtio_user_scsi_dev_create(req->name, req->traddr, req->vq_count, req->vq_size,
     253                 :            :                                                               rpc_create_virtio_dev_cb, req);
     254   [ -  +  +  - ]:          1 :                 } else if (strcmp(req->trtype, "vfio-user") == 0) {
     255                 :          1 :                         rc = bdev_vfio_user_scsi_dev_create(req->name, req->traddr, rpc_create_virtio_dev_cb, req);
     256                 :            :                 }
     257                 :            : 
     258         [ -  + ]:         13 :                 if (rc < 0) {
     259                 :            :                         /* In case of error callback is not called so do it manually to send result. */
     260                 :          0 :                         rpc_create_virtio_dev_cb(req, rc, NULL, 0);
     261                 :            :                 }
     262                 :            :         } else {
     263                 :          0 :                 SPDK_ERRLOG("Invalid dev_type '%s'\n", req->dev_type);
     264                 :          0 :                 spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Invalid dev_type '%s'", req->dev_type);
     265                 :          0 :                 goto cleanup;
     266                 :            :         }
     267                 :            : 
     268                 :         25 :         return;
     269                 :            : 
     270                 :          0 : cleanup:
     271                 :          0 :         free_rpc_bdev_virtio_attach_controller_ctx(req);
     272                 :            : }
     273                 :       1905 : SPDK_RPC_REGISTER("bdev_virtio_attach_controller",
     274                 :            :                   rpc_bdev_virtio_attach_controller, SPDK_RPC_RUNTIME);

Generated by: LCOV version 1.14