Spdk/module/bdev/virtio/bdev_virtio_rpc.c
paul luse a6dbe3721e update Intel copyright notices
per Intel policy to include file commit date using git cmd
below.  The policy does not apply to non-Intel (C) notices.

git log --follow -C90% --format=%ad --date default <file> | tail -1

and then pull just the 4 digit year from the result.

Intel copyrights were not added to files where Intel either had
no contribution ot the contribution lacked substance (ie license
header updates, formatting changes, etc).  Contribution date used
"--follow -C95%" to get the most accurate date.

Note that several files in this patch didn't end the license/(c)
block with a blank comment line so these were added as the vast
majority of files do have this last blank line.  Simply there for
consistency.

Signed-off-by: paul luse <paul.e.luse@intel.com>
Change-Id: Id5b7ce4f658fe87132f14139ead58d6e285c04d4
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15192
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Community-CI: Mellanox Build Bot
2022-11-10 08:28:53 +00:00

275 lines
8.8 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2017 Intel Corporation.
* All rights reserved.
*/
#include "spdk/stdinc.h"
#include "spdk/string.h"
#include "spdk/rpc.h"
#include "spdk/util.h"
#include "spdk/log.h"
#include "spdk/thread.h"
#include "bdev_virtio.h"
#define SPDK_VIRTIO_USER_DEFAULT_VQ_COUNT 1
#define SPDK_VIRTIO_USER_DEFAULT_QUEUE_SIZE 512
struct rpc_bdev_virtio_blk_hotplug {
bool enabled;
uint64_t period_us;
};
static const struct spdk_json_object_decoder rpc_bdev_virtio_blk_hotplug_decoders[] = {
{"enable", offsetof(struct rpc_bdev_virtio_blk_hotplug, enabled), spdk_json_decode_bool, false},
{"period_us", offsetof(struct rpc_bdev_virtio_blk_hotplug, period_us), spdk_json_decode_uint64, true},
};
static void
rpc_bdev_virtio_blk_set_hotplug(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_bdev_virtio_blk_hotplug req = {false, 0};
int rc;
if (spdk_json_decode_object(params, rpc_bdev_virtio_blk_hotplug_decoders,
SPDK_COUNTOF(rpc_bdev_virtio_blk_hotplug_decoders), &req)) {
SPDK_ERRLOG("spdk_json_decode_object failed\n");
rc = -EINVAL;
goto invalid;
}
rc = bdev_virtio_pci_blk_set_hotplug(req.enabled, req.period_us);
if (rc) {
goto invalid;
}
spdk_jsonrpc_send_bool_response(request, true);
return;
invalid:
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_strerror(-rc));
}
SPDK_RPC_REGISTER("bdev_virtio_blk_set_hotplug", rpc_bdev_virtio_blk_set_hotplug, SPDK_RPC_RUNTIME)
struct rpc_remove_virtio_dev {
char *name;
};
static const struct spdk_json_object_decoder rpc_remove_virtio_dev[] = {
{"name", offsetof(struct rpc_remove_virtio_dev, name), spdk_json_decode_string },
};
static void
rpc_bdev_virtio_detach_controller_cb(void *ctx, int errnum)
{
struct spdk_jsonrpc_request *request = ctx;
if (errnum != 0) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
spdk_strerror(-errnum));
return;
}
spdk_jsonrpc_send_bool_response(request, true);
}
static void
rpc_bdev_virtio_detach_controller(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_remove_virtio_dev req = {NULL};
int rc = 0;
if (spdk_json_decode_object(params, rpc_remove_virtio_dev,
SPDK_COUNTOF(rpc_remove_virtio_dev),
&req)) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"spdk_json_decode_object failed");
goto cleanup;
}
rc = bdev_virtio_blk_dev_remove(req.name, rpc_bdev_virtio_detach_controller_cb, request);
if (rc == -ENODEV) {
rc = bdev_virtio_scsi_dev_remove(req.name, rpc_bdev_virtio_detach_controller_cb, request);
}
if (rc != 0) {
spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
}
cleanup:
free(req.name);
}
SPDK_RPC_REGISTER("bdev_virtio_detach_controller",
rpc_bdev_virtio_detach_controller, SPDK_RPC_RUNTIME)
static void
rpc_bdev_virtio_scsi_get_devices(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct spdk_json_write_ctx *w;
if (params != NULL) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"bdev_virtio_scsi_get_devices requires no parameters");
return;
}
w = spdk_jsonrpc_begin_result(request);
bdev_virtio_scsi_dev_list(w);
spdk_jsonrpc_end_result(request, w);
}
SPDK_RPC_REGISTER("bdev_virtio_scsi_get_devices",
rpc_bdev_virtio_scsi_get_devices, SPDK_RPC_RUNTIME)
struct rpc_bdev_virtio_attach_controller_ctx {
char *name;
char *trtype;
char *traddr;
char *dev_type;
uint32_t vq_count;
uint32_t vq_size;
struct spdk_jsonrpc_request *request;
};
static const struct spdk_json_object_decoder rpc_bdev_virtio_attach_controller_ctx[] = {
{"name", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, name), spdk_json_decode_string },
{"trtype", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, trtype), spdk_json_decode_string },
{"traddr", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, traddr), spdk_json_decode_string },
{"dev_type", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, dev_type), spdk_json_decode_string },
{"vq_count", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, vq_count), spdk_json_decode_uint32, true },
{"vq_size", offsetof(struct rpc_bdev_virtio_attach_controller_ctx, vq_size), spdk_json_decode_uint32, true },
};
static void
free_rpc_bdev_virtio_attach_controller_ctx(struct rpc_bdev_virtio_attach_controller_ctx *req)
{
free(req->name);
free(req->trtype);
free(req->traddr);
free(req->dev_type);
free(req);
}
static void
rpc_create_virtio_dev_cb(void *ctx, int result, struct spdk_bdev **bdevs, size_t cnt)
{
struct rpc_bdev_virtio_attach_controller_ctx *req = ctx;
struct spdk_json_write_ctx *w;
size_t i;
if (result) {
spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
spdk_strerror(-result));
free_rpc_bdev_virtio_attach_controller_ctx(req);
return;
}
w = spdk_jsonrpc_begin_result(req->request);
spdk_json_write_array_begin(w);
for (i = 0; i < cnt; i++) {
spdk_json_write_string(w, spdk_bdev_get_name(bdevs[i]));
}
spdk_json_write_array_end(w);
spdk_jsonrpc_end_result(req->request, w);
free_rpc_bdev_virtio_attach_controller_ctx(ctx);
}
static void
rpc_bdev_virtio_attach_controller(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_bdev_virtio_attach_controller_ctx *req;
struct spdk_bdev *bdev = NULL;
struct spdk_pci_addr pci_addr;
int rc = 0;
req = calloc(1, sizeof(*req));
if (!req) {
SPDK_ERRLOG("calloc() failed\n");
spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
return;
}
if (spdk_json_decode_object(params, rpc_bdev_virtio_attach_controller_ctx,
SPDK_COUNTOF(rpc_bdev_virtio_attach_controller_ctx),
req)) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"spdk_json_decode_object failed");
goto cleanup;
}
if (strcmp(req->trtype, "pci") == 0) {
if (req->vq_count != 0 || req->vq_size != 0) {
SPDK_ERRLOG("VQ count or size is not allowed for PCI transport type\n");
spdk_jsonrpc_send_error_response(request, EINVAL,
"vq_count or vq_size is not allowed for PCI transport type.");
goto cleanup;
}
if (spdk_pci_addr_parse(&pci_addr, req->traddr) != 0) {
SPDK_ERRLOG("Invalid PCI address '%s'\n", req->traddr);
spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Invalid PCI address '%s'", req->traddr);
goto cleanup;
}
} else if (strcmp(req->trtype, "user") == 0) {
req->vq_count = req->vq_count == 0 ? SPDK_VIRTIO_USER_DEFAULT_VQ_COUNT : req->vq_count;
req->vq_size = req->vq_size == 0 ? SPDK_VIRTIO_USER_DEFAULT_QUEUE_SIZE : req->vq_size;
} else if (strcmp(req->trtype, "vfio-user") == 0) {
if (req->vq_count != 0 || req->vq_size != 0) {
SPDK_ERRLOG("VQ count or size is not allowed for vfio-user transport type\n");
spdk_jsonrpc_send_error_response(request, EINVAL,
"vq_count or vq_size is not allowed for vfio-user transport type.");
goto cleanup;
}
} else {
SPDK_ERRLOG("Invalid trtype '%s'\n", req->trtype);
spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Invalid trtype '%s'", req->trtype);
goto cleanup;
}
req->request = request;
if (strcmp(req->dev_type, "blk") == 0) {
if (strcmp(req->trtype, "pci") == 0) {
bdev = bdev_virtio_pci_blk_dev_create(req->name, &pci_addr);
} else if (strcmp(req->trtype, "user") == 0) {
bdev = bdev_virtio_user_blk_dev_create(req->name, req->traddr, req->vq_count, req->vq_size);
} else if (strcmp(req->trtype, "vfio-user") == 0) {
bdev = bdev_virtio_vfio_user_blk_dev_create(req->name, req->traddr);
}
/* Virtio blk doesn't use callback so call it manually to send result. */
rc = bdev ? 0 : -EINVAL;
rpc_create_virtio_dev_cb(req, rc, &bdev, bdev ? 1 : 0);
} else if (strcmp(req->dev_type, "scsi") == 0) {
if (strcmp(req->trtype, "pci") == 0) {
rc = bdev_virtio_pci_scsi_dev_create(req->name, &pci_addr, rpc_create_virtio_dev_cb, req);
} else if (strcmp(req->trtype, "user") == 0) {
rc = bdev_virtio_user_scsi_dev_create(req->name, req->traddr, req->vq_count, req->vq_size,
rpc_create_virtio_dev_cb, req);
} else if (strcmp(req->trtype, "vfio-user") == 0) {
rc = bdev_vfio_user_scsi_dev_create(req->name, req->traddr, rpc_create_virtio_dev_cb, req);
}
if (rc < 0) {
/* In case of error callback is not called so do it manually to send result. */
rpc_create_virtio_dev_cb(req, rc, NULL, 0);
}
} else {
SPDK_ERRLOG("Invalid dev_type '%s'\n", req->dev_type);
spdk_jsonrpc_send_error_response_fmt(request, EINVAL, "Invalid dev_type '%s'", req->dev_type);
goto cleanup;
}
return;
cleanup:
free_rpc_bdev_virtio_attach_controller_ctx(req);
}
SPDK_RPC_REGISTER("bdev_virtio_attach_controller",
rpc_bdev_virtio_attach_controller, SPDK_RPC_RUNTIME);