Block layer patches

- vhost-user-blk: Fix error handling during initialisation
 - Add test cases for the vhost-user-blk export
 - Fix leaked Transaction objects
 - qcow2: Expose dirty bit in 'qemu-img info'
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmCjnaoRHGt3b2xmQHJl
 ZGhhdC5jb20ACgkQfwmycsiPL9ZRDRAAw814/9O2E5dXDK3dZfqHqxWBdvNuPEuj
 LTUSGpuF+cAPAMJhzZm5Hy8n8G4KGwzpqt/vgBSnBAeAjHPBORGu4gEpr0G/GiHk
 OltElQ2GBBtHdixVhhimk7XoaE90Rmonh3uvolzdI8Ej8a2uvVYJcZhOD4JNZiOV
 HweG5SWcL3mvF4S8m0SOTFdlzeyA8NloaDduILiX+GiwiHystWw7e9bMMyP9Mejx
 95Qip9Huco3KFpYSpnGCvhTJ4jZwuQdqKs2d0dJBtIiU5PeRBY4mw4XT8xh6K3SA
 d/DBIDJ0iEQiVT/a2eNVtY/MsOklJYqnGVUWs18piOu1d/r6zQ2whLtIx/H6z3eD
 PLk1/mKNYcHDM6sTdBpliRsBDRJ7yeeaSqUGY3JPbyIhc7A/gqgfkXiRfEvN9lHF
 O/zerX4tgg7HRlqsyEyT937wiT7I8HHhbS0JtC0c5uxwmk4J0L+PUCnFptUtmZim
 iJTO5h90PKldnzKz0VNXgvrvCFTgmyR/aq89VZfafTE4sNSlZOTbasPADcPUUr/V
 Ju5J1r3J3lctjBGAReiTRxeTHyYHP2BEfzBqt3Orf86qrsNuWY3SXbzAEbcT1Pyu
 O6rIOF6B8DWEN5R2krPC/aw4/lXDST1FdVHibrmbUyQaayJrEWwvudqgTzCcfPNr
 c96LQH3gkTY=
 =Xe4O
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging

Block layer patches

- vhost-user-blk: Fix error handling during initialisation
- Add test cases for the vhost-user-blk export
- Fix leaked Transaction objects
- qcow2: Expose dirty bit in 'qemu-img info'

# gpg: Signature made Tue 18 May 2021 11:57:46 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:
  vhost-user-blk: Check that num-queues is supported by backend
  virtio: Fail if iommu_platform is requested, but unsupported
  vhost-user-blk: Get more feature flags from vhost device
  vhost-user-blk: Improve error reporting in realize
  vhost-user-blk: Don't reconnect during initialisation
  vhost-user-blk: Make sure to set Error on realize failure
  vhost-user-blk-test: test discard/write zeroes invalid inputs
  tests/qtest: add multi-queue test case to vhost-user-blk-test
  test: new qTest case to test the vhost-user-blk-server
  block/export: improve vu_blk_sect_range_ok()
  block: Fix Transaction leak in bdrv_reopen_multiple()
  block: Fix Transaction leak in bdrv_root_attach_child()
  qcow2: set bdi->is_dirty

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-05-19 16:10:35 +01:00
commit d874bc0816
13 changed files with 1230 additions and 60 deletions

View file

