在 2022/9/12 01:22, Kangjie Xu 写道:
> Introduce vhost_net_virtqueue_restart(), which can restart the
> specific virtqueue when the vhost net started running before.
> If it fails to restart the virtqueue, the device will be stopped.
>
> Here we do not reuse vhost_net_start_one() or vhost_dev_start()
> because they work at queue pair level. The mem table and features
> do not change, so we can call the vhost_virtqueue_start() to
> restart a specific queue.
>
> This patch only considers the case of vhost-kernel, when
> NetClientDriver is NET_CLIENT_DRIVER_TAP.
>
> Signed-off-by: Kangjie Xu <kangjie.xu@linux.alibaba.com>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
> hw/net/vhost_net.c | 52 +++++++++++++++++++++++++++++++++++++++++
> include/net/vhost_net.h | 2 ++
> 2 files changed, 54 insertions(+)
>
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 8beecb4d22..1059aa45b4 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -556,3 +556,55 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
> net->dev.vqs + idx,
> net->dev.vq_index + idx);
> }
> +
> +int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
> + int vq_index)
> +{
> + VHostNetState *net = get_vhost_net(nc->peer);
> + const VhostOps *vhost_ops = net->dev.vhost_ops;
> + struct vhost_vring_file file = { };
> + int idx, r;
> +
> + if (!net->dev.started) {
> + return -ENOTSUP;
> + }
-EBUSY?
> +
> + /* should only be called after backend is connected */
> + assert(vhost_ops);
> +
> + idx = vhost_ops->vhost_get_vq_index(&net->dev, vq_index);
> +
> + r = vhost_virtqueue_start(&net->dev,
> + vdev,
> + net->dev.vqs + idx,
> + net->dev.vq_index + idx);
> + if (r < 0) {
> + goto err_start;
> + }
> +
> + if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
> + file.index = idx;
> + file.fd = net->backend;
> + r = vhost_net_set_backend(&net->dev, &file);
> + if (r < 0) {
> + r = -errno;
> + goto err_start;
> + }
> + }
> +
> + return 0;
> +
> +err_start:
> + error_report("Error when restarting the queue.");
> +
> + if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
> + file.fd = -1;
Let's try reuse VHOST_FILE_UNBIND.
Other looks good.
Thanks
> + file.index = idx;
> + int r = vhost_net_set_backend(&net->dev, &file);
> + assert(r >= 0);
> + }
> +
> + vhost_dev_stop(&net->dev, vdev);
> +
> + return r;
> +}
> diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
> index 85d85a4957..40b9a40074 100644
> --- a/include/net/vhost_net.h
> +++ b/include/net/vhost_net.h
> @@ -50,4 +50,6 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
>
> void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
> int vq_index);
> +int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
> + int vq_index);
> #endif