mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 17:53:56 -06:00
Block layer patches
- Supporting changing 'file' in x-blockdev-reopen - ssh: add support for sha256 host key fingerprints - vhost-user-blk: Implement reconnection during realize - introduce QEMU_AUTO_VFREE - Don't require password of encrypted backing file for image creation - Code cleanups -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmDclTcRHGt3b2xmQHJl ZGhhdC5jb20ACgkQfwmycsiPL9bzaw/+PYQ9vPG+ZROWl633TUOQu7IYGZynXCET ZHlV2JlXnFH8QoO8A53U72cgVg+GlwDpiMCCtjEGMG1yfMBNe+DXR1wFUMDne1Gs qIFX4gIVpPGDi3gPeQvefLCwoN8VXwIxvCJj40YR9BY0cqQR6joI81kjVlqKemqB cHG4qJHmnphihSLep/dd2BRInkeHWXWU63jK4d7ctdCwHZPNDf0u0FEraxEqS/d0 5tfdIl3haghhoDRRamyh5bLZBCW1KlpfTR98RdspcwpSlXq/FgV5N9CFa15XSYfQ rinSClSIOpLzG90+tBihROVBXvbugO5qZVQTG0Yg1tt4FGG8Cmiqf9MNXC5yctNg WnaQQipx/37deafGA4jqorZBJd1R87JLJTBFTpkB47XAFq/ltqsTDhrrfdS+jail Fd+qyqWg0Jx3JjdhSUpHvDKBBsErjoxtoyQIGakSreXGmj2UY6BFmGii7lnLZNLo +E81C7exnkCIGKkOHy+y9DkpVY/PEJKCG7uwcyy+F2qOqGUOxKLuZomWcLodo6Vf /eJ/UsLJt6HhXhXq/1ZZHmaORn8Lft1yr/9azoGXZ7er+jZcbEkhbcZmET+Y6ykq Vox/GmLkhyVkM96MA0lMW5hHPWUbF29m9Jmq3nNfvFWBcILEs4uWSlbd0M2oAmWj ung9sKIV/8s= =aB0a -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block layer patches - Supporting changing 'file' in x-blockdev-reopen - ssh: add support for sha256 host key fingerprints - vhost-user-blk: Implement reconnection during realize - introduce QEMU_AUTO_VFREE - Don't require password of encrypted backing file for image creation - Code cleanups # gpg: Signature made Wed 30 Jun 2021 17:00:55 BST # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (24 commits) vhost-user-blk: Implement reconnection during realize vhost-user-blk: Factor out vhost_user_blk_realize_connect() vhost: Distinguish errors in vhost_dev_get_config() vhost-user-blk: Add Error parameter to vhost_user_blk_start() vhost: Return 0/-errno in vhost_dev_init() vhost: Distinguish errors in vhost_backend_init() vhost: Add Error parameter to vhost_dev_init() block/ssh: add support for sha256 host key fingerprints block/commit: use QEMU_AUTO_VFREE introduce QEMU_AUTO_VFREE iotests: Test replacing files with x-blockdev-reopen block: Allow changing bs->file on reopen block: BDRVReopenState: drop replace_backing_bs field block: move supports_backing check to bdrv_set_file_or_backing_noperm() block: bdrv_reopen_parse_backing(): simplify handling implicit filters block: bdrv_reopen_parse_backing(): don't check frozen child block: bdrv_reopen_parse_backing(): don't check aio context block: introduce bdrv_set_file_or_backing_noperm() block: introduce bdrv_remove_file_or_backing_child() block: comment graph-modifying function not updating permissions ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
9c2647f750
32 changed files with 601 additions and 305 deletions
|
@ -31,6 +31,8 @@
|
|||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/runstate.h"
|
||||
|
||||
#define REALIZE_CONNECTION_RETRIES 3
|
||||
|
||||
static const int user_feature_bits[] = {
|
||||
VIRTIO_BLK_F_SIZE_MAX,
|
||||
VIRTIO_BLK_F_SEG_MAX,
|
||||
|
@ -91,11 +93,13 @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev)
|
|||
int ret;
|
||||
struct virtio_blk_config blkcfg;
|
||||
VHostUserBlk *s = VHOST_USER_BLK(dev->vdev);
|
||||
Error *local_err = NULL;
|
||||
|
||||
ret = vhost_dev_get_config(dev, (uint8_t *)&blkcfg,
|
||||
sizeof(struct virtio_blk_config));
|
||||
sizeof(struct virtio_blk_config),
|
||||
&local_err);
|
||||
if (ret < 0) {
|
||||
error_report("get config space failed");
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -113,7 +117,7 @@ const VhostDevConfigOps blk_ops = {
|
|||
.vhost_dev_config_notifier = vhost_user_blk_handle_config_change,
|
||||
};
|
||||
|
||||
static int vhost_user_blk_start(VirtIODevice *vdev)
|
||||
static int vhost_user_blk_start(VirtIODevice *vdev, Error **errp)
|
||||
{
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
|
||||
|
@ -121,19 +125,19 @@ static int vhost_user_blk_start(VirtIODevice *vdev)
|
|||
int i, ret;
|
||||
|
||||
if (!k->set_guest_notifiers) {
|
||||
error_report("binding does not support guest notifiers");
|
||||
error_setg(errp, "binding does not support guest notifiers");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
ret = vhost_dev_enable_notifiers(&s->dev, vdev);
|
||||
if (ret < 0) {
|
||||
error_report("Error enabling host notifiers: %d", -ret);
|
||||
error_setg_errno(errp, -ret, "Error enabling host notifiers");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, true);
|
||||
if (ret < 0) {
|
||||
error_report("Error binding guest notifier: %d", -ret);
|
||||
error_setg_errno(errp, -ret, "Error binding guest notifier");
|
||||
goto err_host_notifiers;
|
||||
}
|
||||
|
||||
|
@ -141,27 +145,27 @@ static int vhost_user_blk_start(VirtIODevice *vdev)
|
|||
|
||||
ret = vhost_dev_prepare_inflight(&s->dev, vdev);
|
||||
if (ret < 0) {
|
||||
error_report("Error set inflight format: %d", -ret);
|
||||
error_setg_errno(errp, -ret, "Error setting inflight format");
|
||||
goto err_guest_notifiers;
|
||||
}
|
||||
|
||||
if (!s->inflight->addr) {
|
||||
ret = vhost_dev_get_inflight(&s->dev, s->queue_size, s->inflight);
|
||||
if (ret < 0) {
|
||||
error_report("Error get inflight: %d", -ret);
|
||||
error_setg_errno(errp, -ret, "Error getting inflight");
|
||||
goto err_guest_notifiers;
|
||||
}
|
||||
}
|
||||
|
||||
ret = vhost_dev_set_inflight(&s->dev, s->inflight);
|
||||
if (ret < 0) {
|
||||
error_report("Error set inflight: %d", -ret);
|
||||
error_setg_errno(errp, -ret, "Error setting inflight");
|
||||
goto err_guest_notifiers;
|
||||
}
|
||||
|
||||
ret = vhost_dev_start(&s->dev, vdev);
|
||||
if (ret < 0) {
|
||||
error_report("Error starting vhost: %d", -ret);
|
||||
error_setg_errno(errp, -ret, "Error starting vhost");
|
||||
goto err_guest_notifiers;
|
||||
}
|
||||
s->started_vu = true;
|
||||
|
@ -214,6 +218,7 @@ static void vhost_user_blk_set_status(VirtIODevice *vdev, uint8_t status)
|
|||
{
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
bool should_start = virtio_device_started(vdev, status);
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
if (!vdev->vm_running) {
|
||||
|
@ -229,10 +234,9 @@ static void vhost_user_blk_set_status(VirtIODevice *vdev, uint8_t status)
|
|||
}
|
||||
|
||||
if (should_start) {
|
||||
ret = vhost_user_blk_start(vdev);
|
||||
ret = vhost_user_blk_start(vdev, &local_err);
|
||||
if (ret < 0) {
|
||||
error_report("vhost-user-blk: vhost start failed: %s",
|
||||
strerror(-ret));
|
||||
error_reportf_err(local_err, "vhost-user-blk: vhost start failed: ");
|
||||
qemu_chr_fe_disconnect(&s->chardev);
|
||||
}
|
||||
} else {
|
||||
|
@ -270,6 +274,7 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev,
|
|||
static void vhost_user_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
Error *local_err = NULL;
|
||||
int i, ret;
|
||||
|
||||
if (!vdev->start_on_kick) {
|
||||
|
@ -287,10 +292,9 @@ static void vhost_user_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
|||
/* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start
|
||||
* vhost here instead of waiting for .set_status().
|
||||
*/
|
||||
ret = vhost_user_blk_start(vdev);
|
||||
ret = vhost_user_blk_start(vdev, &local_err);
|
||||
if (ret < 0) {
|
||||
error_report("vhost-user-blk: vhost start failed: %s",
|
||||
strerror(-ret));
|
||||
error_reportf_err(local_err, "vhost-user-blk: vhost start failed: ");
|
||||
qemu_chr_fe_disconnect(&s->chardev);
|
||||
return;
|
||||
}
|
||||
|
@ -332,17 +336,16 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
|
|||
|
||||
vhost_dev_set_config_notifier(&s->dev, &blk_ops);
|
||||
|
||||
ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0);
|
||||
ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0,
|
||||
errp);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "vhost initialization failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* restore vhost state */
|
||||
if (virtio_device_started(vdev, vdev->status)) {
|
||||
ret = vhost_user_blk_start(vdev);
|
||||
ret = vhost_user_blk_start(vdev, errp);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "vhost start failed");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -422,10 +425,42 @@ static void vhost_user_blk_event(void *opaque, QEMUChrEvent event)
|
|||
}
|
||||
}
|
||||
|
||||
static int vhost_user_blk_realize_connect(VHostUserBlk *s, Error **errp)
|
||||
{
|
||||
DeviceState *dev = &s->parent_obj.parent_obj;
|
||||
int ret;
|
||||
|
||||
s->connected = false;
|
||||
|
||||
ret = qemu_chr_fe_wait_connected(&s->chardev, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = vhost_user_blk_connect(dev, errp);
|
||||
if (ret < 0) {
|
||||
qemu_chr_fe_disconnect(&s->chardev);
|
||||
return ret;
|
||||
}
|
||||
assert(s->connected);
|
||||
|
||||
ret = vhost_dev_get_config(&s->dev, (uint8_t *)&s->blkcfg,
|
||||
sizeof(struct virtio_blk_config), errp);
|
||||
if (ret < 0) {
|
||||
qemu_chr_fe_disconnect(&s->chardev);
|
||||
vhost_dev_cleanup(&s->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
int retries;
|
||||
int i, ret;
|
||||
|
||||
if (!s->chardev.chr) {
|
||||
|
@ -466,23 +501,20 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
s->inflight = g_new0(struct vhost_inflight, 1);
|
||||
s->vhost_vqs = g_new0(struct vhost_virtqueue, s->num_queues);
|
||||
s->connected = false;
|
||||
|
||||
if (qemu_chr_fe_wait_connected(&s->chardev, errp) < 0) {
|
||||
goto virtio_err;
|
||||
}
|
||||
retries = REALIZE_CONNECTION_RETRIES;
|
||||
assert(!*errp);
|
||||
do {
|
||||
if (*errp) {
|
||||
error_prepend(errp, "Reconnecting after error: ");
|
||||
error_report_err(*errp);
|
||||
*errp = NULL;
|
||||
}
|
||||
ret = vhost_user_blk_realize_connect(s, errp);
|
||||
} while (ret == -EPROTO && retries--);
|
||||
|
||||
if (vhost_user_blk_connect(dev, errp) < 0) {
|
||||
qemu_chr_fe_disconnect(&s->chardev);
|
||||
goto virtio_err;
|
||||
}
|
||||
assert(s->connected);
|
||||
|
||||
ret = vhost_dev_get_config(&s->dev, (uint8_t *)&s->blkcfg,
|
||||
sizeof(struct virtio_blk_config));
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "vhost-user-blk: get block config failed");
|
||||
goto vhost_err;
|
||||
goto virtio_err;
|
||||
}
|
||||
|
||||
/* we're fully initialized, now we can operate, so add the handler */
|
||||
|
@ -491,8 +523,6 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
|
|||
NULL, true);
|
||||
return;
|
||||
|
||||
vhost_err:
|
||||
vhost_dev_cleanup(&s->dev);
|
||||
virtio_err:
|
||||
g_free(s->vhost_vqs);
|
||||
s->vhost_vqs = NULL;
|
||||
|
|
|
@ -415,14 +415,16 @@ vhost_user_gpu_get_config(VirtIODevice *vdev, uint8_t *config_data)
|
|||
VirtIOGPUBase *b = VIRTIO_GPU_BASE(vdev);
|
||||
struct virtio_gpu_config *vgconfig =
|
||||
(struct virtio_gpu_config *)config_data;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
memset(config_data, 0, sizeof(struct virtio_gpu_config));
|
||||
|
||||
ret = vhost_dev_get_config(&g->vhost->dev,
|
||||
config_data, sizeof(struct virtio_gpu_config));
|
||||
config_data, sizeof(struct virtio_gpu_config),
|
||||
&local_err);
|
||||
if (ret) {
|
||||
error_report("vhost-user-gpu: get device config space failed");
|
||||
error_report_err(local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,13 +49,15 @@ static void vhost_input_get_config(VirtIODevice *vdev, uint8_t *config_data)
|
|||
{
|
||||
VirtIOInput *vinput = VIRTIO_INPUT(vdev);
|
||||
VHostUserInput *vhi = VHOST_USER_INPUT(vdev);
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
memset(config_data, 0, vinput->cfg_size);
|
||||
|
||||
ret = vhost_dev_get_config(&vhi->vhost->dev, config_data, vinput->cfg_size);
|
||||
ret = vhost_dev_get_config(&vhi->vhost->dev, config_data, vinput->cfg_size,
|
||||
&local_err);
|
||||
if (ret) {
|
||||
error_report("vhost-user-input: get device config space failed");
|
||||
error_report_err(local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "standard-headers/linux/vhost_types.h"
|
||||
#include "hw/virtio/virtio-net.h"
|
||||
#include "net/vhost_net.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
|
@ -116,7 +117,7 @@ uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
|
|||
int vhost_net_get_config(struct vhost_net *net, uint8_t *config,
|
||||
uint32_t config_len)
|
||||
{
|
||||
return vhost_dev_get_config(&net->dev, config, config_len);
|
||||
return vhost_dev_get_config(&net->dev, config, config_len, NULL);
|
||||
}
|
||||
int vhost_net_set_config(struct vhost_net *net, const uint8_t *data,
|
||||
uint32_t offset, uint32_t size, uint32_t flags)
|
||||
|
@ -157,6 +158,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
|||
bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL;
|
||||
struct vhost_net *net = g_new0(struct vhost_net, 1);
|
||||
uint64_t features = 0;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!options->net_backend) {
|
||||
fprintf(stderr, "vhost-net requires net backend to be setup\n");
|
||||
|
@ -187,8 +189,10 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
|||
}
|
||||
|
||||
r = vhost_dev_init(&net->dev, options->opaque,
|
||||
options->backend_type, options->busyloop_timeout);
|
||||
options->backend_type, options->busyloop_timeout,
|
||||
&local_err);
|
||||
if (r < 0) {
|
||||
error_report_err(local_err);
|
||||
goto fail;
|
||||
}
|
||||
if (backend_kernel) {
|
||||
|
|
|
@ -219,10 +219,8 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
|
|||
vsc->dev.backend_features = 0;
|
||||
|
||||
ret = vhost_dev_init(&vsc->dev, (void *)(uintptr_t)vhostfd,
|
||||
VHOST_BACKEND_TYPE_KERNEL, 0);
|
||||
VHOST_BACKEND_TYPE_KERNEL, 0, errp);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
|
||||
strerror(-ret));
|
||||
goto free_vqs;
|
||||
}
|
||||
|
||||
|
|
|
@ -122,10 +122,8 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
|
|||
vqs = vsc->dev.vqs;
|
||||
|
||||
ret = vhost_dev_init(&vsc->dev, &s->vhost_user,
|
||||
VHOST_BACKEND_TYPE_USER, 0);
|
||||
VHOST_BACKEND_TYPE_USER, 0, errp);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "vhost-user-scsi: vhost initialization failed: %s",
|
||||
strerror(-ret));
|
||||
goto free_vhost;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,13 +24,15 @@ static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request,
|
|||
void *arg)
|
||||
{
|
||||
int fd = (uintptr_t) dev->opaque;
|
||||
int ret;
|
||||
|
||||
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
|
||||
|
||||
return ioctl(fd, request, arg);
|
||||
ret = ioctl(fd, request, arg);
|
||||
return ret < 0 ? -errno : ret;
|
||||
}
|
||||
|
||||
static int vhost_kernel_init(struct vhost_dev *dev, void *opaque)
|
||||
static int vhost_kernel_init(struct vhost_dev *dev, void *opaque, Error **errp)
|
||||
{
|
||||
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
|
||||
|
||||
|
|
|
@ -235,9 +235,8 @@ static void vuf_device_realize(DeviceState *dev, Error **errp)
|
|||
fs->vhost_dev.nvqs = 1 + fs->conf.num_request_queues;
|
||||
fs->vhost_dev.vqs = g_new0(struct vhost_virtqueue, fs->vhost_dev.nvqs);
|
||||
ret = vhost_dev_init(&fs->vhost_dev, &fs->vhost_user,
|
||||
VHOST_BACKEND_TYPE_USER, 0);
|
||||
VHOST_BACKEND_TYPE_USER, 0, errp);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "vhost_dev_init failed");
|
||||
goto err_virtio;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,12 @@ static void vuv_get_config(VirtIODevice *vdev, uint8_t *config)
|
|||
static int vuv_handle_config_change(struct vhost_dev *dev)
|
||||
{
|
||||
VHostUserVSock *vsock = VHOST_USER_VSOCK(dev->vdev);
|
||||
Error *local_err = NULL;
|
||||
int ret = vhost_dev_get_config(dev, (uint8_t *)&vsock->vsockcfg,
|
||||
sizeof(struct virtio_vsock_config));
|
||||
sizeof(struct virtio_vsock_config),
|
||||
&local_err);
|
||||
if (ret < 0) {
|
||||
error_report("get config space failed");
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -108,16 +110,14 @@ static void vuv_device_realize(DeviceState *dev, Error **errp)
|
|||
vhost_dev_set_config_notifier(&vvc->vhost_dev, &vsock_ops);
|
||||
|
||||
ret = vhost_dev_init(&vvc->vhost_dev, &vsock->vhost_user,
|
||||
VHOST_BACKEND_TYPE_USER, 0);
|
||||
VHOST_BACKEND_TYPE_USER, 0, errp);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "vhost_dev_init failed");
|
||||
goto err_virtio;
|
||||
}
|
||||
|
||||
ret = vhost_dev_get_config(&vvc->vhost_dev, (uint8_t *)&vsock->vsockcfg,
|
||||
sizeof(struct virtio_vsock_config));
|
||||
sizeof(struct virtio_vsock_config), errp);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "get config space failed");
|
||||
goto err_vhost_dev;
|
||||
}
|
||||
|
||||
|
|
|
@ -1353,7 +1353,11 @@ static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64)
|
|||
|
||||
static int vhost_user_get_features(struct vhost_dev *dev, uint64_t *features)
|
||||
{
|
||||
return vhost_user_get_u64(dev, VHOST_USER_GET_FEATURES, features);
|
||||
if (vhost_user_get_u64(dev, VHOST_USER_GET_FEATURES, features) < 0) {
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vhost_user_set_owner(struct vhost_dev *dev)
|
||||
|
@ -1364,7 +1368,7 @@ static int vhost_user_set_owner(struct vhost_dev *dev)
|
|||
};
|
||||
|
||||
if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
|
||||
return -1;
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1856,7 +1860,8 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque)
|
||||
static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
|
||||
Error **errp)
|
||||
{
|
||||
uint64_t features, protocol_features, ram_slots;
|
||||
struct vhost_user *u;
|
||||
|
@ -1880,7 +1885,7 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque)
|
|||
err = vhost_user_get_u64(dev, VHOST_USER_GET_PROTOCOL_FEATURES,
|
||||
&protocol_features);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
dev->protocol_features =
|
||||
|
@ -1891,14 +1896,14 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque)
|
|||
dev->protocol_features &= ~(1ULL << VHOST_USER_PROTOCOL_F_CONFIG);
|
||||
} else if (!(protocol_features &
|
||||
(1ULL << VHOST_USER_PROTOCOL_F_CONFIG))) {
|
||||
error_report("Device expects VHOST_USER_PROTOCOL_F_CONFIG "
|
||||
"but backend does not support it.");
|
||||
return -1;
|
||||
error_setg(errp, "Device expects VHOST_USER_PROTOCOL_F_CONFIG "
|
||||
"but backend does not support it.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = vhost_user_set_protocol_features(dev, dev->protocol_features);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
/* query the max queues we support if backend supports Multiple Queue */
|
||||
|
@ -1906,12 +1911,12 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque)
|
|||
err = vhost_user_get_u64(dev, VHOST_USER_GET_QUEUE_NUM,
|
||||
&dev->max_queues);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
return -EPROTO;
|
||||
}
|
||||
}
|
||||
if (dev->num_queues && dev->max_queues < dev->num_queues) {
|
||||
error_report("The maximum number of queues supported by the "
|
||||
"backend is %" PRIu64, dev->max_queues);
|
||||
error_setg(errp, "The maximum number of queues supported by the "
|
||||
"backend is %" PRIu64, dev->max_queues);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1920,9 +1925,9 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque)
|
|||
VHOST_USER_PROTOCOL_F_SLAVE_REQ) &&
|
||||
virtio_has_feature(dev->protocol_features,
|
||||
VHOST_USER_PROTOCOL_F_REPLY_ACK))) {
|
||||
error_report("IOMMU support requires reply-ack and "
|
||||
"slave-req protocol features.");
|
||||
return -1;
|
||||
error_setg(errp, "IOMMU support requires reply-ack and "
|
||||
"slave-req protocol features.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* get max memory regions if backend supports configurable RAM slots */
|
||||
|
@ -1932,15 +1937,15 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque)
|
|||
} else {
|
||||
err = vhost_user_get_max_memslots(dev, &ram_slots);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (ram_slots < u->user->memory_slots) {
|
||||
error_report("The backend specified a max ram slots limit "
|
||||
"of %" PRIu64", when the prior validated limit was %d. "
|
||||
"This limit should never decrease.", ram_slots,
|
||||
u->user->memory_slots);
|
||||
return -1;
|
||||
error_setg(errp, "The backend specified a max ram slots limit "
|
||||
"of %" PRIu64", when the prior validated limit was "
|
||||
"%d. This limit should never decrease.", ram_slots,
|
||||
u->user->memory_slots);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
u->user->memory_slots = MIN(ram_slots, VHOST_USER_MAX_RAM_SLOTS);
|
||||
|
@ -1958,7 +1963,7 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque)
|
|||
if (dev->vq_index == 0) {
|
||||
err = vhost_setup_slave_channel(dev);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
return -EPROTO;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2112,7 +2117,7 @@ static void vhost_user_set_iotlb_callback(struct vhost_dev *dev, int enabled)
|
|||
}
|
||||
|
||||
static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config,
|
||||
uint32_t config_len)
|
||||
uint32_t config_len, Error **errp)
|
||||
{
|
||||
VhostUserMsg msg = {
|
||||
.hdr.request = VHOST_USER_GET_CONFIG,
|
||||
|
@ -2122,32 +2127,32 @@ static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config,
|
|||
|
||||
if (!virtio_has_feature(dev->protocol_features,
|
||||
VHOST_USER_PROTOCOL_F_CONFIG)) {
|
||||
return -1;
|
||||
error_setg(errp, "VHOST_USER_PROTOCOL_F_CONFIG not supported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (config_len > VHOST_USER_MAX_CONFIG_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
assert(config_len <= VHOST_USER_MAX_CONFIG_SIZE);
|
||||
|
||||
msg.payload.config.offset = 0;
|
||||
msg.payload.config.size = config_len;
|
||||
if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
|
||||
return -1;
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (vhost_user_read(dev, &msg) < 0) {
|
||||
return -1;
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (msg.hdr.request != VHOST_USER_GET_CONFIG) {
|
||||
error_report("Received unexpected msg type. Expected %d received %d",
|
||||
VHOST_USER_GET_CONFIG, msg.hdr.request);
|
||||
return -1;
|
||||
error_setg(errp,
|
||||
"Received unexpected msg type. Expected %d received %d",
|
||||
VHOST_USER_GET_CONFIG, msg.hdr.request);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (msg.hdr.size != VHOST_USER_CONFIG_HDR_SIZE + config_len) {
|
||||
error_report("Received bad msg size.");
|
||||
return -1;
|
||||
error_setg(errp, "Received bad msg size.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(config, msg.payload.config.region, config_len);
|
||||
|
|
|
@ -245,10 +245,12 @@ static int vhost_vdpa_call(struct vhost_dev *dev, unsigned long int request,
|
|||
{
|
||||
struct vhost_vdpa *v = dev->opaque;
|
||||
int fd = v->device_fd;
|
||||
int ret;
|
||||
|
||||
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
|
||||
|
||||
return ioctl(fd, request, arg);
|
||||
ret = ioctl(fd, request, arg);
|
||||
return ret < 0 ? -errno : ret;
|
||||
}
|
||||
|
||||
static void vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status)
|
||||
|
@ -265,7 +267,7 @@ static void vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status)
|
|||
vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &s);
|
||||
}
|
||||
|
||||
static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque)
|
||||
static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp)
|
||||
{
|
||||
struct vhost_vdpa *v;
|
||||
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
|
||||
|
@ -521,7 +523,7 @@ static int vhost_vdpa_set_config(struct vhost_dev *dev, const uint8_t *data,
|
|||
}
|
||||
|
||||
static int vhost_vdpa_get_config(struct vhost_dev *dev, uint8_t *config,
|
||||
uint32_t config_len)
|
||||
uint32_t config_len, Error **errp)
|
||||
{
|
||||
struct vhost_vdpa_config *v_config;
|
||||
unsigned long config_size = offsetof(struct vhost_vdpa_config, buf);
|
||||
|
|
|
@ -170,9 +170,8 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
|
|||
vhost_vsock_common_realize(vdev, "vhost-vsock");
|
||||
|
||||
ret = vhost_dev_init(&vvc->vhost_dev, (void *)(uintptr_t)vhostfd,
|
||||
VHOST_BACKEND_TYPE_KERNEL, 0);
|
||||
VHOST_BACKEND_TYPE_KERNEL, 0, errp);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "vhost-vsock: vhost_dev_init failed");
|
||||
goto err_virtio;
|
||||
}
|
||||
|
||||
|
|
|
@ -1286,11 +1286,12 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
|
|||
}
|
||||
|
||||
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
||||
VhostBackendType backend_type, uint32_t busyloop_timeout)
|
||||
VhostBackendType backend_type, uint32_t busyloop_timeout,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
uint64_t features;
|
||||
int i, r, n_initialized_vqs = 0;
|
||||
Error *local_err = NULL;
|
||||
|
||||
hdev->vdev = NULL;
|
||||
hdev->migration_blocker = NULL;
|
||||
|
@ -1298,26 +1299,30 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
|||
r = vhost_set_backend_type(hdev, backend_type);
|
||||
assert(r >= 0);
|
||||
|
||||
r = hdev->vhost_ops->vhost_backend_init(hdev, opaque);
|
||||
r = hdev->vhost_ops->vhost_backend_init(hdev, opaque, errp);
|
||||
if (r < 0) {
|
||||
if (!*errp) {
|
||||
error_setg_errno(errp, -r, "vhost_backend_init failed");
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = hdev->vhost_ops->vhost_set_owner(hdev);
|
||||
if (r < 0) {
|
||||
VHOST_OPS_DEBUG("vhost_set_owner failed");
|
||||
error_setg_errno(errp, -r, "vhost_set_owner failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = hdev->vhost_ops->vhost_get_features(hdev, &features);
|
||||
if (r < 0) {
|
||||
VHOST_OPS_DEBUG("vhost_get_features failed");
|
||||
error_setg_errno(errp, -r, "vhost_get_features failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) {
|
||||
r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i);
|
||||
if (r < 0) {
|
||||
error_setg_errno(errp, -r, "Failed to initialize virtqueue %d", i);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -1327,6 +1332,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
|||
r = vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i,
|
||||
busyloop_timeout);
|
||||
if (r < 0) {
|
||||
error_setg_errno(errp, -r, "Failed to set busyloop timeout");
|
||||
goto fail_busyloop;
|
||||
}
|
||||
}
|
||||
|
@ -1365,9 +1371,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
|||
}
|
||||
|
||||
if (hdev->migration_blocker != NULL) {
|
||||
r = migrate_add_blocker(hdev->migration_blocker, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
r = migrate_add_blocker(hdev->migration_blocker, errp);
|
||||
if (*errp) {
|
||||
error_free(hdev->migration_blocker);
|
||||
goto fail_busyloop;
|
||||
}
|
||||
|
@ -1384,9 +1389,9 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
|
|||
QLIST_INSERT_HEAD(&vhost_devices, hdev, entry);
|
||||
|
||||
if (used_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) {
|
||||
error_report("vhost backend memory slots limit is less"
|
||||
" than current number of present memory slots");
|
||||
r = -1;
|
||||
error_setg(errp, "vhost backend memory slots limit is less"
|
||||
" than current number of present memory slots");
|
||||
r = -EINVAL;
|
||||
goto fail_busyloop;
|
||||
}
|
||||
|
||||
|
@ -1557,15 +1562,23 @@ void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
|
|||
}
|
||||
|
||||
int vhost_dev_get_config(struct vhost_dev *hdev, uint8_t *config,
|
||||
uint32_t config_len)
|
||||
uint32_t config_len, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
int ret;
|
||||
|
||||
assert(hdev->vhost_ops);
|
||||
|
||||
if (hdev->vhost_ops->vhost_get_config) {
|
||||
return hdev->vhost_ops->vhost_get_config(hdev, config, config_len);
|
||||
ret = hdev->vhost_ops->vhost_get_config(hdev, config, config_len, errp);
|
||||
if (ret < 0 && !*errp) {
|
||||
error_setg_errno(errp, -ret, "vhost_get_config failed");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return -1;
|
||||
error_setg(errp, "vhost_get_config not implemented");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int vhost_dev_set_config(struct vhost_dev *hdev, const uint8_t *data,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue