From nobody Tue Feb 10 18:54:38 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1553081509269102.32521331012208; Wed, 20 Mar 2019 04:31:49 -0700 (PDT) Received: from localhost ([127.0.0.1]:46453 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h6ZRh-0002KV-6p for importer@patchew.org; Wed, 20 Mar 2019 07:31:45 -0400 Received: from eggs.gnu.org ([209.51.188.92]:49511) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h6ZNp-0007ua-DS for qemu-devel@nongnu.org; Wed, 20 Mar 2019 07:27:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h6ZNo-000412-43 for qemu-devel@nongnu.org; Wed, 20 Mar 2019 07:27:45 -0400 Received: from mail-pg1-x542.google.com ([2607:f8b0:4864:20::542]:38636) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1h6ZNn-0003zv-Mf for qemu-devel@nongnu.org; Wed, 20 Mar 2019 07:27:44 -0400 Received: by mail-pg1-x542.google.com with SMTP id v1so1596110pgi.5 for ; Wed, 20 Mar 2019 04:27:43 -0700 (PDT) Received: from localhost ([116.247.112.152]) by smtp.gmail.com with ESMTPSA id y34sm5347282pgl.35.2019.03.20.04.27.41 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 20 Mar 2019 04:27:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zow+oGvpqEYFuGtHHvCnboKR4dsoTq+1kTv8H8eXYt8=; b=C1sobIZI+9r52NrsoA4LrvdT+DCkjmvj8sUQcohOjcgaOEUjTFNY8wJSSA6W3MQpkr sZjx8xsczxbq8xRoa1NQe2cAzeSjve2v1P76iMYPOo9FE9yaDRvTPH3qbc5pitkgxQhQ XfHRq4Cy5eUgmDtZWQtStswbr5/wnAIMwQpqlTvyY0YYmMf+KMajFVxtW6KHBVJa+/p2 mNxvKYvucv+L7KeQE6QxPHfSMYAM7cV7lxak4AcSmegfHOzumUImXrRMqoR4OkS/0mvi 4tNOS3erW3x6cy2D7MPc366ni+qAs4xw1svh/hRHk2Tx6Ou6PnPKwkgIKNbreoOj8ZV7 XSDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zow+oGvpqEYFuGtHHvCnboKR4dsoTq+1kTv8H8eXYt8=; b=qZbVGLQY5Ly1vbYObmZCP2+YyF0QEGxAdcO+0+KBJHACmLkd/DixO5SBXT3ITP5WMj SAj6hCtUlXiZAYSDl7Tb7C74XtzuZlVH5G1T6TA37vDp+gl0wzRMvCv3ARPQrRJnOy09 V9kYGyDYYvYyFT1Xshtn2NYVzTNzZghBOO5vZvYYn2k2GJEUHcKJXI+XoXDZi4um0C19 9FCT8lVrJyhgh9PPS7I1nO2BNzSp4iArizPXMBGX5lUoSvmzJbHDIIdHYDZAu078IepS QwSpRWmztUGKDQQYBHmnroLUtVg8TdjYuQ4qhY+Hrz/1a0hcds7pNcIbj8MO9pRkSrWd BPeA== X-Gm-Message-State: APjAAAUEifpfBLUi+1RjzUiO6tWiCYY2AWjW3OH4ajhrarXNnpX8DcHp bEnSIVyP1/TiLf5qjC/dN4xr2m+Y X-Google-Smtp-Source: APXvYqyQVaLq4fR8N1m5qDfYh5NTA7tA4xgC251pRAHd9e9zNEJoRXm9LdQ8zoKlBI1nQoJprF6TaA== X-Received: by 2002:a63:e303:: with SMTP id f3mr942451pgh.374.1553081262730; Wed, 20 Mar 2019 04:27:42 -0700 (PDT) From: elohimes@gmail.com X-Google-Original-From: xieyongji@baidu.com To: mst@redhat.com, kwolf@redhat.com, mreitz@redhat.com, stefanha@gmail.com, marcandre.lureau@redhat.com, berrange@redhat.com, jasowang@redhat.com, maxime.coquelin@redhat.com, yury-kotov@yandex-team.ru, wrfsh@yandex-team.ru, changpeng.liu@intel.com Date: Wed, 20 Mar 2019 19:26:45 +0800 Message-Id: <20190320112646.3712-7-xieyongji@baidu.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190320112646.3712-1-xieyongji@baidu.com> References: <20190320112646.3712-1-xieyongji@baidu.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::542 Subject: [Qemu-devel] [PATCH v8 6/7] vhost-user-blk: Add support to reconnect backend X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nixun@baidu.com, qemu-devel@nongnu.org, lilin24@baidu.com, zhangyu31@baidu.com, chaiwen@baidu.com, Xie Yongji Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Xie Yongji Since we now support the message VHOST_USER_GET_INFLIGHT_FD and VHOST_USER_SET_INFLIGHT_FD. The backend is able to restart safely because it can track inflight I/O in shared memory. This patch allows qemu to reconnect the backend after connection closed. Signed-off-by: Xie Yongji Signed-off-by: Ni Xun Signed-off-by: Zhang Yu --- hw/block/vhost-user-blk.c | 159 ++++++++++++++++++++++++----- include/hw/virtio/vhost-user-blk.h | 3 + 2 files changed, 139 insertions(+), 23 deletions(-) diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 6802c19d65..9cb61336a6 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -192,17 +192,27 @@ static void vhost_user_blk_set_status(VirtIODevice *v= dev, uint8_t status) { VHostUserBlk *s =3D VHOST_USER_BLK(vdev); bool should_start =3D vdev->started; + int ret; =20 if (!vdev->vm_running) { should_start =3D false; } =20 + if (!s->connected) { + return; + } + if (s->dev.started =3D=3D should_start) { return; } =20 if (should_start) { - vhost_user_blk_start(vdev); + ret =3D vhost_user_blk_start(vdev); + if (ret < 0) { + error_report("vhost-user-blk: vhost start failed: %s", + strerror(-ret)); + qemu_chr_fe_disconnect(&s->chardev); + } } else { vhost_user_blk_stop(vdev); } @@ -238,12 +248,16 @@ static uint64_t vhost_user_blk_get_features(VirtIODev= ice *vdev, static void vhost_user_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) { VHostUserBlk *s =3D VHOST_USER_BLK(vdev); - int i; + int i, ret; =20 if (!vdev->start_on_kick) { return; } =20 + if (!s->connected) { + return; + } + if (s->dev.started) { return; } @@ -251,7 +265,13 @@ 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(). */ - vhost_user_blk_start(vdev); + ret =3D vhost_user_blk_start(vdev); + if (ret < 0) { + error_report("vhost-user-blk: vhost start failed: %s", + strerror(-ret)); + qemu_chr_fe_disconnect(&s->chardev); + return; + } =20 /* Kick right away to begin processing requests already in vring */ for (i =3D 0; i < s->dev.nvqs; i++) { @@ -271,11 +291,103 @@ static void vhost_user_blk_reset(VirtIODevice *vdev) vhost_dev_free_inflight(s->inflight); } =20 +static int vhost_user_blk_connect(DeviceState *dev) +{ + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + VHostUserBlk *s =3D VHOST_USER_BLK(vdev); + int ret =3D 0; + + if (s->connected) { + return 0; + } + s->connected =3D true; + + s->dev.nvqs =3D s->num_queues; + s->dev.vqs =3D s->vqs; + s->dev.vq_index =3D 0; + s->dev.backend_features =3D 0; + + vhost_dev_set_config_notifier(&s->dev, &blk_ops); + + ret =3D vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USE= R, 0); + if (ret < 0) { + error_report("vhost-user-blk: vhost initialization failed: %s", + strerror(-ret)); + return ret; + } + + /* restore vhost state */ + if (vdev->started) { + ret =3D vhost_user_blk_start(vdev); + if (ret < 0) { + error_report("vhost-user-blk: vhost start failed: %s", + strerror(-ret)); + return ret; + } + } + + return 0; +} + +static void vhost_user_blk_disconnect(DeviceState *dev) +{ + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + VHostUserBlk *s =3D VHOST_USER_BLK(vdev); + + if (!s->connected) { + return; + } + s->connected =3D false; + + if (s->dev.started) { + vhost_user_blk_stop(vdev); + } + + vhost_dev_cleanup(&s->dev); +} + +static gboolean vhost_user_blk_watch(GIOChannel *chan, GIOCondition cond, + void *opaque) +{ + DeviceState *dev =3D opaque; + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + VHostUserBlk *s =3D VHOST_USER_BLK(vdev); + + qemu_chr_fe_disconnect(&s->chardev); + + return true; +} + +static void vhost_user_blk_event(void *opaque, int event) +{ + DeviceState *dev =3D opaque; + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + VHostUserBlk *s =3D VHOST_USER_BLK(vdev); + + switch (event) { + case CHR_EVENT_OPENED: + if (vhost_user_blk_connect(dev) < 0) { + qemu_chr_fe_disconnect(&s->chardev); + return; + } + s->watch =3D qemu_chr_fe_add_watch(&s->chardev, G_IO_HUP, + vhost_user_blk_watch, dev); + break; + case CHR_EVENT_CLOSED: + vhost_user_blk_disconnect(dev); + if (s->watch) { + g_source_remove(s->watch); + s->watch =3D 0; + } + break; + } +} + static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); VHostUserBlk *s =3D VHOST_USER_BLK(vdev); - struct vhost_virtqueue *vqs =3D NULL; + Error *err =3D NULL; int i, ret; =20 if (!s->chardev.chr) { @@ -306,27 +418,29 @@ static void vhost_user_blk_device_realize(DeviceState= *dev, Error **errp) } =20 s->inflight =3D g_new0(struct vhost_inflight, 1); + s->vqs =3D g_new(struct vhost_virtqueue, s->num_queues); + s->watch =3D 0; + s->connected =3D false; =20 - s->dev.nvqs =3D s->num_queues; - s->dev.vqs =3D g_new(struct vhost_virtqueue, s->dev.nvqs); - s->dev.vq_index =3D 0; - s->dev.backend_features =3D 0; - vqs =3D s->dev.vqs; - - vhost_dev_set_config_notifier(&s->dev, &blk_ops); + qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_even= t, + NULL, (void *)dev, NULL, true); =20 - ret =3D vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USE= R, 0); - if (ret < 0) { - error_setg(errp, "vhost-user-blk: vhost initialization failed: %s", - strerror(-ret)); +reconnect: + if (qemu_chr_fe_wait_connected(&s->chardev, &err) < 0) { + error_report_err(err); goto virtio_err; } =20 + /* check whether vhost_user_blk_connect() failed or not */ + if (!s->connected) { + goto reconnect; + } + ret =3D vhost_dev_get_config(&s->dev, (uint8_t *)&s->blkcfg, - sizeof(struct virtio_blk_config)); + sizeof(struct virtio_blk_config)); if (ret < 0) { - error_setg(errp, "vhost-user-blk: get block config failed"); - goto vhost_err; + error_report("vhost-user-blk: get block config failed"); + goto reconnect; } =20 if (s->blkcfg.num_queues !=3D s->num_queues) { @@ -335,10 +449,8 @@ static void vhost_user_blk_device_realize(DeviceState = *dev, Error **errp) =20 return; =20 -vhost_err: - vhost_dev_cleanup(&s->dev); virtio_err: - g_free(vqs); + g_free(s->vqs); g_free(s->inflight); virtio_cleanup(vdev); vhost_user_cleanup(&s->vhost_user); @@ -348,12 +460,13 @@ static void vhost_user_blk_device_unrealize(DeviceSta= te *dev, Error **errp) { VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); VHostUserBlk *s =3D VHOST_USER_BLK(dev); - struct vhost_virtqueue *vqs =3D s->dev.vqs; =20 virtio_set_status(vdev, 0); + qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, NULL, + NULL, NULL, NULL, false); vhost_dev_cleanup(&s->dev); vhost_dev_free_inflight(s->inflight); - g_free(vqs); + g_free(s->vqs); g_free(s->inflight); virtio_cleanup(vdev); vhost_user_cleanup(&s->vhost_user); diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-u= ser-blk.h index 68634bee61..51457fb857 100644 --- a/include/hw/virtio/vhost-user-blk.h +++ b/include/hw/virtio/vhost-user-blk.h @@ -38,6 +38,9 @@ typedef struct VHostUserBlk { struct vhost_dev dev; struct vhost_inflight *inflight; VhostUserState vhost_user; + struct vhost_virtqueue *vqs; + guint watch; + bool connected; } VHostUserBlk; =20 #endif --=20 2.17.1