From: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
To: svt-core@virtuozzo.com
Cc: den@openvz.org, andrey.drobyshev@virtuozzo.com
Subject: [QEMU HCI-8.0 PATCH 2/5] vhost-blk: change backend setup
Date: Thu, 3 Sep 2026 15:32:01 +0300 [thread overview]
Message-ID: <20260903123204.24035-3-andrey.zhadchenko@virtuozzo.com> (raw)
In-Reply-To: <20260903123204.24035-1-andrey.zhadchenko@virtuozzo.com>
Previously we used very ugly and incapsulation-breaking assignment
fd = blk_bs(s->conf.conf.blk)->file->bs->opaque;
It is wrong in a many ways, so let's rework this.
Patch changes default `drive` to new `devpath` option so device fd
is managed by vhost-blk itself. Unfortunately this way we need a
bit more preparational work: finding out disk length, block size,
etc. Don't be too broad and just do the minimal and set reasonable
default values. Validate with previously introduced
blkconf_validate_blocksizes().
Also we lose resize, as this is tied to the block node, which is
now have no place in the setup. We will add this in the next
patches as well as RO mode.
https://virtuozzo.atlassian.net/browse/VSTOR-143437
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
---
hw/block/vhost-blk.c | 144 ++++++++++++++++++++++------------
include/hw/virtio/vhost-blk.h | 5 +-
2 files changed, 95 insertions(+), 54 deletions(-)
diff --git a/hw/block/vhost-blk.c b/hw/block/vhost-blk.c
index c52851fcf8..a3e0010982 100644
--- a/hw/block/vhost-blk.c
+++ b/hw/block/vhost-blk.c
@@ -24,23 +24,17 @@
#include "system/system.h"
#include "linux-headers/linux/vhost.h"
#include <sys/ioctl.h>
-#include <linux/fs.h>
-#include "include/block/block_int-common.h"
#include "system/runstate.h"
static int vhost_blk_start(VirtIODevice *vdev)
{
VHostBlk *s = VHOST_BLK(vdev);
struct vhost_vring_file backend;
- int ret, i, nworkers, *fd;
+ int ret, i, nworkers;
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
char serial[VIRTIO_BLK_ID_BYTES] = {0};
- bdrv_graph_rdlock_main_loop();
- fd = blk_bs(s->conf.conf.blk)->file->bs->opaque;
- bdrv_graph_rdunlock_main_loop();
-
if (!k->set_guest_notifiers) {
error_report("vhost-blk: binding does not support guest notifiers");
return -ENOSYS;
@@ -92,7 +86,7 @@ static int vhost_blk_start(VirtIODevice *vdev)
memset(&backend, 0, sizeof(backend));
backend.index = 0;
- backend.fd = *fd;
+ backend.fd = s->backend_fd;
if (ioctl(s->vhostfd, VHOST_BLK_SET_BACKEND, &backend)) {
error_report("vhost-blk: unable to set backend");
ret = -errno;
@@ -208,29 +202,79 @@ static void vhost_blk_vm_state(void *opaque, bool running, RunState state)
}
}
-static void vhost_blk_resize_cb(void *opaque)
+static int vhost_blk_update_size(VHostBlk *s, Error **errp)
{
- VirtIODevice *vdev = opaque;
+ BlockConf *conf = &s->conf.conf;
+ off_t length;
+ bool changed;
+
+ length = lseek(s->backend_fd, 0, SEEK_END);
+ if (length < 0) {
+ int error = errno;
+
+ error_setg_errno(errp, error,
+ "vhost-blk: unable to determine size of '%s'",
+ s->conf.devpath);
+ return -error;
+ }
- assert(qemu_get_current_aio_context() == qemu_get_aio_context());
- virtio_notify_config(vdev);
+ changed = s->length != length;
+ s->length = length;
+ conf->heads = 16;
+ conf->secs = 63;
+ conf->cyls = s->length / BDRV_SECTOR_SIZE /
+ (conf->heads * conf->secs);
+ conf->cyls = MIN(MAX(conf->cyls, 2U), 16383U);
+
+ return changed;
}
-static void vhost_blk_resize(void *opaque)
+static bool vhost_blk_open_backend(VHostBlk *s, Error **errp)
{
- VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
+ BlockConf *conf = &s->conf.conf;
+ struct stat st;
- /*
- * virtio_notify_config() needs to acquire the global mutex,
- * so it can't be called from an iothread. Instead, schedule
- * it to be run in the main context BH.
- */
- aio_bh_schedule_oneshot(qemu_get_aio_context(), vhost_blk_resize_cb, vdev);
-}
+ s->backend_fd = qemu_open(s->conf.devpath, O_RDWR, errp);
+ if (s->backend_fd < 0) {
+ error_prepend(errp, "vhost-blk: unable to open backend: ");
+ return false;
+ }
-static const BlockDevOps vhost_blk_block_ops = {
- .resize_cb = vhost_blk_resize,
-};
+ if (fstat(s->backend_fd, &st) < 0) {
+ error_setg_errno(errp, errno, "vhost-blk: unable to stat '%s'",
+ s->conf.devpath);
+ goto fail;
+ }
+
+ if (!S_ISBLK(st.st_mode)) {
+ error_setg(errp, "vhost-blk: '%s' is not a block device",
+ s->conf.devpath);
+ goto fail;
+ }
+
+ if (vhost_blk_update_size(s, errp) < 0) {
+ goto fail;
+ }
+
+ if (!conf->logical_block_size) {
+ conf->logical_block_size = BDRV_SECTOR_SIZE;
+ }
+
+ if (!conf->physical_block_size) {
+ conf->physical_block_size = BDRV_SECTOR_SIZE;
+ }
+
+ if (!blkconf_validate_blocksizes(conf, errp)) {
+ goto fail;
+ }
+
+ return true;
+
+fail:
+ qemu_close(s->backend_fd);
+ s->backend_fd = -1;
+ return false;
+}
static void vhost_blk_device_realize(DeviceState *dev, Error **errp)
{
@@ -239,13 +283,8 @@ static void vhost_blk_device_realize(DeviceState *dev, Error **errp)
VhostBlkConf *conf = &s->conf;
int i, ret;
- if (!conf->conf.blk) {
- error_setg(errp, "vhost-blk: drive property not set");
- return;
- }
-
- if (!blk_is_inserted(conf->conf.blk)) {
- error_setg(errp, "vhost-blk: device needs media, but drive is empty");
+ if (!conf->devpath) {
+ error_setg(errp, "vhost-blk: devpath property must be set");
return;
}
@@ -273,17 +312,7 @@ static void vhost_blk_device_realize(DeviceState *dev, Error **errp)
return;
}
- if (!blkconf_apply_backend_options(&conf->conf,
- !blk_supports_write_perm(conf->conf.blk),
- true, errp)) {
- return;
- }
-
- if (!blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, errp)) {
- return;
- }
-
- if (!blkconf_blocksizes(&conf->conf, errp)) {
+ if (!vhost_blk_open_backend(s, errp)) {
return;
}
@@ -311,13 +340,13 @@ static void vhost_blk_device_realize(DeviceState *dev, Error **errp)
goto cleanup;
}
- blk_set_dev_ops(s->conf.conf.blk, &vhost_blk_block_ops, s);
-
ret = vhost_dev_init(&s->dev, (void *)((size_t)s->vhostfd),
VHOST_BACKEND_TYPE_KERNEL, 0, NULL);
if (ret < 0) {
error_setg(errp, "vhost-blk: vhost initialization failed: %s",
strerror(-ret));
+ /* vhost_dev_init() closes vhostfd on failure */
+ s->vhostfd = -1;
goto cleanup;
}
@@ -328,7 +357,14 @@ cleanup:
qemu_del_vm_change_state_handler(s->mighand);
}
g_free(s->dev.vqs);
- close(s->vhostfd);
+ if (s->vhostfd >= 0) {
+ close(s->vhostfd);
+ s->vhostfd = -1;
+ }
+ if (s->backend_fd >= 0) {
+ qemu_close(s->backend_fd);
+ s->backend_fd = -1;
+ }
for (i = 0; i < conf->num_queues; i++) {
virtio_del_queue(vdev, i);
}
@@ -344,6 +380,10 @@ static void vhost_blk_device_unrealize(DeviceState *dev)
qemu_del_vm_change_state_handler(s->mighand);
vhost_blk_set_status(vdev, 0);
vhost_dev_cleanup(&s->dev);
+ if (s->backend_fd >= 0) {
+ qemu_close(s->backend_fd);
+ s->backend_fd = -1;
+ }
g_free(s->dev.vqs);
virtio_cleanup(vdev);
}
@@ -376,10 +416,6 @@ static uint64_t vhost_blk_get_features(VirtIODevice *vdev,
virtio_add_feature(&features, VIRTIO_F_VERSION_1);
- if (!blk_is_writable(s->conf.conf.blk)) {
- virtio_add_feature(&features, VIRTIO_BLK_F_RO);
- }
-
if (s->conf.num_queues > 1) {
virtio_add_feature(&features, VIRTIO_BLK_F_MQ);
}
@@ -398,7 +434,9 @@ static void vhost_blk_update_config(VirtIODevice *vdev, uint8_t *config)
int64_t length;
int blk_size = conf->logical_block_size;
- blk_get_geometry(s->conf.conf.blk, &capacity);
+ length = s->length;
+ capacity = length / BDRV_SECTOR_SIZE;
+
memset(&blkcfg, 0, sizeof(blkcfg));
virtio_stq_p(vdev, &blkcfg.capacity, capacity);
virtio_stl_p(vdev, &blkcfg.seg_max, s->conf.queue_size - 2);
@@ -406,7 +444,6 @@ static void vhost_blk_update_config(VirtIODevice *vdev, uint8_t *config)
virtio_stl_p(vdev, &blkcfg.blk_size, blk_size);
blkcfg.geometry.heads = conf->heads;
- length = blk_getlength(s->conf.conf.blk);
if (length > 0 && length / conf->heads / conf->secs % blk_size) {
unsigned short mask;
@@ -425,7 +462,8 @@ static void vhost_blk_update_config(VirtIODevice *vdev, uint8_t *config)
}
static const Property vhost_blk_properties[] = {
- DEFINE_BLOCK_PROPERTIES(VHostBlk, conf.conf),
+ DEFINE_BLOCK_PROPERTIES_BASE(VHostBlk, conf.conf),
+ DEFINE_PROP_STRING("devpath", VHostBlk, conf.devpath),
DEFINE_PROP_UINT16("num-queues", VHostBlk, conf.num_queues,
VHOST_BLK_AUTO_NUM_QUEUES),
DEFINE_PROP_UINT16("queue-size", VHostBlk, conf.queue_size, 256),
@@ -470,6 +508,8 @@ static void vhost_blk_instance_init(Object *obj)
{
VHostBlk *s = VHOST_BLK(obj);
+ s->vhostfd = -1;
+ s->backend_fd = -1;
device_add_bootindex_property(obj, &s->conf.conf.bootindex,
"bootindex", "/disk@0,0",
DEVICE(obj));
diff --git a/include/hw/virtio/vhost-blk.h b/include/hw/virtio/vhost-blk.h
index 0c7e212595..c194b421d9 100644
--- a/include/hw/virtio/vhost-blk.h
+++ b/include/hw/virtio/vhost-blk.h
@@ -14,7 +14,6 @@
#include "standard-headers/linux/virtio_blk.h"
#include "hw/block/block.h"
#include "hw/virtio/vhost.h"
-#include "system/block-backend.h"
#define TYPE_VHOST_BLK "vhost-blk"
#define VHOST_BLK(obj) \
@@ -25,6 +24,7 @@
typedef struct VhostBlkConf {
BlockConf conf;
+ char *devpath;
uint16_t num_queues;
uint16_t queue_size;
uint16_t num_threads;
@@ -37,10 +37,11 @@ typedef struct VHostBlk {
VMChangeStateEntry *mighand;
uint64_t host_features;
uint64_t decided_features;
- struct virtio_blk_config blkcfg;
int vhostfd;
+ int backend_fd;
struct vhost_dev dev;
bool vhost_started;
+ uint64_t length;
} VHostBlk;
#endif
--
2.43.5
next prev parent reply other threads:[~2026-09-03 12:35 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 12:31 [QEMU HCI-8.0 PATCH 0/5] vhost-blk " Andrey Zhadchenko
2026-09-03 12:32 ` [QEMU HCI-8.0 PATCH 1/5] blk: factor out validation Andrey Zhadchenko
2026-09-03 14:56 ` Andrey Drobyshev
2026-09-03 12:32 ` Andrey Zhadchenko [this message]
2026-09-03 14:56 ` [QEMU HCI-8.0 PATCH 2/5] vhost-blk: change backend setup Andrey Drobyshev
2026-09-03 15:27 ` Andrey Zhadchenko
2026-09-03 15:34 ` Andrey Drobyshev
2026-09-03 12:32 ` [QEMU HCI-8.0 PATCH 3/5] vhost-blk: add read-only flag Andrey Zhadchenko
2026-09-03 14:56 ` Andrey Drobyshev
2026-09-03 12:32 ` [QEMU HCI-8.0 PATCH 4/5] vhost-blk: watch the device for resize events Andrey Zhadchenko
2026-09-03 14:56 ` Andrey Drobyshev
2026-09-03 15:30 ` Andrey Zhadchenko
2026-09-03 15:45 ` Andrey Drobyshev
2026-09-03 15:50 ` Andrey Zhadchenko
2026-09-03 12:32 ` [QEMU HCI-8.0 PATCH 5/5] vhost-blk: filter uevents in the kernel Andrey Zhadchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260903123204.24035-3-andrey.zhadchenko@virtuozzo.com \
--to=andrey.zhadchenko@virtuozzo.com \
--cc=andrey.drobyshev@virtuozzo.com \
--cc=den@openvz.org \
--cc=svt-core@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox