vhost-user-blk-server: notify client about disk resize

Currently block_resize qmp command is simply ignored by vhost-user-blk
export. So, the block-node is successfully resized, but virtio config
is unchanged and guest doesn't see that disk is resized.

Let's handle the resize by modifying the config and notifying the guest
appropriately.

After this comment, lsblk in linux guest with attached
vhost-user-blk-pci device shows new size immediately after block_resize
QMP command on vhost-user exported block node.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Message-Id: <20230321201323.3695923-1-vsementsov@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Vladimir Sementsov-Ogievskiy 2023-03-21 23:13:23 +03:00 committed by Michael S. Tsirkin
parent b93fe7f2ca
commit ca858a5fe9
3 changed files with 36 additions and 0 deletions

View File

@ -10,6 +10,7 @@
* later. See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "block/block.h"
#include "subprojects/libvhost-user/libvhost-user.h" /* only for the type definitions */
#include "standard-headers/linux/virtio_blk.h"
@ -251,6 +252,27 @@ static void vu_blk_exp_request_shutdown(BlockExport *exp)
vhost_user_server_stop(&vexp->vu_server);
}
static void vu_blk_exp_resize(void *opaque)
{
VuBlkExport *vexp = opaque;
BlockDriverState *bs = blk_bs(vexp->handler.blk);
int64_t new_size = bdrv_getlength(bs);
if (new_size < 0) {
error_printf("Failed to get length of block node '%s'",
bdrv_get_node_name(bs));
return;
}
vexp->blkcfg.capacity = cpu_to_le64(new_size >> VIRTIO_BLK_SECTOR_BITS);
vu_config_change_msg(&vexp->vu_server.vu_dev);
}
static const BlockDevOps vu_blk_dev_ops = {
.resize_cb = vu_blk_exp_resize,
};
static int vu_blk_exp_create(BlockExport *exp, BlockExportOptions *opts,
Error **errp)
{
@ -292,6 +314,8 @@ static int vu_blk_exp_create(BlockExport *exp, BlockExportOptions *opts,
blk_add_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach,
vexp);
blk_set_dev_ops(exp->blk, &vu_blk_dev_ops, vexp);
if (!vhost_user_server_start(&vexp->vu_server, vu_opts->addr, exp->ctx,
num_queues, &vu_blk_iface, errp)) {
blk_remove_aio_context_notifier(exp->blk, blk_aio_attached,

View File

@ -2455,6 +2455,16 @@ void vu_queue_notify_sync(VuDev *dev, VuVirtq *vq)
_vu_queue_notify(dev, vq, true);
}
void vu_config_change_msg(VuDev *dev)
{
VhostUserMsg vmsg = {
.request = VHOST_USER_BACKEND_CONFIG_CHANGE_MSG,
.flags = VHOST_USER_VERSION,
};
vu_message_write(dev, dev->slave_fd, &vmsg);
}
static inline void
vring_used_flags_set_bit(VuVirtq *vq, int mask)
{

View File

@ -585,6 +585,8 @@ bool vu_queue_empty(VuDev *dev, VuVirtq *vq);
*/
void vu_queue_notify(VuDev *dev, VuVirtq *vq);
void vu_config_change_msg(VuDev *dev);
/**
* vu_queue_notify_sync:
* @dev: a VuDev context