LCOV - code coverage report
Current view: top level - module/bdev/virtio - bdev_virtio_rpc.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 121 0.0 %
Date: 2024-07-15 01:10:13 Functions: 0 11 0.0 %

          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           0 : 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           0 : rpc_bdev_virtio_detach_controller_cb(void *ctx, int errnum)
      65             : {
      66           0 :         struct spdk_jsonrpc_request *request = ctx;
      67             : 
      68           0 :         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           0 :         spdk_jsonrpc_send_bool_response(request, true);
      75             : }
      76             : 
      77             : static void
      78           0 : rpc_bdev_virtio_detach_controller(struct spdk_jsonrpc_request *request,
      79             :                                   const struct spdk_json_val *params)
      80             : {
      81           0 :         struct rpc_remove_virtio_dev req = {NULL};
      82           0 :         int rc = 0;
      83             : 
      84           0 :         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           0 :         rc = bdev_virtio_blk_dev_remove(req.name, rpc_bdev_virtio_detach_controller_cb, request);
      93           0 :         if (rc == -ENODEV) {
      94           0 :                 rc = bdev_virtio_scsi_dev_remove(req.name, rpc_bdev_virtio_detach_controller_cb, request);
      95             :         }
      96             : 
      97           0 :         if (rc != 0) {
      98           0 :                 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
      99             :         }
     100             : 
     101           0 : cleanup:
     102           0 :         free(req.name);
     103           0 : }
     104           0 : SPDK_RPC_REGISTER("bdev_virtio_detach_controller",
     105             :                   rpc_bdev_virtio_detach_controller, SPDK_RPC_RUNTIME)
     106             : 
     107             : static void
     108           0 : 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           0 :         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           0 :         w = spdk_jsonrpc_begin_result(request);
     120           0 :         bdev_virtio_scsi_dev_list(w);
     121           0 :         spdk_jsonrpc_end_result(request, w);
     122             : }
     123           0 : 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           0 : free_rpc_bdev_virtio_attach_controller_ctx(struct rpc_bdev_virtio_attach_controller_ctx *req)
     147             : {
     148           0 :         free(req->name);
     149           0 :         free(req->trtype);
     150           0 :         free(req->traddr);
     151           0 :         free(req->dev_type);
     152           0 :         free(req);
     153           0 : }
     154             : 
     155             : static void
     156           0 : rpc_create_virtio_dev_cb(void *ctx, int result, struct spdk_bdev **bdevs, size_t cnt)
     157             : {
     158           0 :         struct rpc_bdev_virtio_attach_controller_ctx *req = ctx;
     159             :         struct spdk_json_write_ctx *w;
     160             :         size_t i;
     161             : 
     162           0 :         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           0 :         w = spdk_jsonrpc_begin_result(req->request);
     170           0 :         spdk_json_write_array_begin(w);
     171             : 
     172           0 :         for (i = 0; i < cnt; i++) {
     173           0 :                 spdk_json_write_string(w, spdk_bdev_get_name(bdevs[i]));
     174             :         }
     175             : 
     176           0 :         spdk_json_write_array_end(w);
     177           0 :         spdk_jsonrpc_end_result(req->request, w);
     178             : 
     179           0 :         free_rpc_bdev_virtio_attach_controller_ctx(ctx);
     180             : }
     181             : 
     182             : static void
     183           0 : 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           0 :         struct spdk_bdev *bdev = NULL;
     188           0 :         struct spdk_pci_addr pci_addr;
     189           0 :         int rc = 0;
     190             : 
     191           0 :         req = calloc(1, sizeof(*req));
     192           0 :         if (!req) {
     193           0 :                 SPDK_ERRLOG("calloc() failed\n");
     194           0 :                 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
     195           0 :                 return;
     196             :         }
     197             : 
     198           0 :         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           0 :         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           0 :         } else if (strcmp(req->trtype, "user") == 0) {
     220           0 :                 req->vq_count = req->vq_count == 0 ? SPDK_VIRTIO_USER_DEFAULT_VQ_COUNT : req->vq_count;
     221           0 :                 req->vq_size = req->vq_size == 0 ? SPDK_VIRTIO_USER_DEFAULT_QUEUE_SIZE : req->vq_size;
     222           0 :         } else if (strcmp(req->trtype, "vfio-user") == 0) {
     223           0 :                 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           0 :         req->request = request;
     236           0 :         if (strcmp(req->dev_type, "blk") == 0) {
     237           0 :                 if (strcmp(req->trtype, "pci") == 0) {
     238           0 :                         bdev = bdev_virtio_pci_blk_dev_create(req->name, &pci_addr);
     239           0 :                 } else if (strcmp(req->trtype, "user") == 0) {
     240           0 :                         bdev = bdev_virtio_user_blk_dev_create(req->name, req->traddr, req->vq_count, req->vq_size);
     241           0 :                 } else if (strcmp(req->trtype, "vfio-user") == 0) {
     242           0 :                         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           0 :                 rc = bdev ? 0 : -EINVAL;
     247           0 :                 rpc_create_virtio_dev_cb(req, rc, &bdev, bdev ? 1 : 0);
     248           0 :         } else if (strcmp(req->dev_type, "scsi") == 0) {
     249           0 :                 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           0 :                 } else if (strcmp(req->trtype, "user") == 0) {
     252           0 :                         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           0 :                 } else if (strcmp(req->trtype, "vfio-user") == 0) {
     255           0 :                         rc = bdev_vfio_user_scsi_dev_create(req->name, req->traddr, rpc_create_virtio_dev_cb, req);
     256             :                 }
     257             : 
     258           0 :                 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           0 :         return;
     269             : 
     270           0 : cleanup:
     271           0 :         free_rpc_bdev_virtio_attach_controller_ctx(req);
     272             : }
     273           0 : SPDK_RPC_REGISTER("bdev_virtio_attach_controller",
     274             :                   rpc_bdev_virtio_attach_controller, SPDK_RPC_RUNTIME);

Generated by: LCOV version 1.15