@ -47,9 +47,13 @@ static const int user_feature_bits[] = {
VIRTIO_RING_F_INDIRECT_DESC,
VIRTIO_RING_F_EVENT_IDX,
VIRTIO_F_NOTIFY_ON_EMPTY,
VIRTIO_F_RING_PACKED,
VIRTIO_F_IOMMU_PLATFORM,
VHOST_INVALID_FEATURE_BIT
};
static void vhost_user_blk_event(void *opaque, QEMUChrEvent event);
static void vhost_user_blk_update_config(VirtIODevice *vdev, uint8_t *config)
{
VHostUserBlk *s = VHOST_USER_BLK(vdev);
@ -309,7 +313,7 @@ static void vhost_user_blk_reset(VirtIODevice *vdev)
vhost_dev_free_inflight(s->inflight);
}
static int vhost_user_blk_connect(DeviceState *dev)
static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostUserBlk *s = VHOST_USER_BLK(vdev);
@ -320,6 +324,7 @@ static int vhost_user_blk_connect(DeviceState *dev)
}
s->connected = true;
s->dev.num_queues = s->num_queues;
s->dev.nvqs = s->num_queues;
s->dev.vqs = s->vhost_vqs;
s->dev.vq_index = 0;
@ -329,8 +334,7 @@ static int vhost_user_blk_connect(DeviceState *dev)
ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0);
if (ret < 0) {
error_report("vhost-user-blk: vhost initialization failed: %s",
strerror(-ret));
error_setg_errno(errp, -ret, "vhost initialization failed");
return ret;
}
@ -338,8 +342,7 @@ static int vhost_user_blk_connect(DeviceState *dev)
if (virtio_device_started(vdev, vdev->status)) {
ret = vhost_user_blk_start(vdev);
if (ret < 0) {
error_report("vhost-user-blk: vhost start failed: %s",
strerror(-ret));
error_setg_errno(errp, -ret, "vhost start failed");
return ret;
}
}
@ -362,19 +365,6 @@ static void vhost_user_blk_disconnect(DeviceState *dev)
vhost_dev_cleanup(&s->dev);
}
static void vhost_user_blk_event(void *opaque, QEMUChrEvent event,
bool realized);
static void vhost_user_blk_event_realize(void *opaque, QEMUChrEvent event)
{
vhost_user_blk_event(opaque, event, false);
}
static void vhost_user_blk_event_oper(void *opaque, QEMUChrEvent event)
{
vhost_user_blk_event(opaque, event, true);
}
static void vhost_user_blk_chr_closed_bh(void *opaque)
{
DeviceState *dev = opaque;
@ -382,36 +372,27 @@ static void vhost_user_blk_chr_closed_bh(void *opaque)
VHostUserBlk *s = VHOST_USER_BLK(vdev);
vhost_user_blk_disconnect(dev);
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL,
vhost_user_blk_event_oper, NULL, opaque, NULL, true);
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event,
NULL, opaque, NULL, true);
}
static void vhost_user_blk_event(void *opaque, QEMUChrEvent event,
bool realized)
static void vhost_user_blk_event(void *opaque, QEMUChrEvent event)
{
DeviceState *dev = opaque;
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostUserBlk *s = VHOST_USER_BLK(vdev);
Error *local_err = NULL;
switch (event) {
case CHR_EVENT_OPENED:
if (vhost_user_blk_connect(dev) < 0) {
if (vhost_user_blk_connect(dev, &local_err) < 0) {
error_report_err(local_err);
qemu_chr_fe_disconnect(&s->chardev);
return;
}
break;
case CHR_EVENT_CLOSED:
/*
* Closing the connection should happen differently on device
* initialization and operation stages.
* On initalization, we want to re-start vhost_dev initialization
* from the very beginning right away when the connection is closed,
* so we clean up vhost_dev on each connection closing.
* On operation, we want to postpone vhost_dev cleanup to let the
* other code perform its own cleanup sequence using vhost_dev data
* (e.g. vhost_dev_set_log).
*/
if (realized && !runstate_check(RUN_STATE_SHUTDOWN)) {
if (!runstate_check(RUN_STATE_SHUTDOWN)) {
/*
* A close event may happen during a read/write, but vhost
* code assumes the vhost_dev remains setup, so delay the
@ -431,8 +412,6 @@ static void vhost_user_blk_event(void *opaque, QEMUChrEvent event,
* knowing its type (in this case vhost-user).
*/
s->dev.started = false;
} else {
vhost_user_blk_disconnect(dev);
}
break;
case CHR_EVENT_BREAK:
@ -447,11 +426,10 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostUserBlk *s = VHOST_USER_BLK(vdev);
Error *err = NULL;
int i, ret;
if (!s->chardev.chr) {
error_setg(errp, "vhost-user-blk: chardev is mandatory");
error_setg(errp, "chardev is mandatory");
return;
}
@ -459,16 +437,16 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
s->num_queues = 1;
}
if (!s->num_queues || s->num_queues > VIRTIO_QUEUE_MAX) {
error_setg(errp, "vhost-user-blk: invalid number of IO queues");
error_setg(errp, "invalid number of IO queues");
return;
}
if (!s->queue_size) {
error_setg(errp, "vhost-user-blk: queue size must be non-zero");
error_setg(errp, "queue size must be non-zero");
return;
}
if (s->queue_size > VIRTQUEUE_MAX_SIZE) {
error_setg(errp, "vhost-user-blk: queue size must not exceed %d",
error_setg(errp, "queue size must not exceed %d",
VIRTQUEUE_MAX_SIZE);
return;
}
@ -490,34 +468,31 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
s->vhost_vqs = g_new0(struct vhost_virtqueue, s->num_queues);
s->connected = false;
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL,
vhost_user_blk_event_realize, NULL, (void *)dev,
NULL, true);
reconnect:
if (qemu_chr_fe_wait_connected(&s->chardev, &err) < 0) {
error_report_err(err);
if (qemu_chr_fe_wait_connected(&s->chardev, errp) < 0) {
goto virtio_err;
}
/* check whether vhost_user_blk_connect() failed or not */
if (!s->connected) {
goto reconnect;
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_report("vhost-user-blk: get block config failed");
goto reconnect;
error_setg(errp, "vhost-user-blk: get block config failed");
goto vhost_err;
}
/* we're fully initialized, now we can operate, so change the handler */
/* we're fully initialized, now we can operate, so add the handler */
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL,
vhost_user_blk_event_oper, NULL, (void *)dev,
vhost_user_blk_event, NULL, (void *)dev,
NULL, true);
return;
vhost_err:
vhost_dev_cleanup(&s->dev);
virtio_err:
g_free(s->vhost_vqs);
s->vhost_vqs = NULL;

View file

@ -1909,6 +1909,11 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque)
return err;
}
}
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);
return -EINVAL;
}
if (virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM) &&
!(virtio_has_feature(dev->protocol_features,

View file

@ -69,6 +69,11 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp)
return;
}
if (has_iommu && !virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) {
error_setg(errp, "iommu_platform=true is not supported by the device");
return;
}
if (klass->device_plugged != NULL) {
klass->device_plugged(qbus->parent, &local_err);
}