[Devel] [PATCH RH9 v3 02/10] drivers/vhost: use array to store workers
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Thu Oct 13 16:06:34 MSK 2022
On 10.10.2022 17:56, Andrey Zhadchenko wrote:
> We want to support several vhost workers. The first step is to
> rework vhost to use array of workers rather than single pointer.
> Update creation and cleanup routines.
>
> https://jira.sw.ru/browse/PSBM-139414
> Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
> ---
> v3:
> set vq->worker to NULL in vhost_vq_reset()
vhost_virtqueue->worker field is added in [PATCH RH9 v3 07/10]
drivers/vhost: assign workers to virtqueues, so at this point you don't
yet have it, this would break compilation on this patch
=> please re-check compilation on each patch
>
> drivers/vhost/vhost.c | 76 +++++++++++++++++++++++++++++++------------
> drivers/vhost/vhost.h | 10 +++++-
> 2 files changed, 64 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index a0bfc77c6a43..321967322285 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -231,11 +231,24 @@ void vhost_poll_stop(struct vhost_poll *poll)
> }
> EXPORT_SYMBOL_GPL(vhost_poll_stop);
>
> +static void vhost_work_queue_at_worker(struct vhost_worker *w,
> + struct vhost_work *work)
> +{
> + if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) {
> + /* We can only add the work to the list after we're
> + * sure it was not in the list.
> + * test_and_set_bit() implies a memory barrier.
> + */
> + llist_add(&work->node, &w->work_list);
> + wake_up_process(w->worker);
> + }
> +}
> +
> void vhost_work_dev_flush(struct vhost_dev *dev)
> {
> struct vhost_flush_struct flush;
>
> - if (dev->worker) {
> + if (dev->workers[0].worker) {
> init_completion(&flush.wait_event);
> vhost_work_init(&flush.work, vhost_flush_work);
>
> @@ -255,17 +268,12 @@ EXPORT_SYMBOL_GPL(vhost_poll_flush);
>
> void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
> {
> - if (!dev->worker)
> + struct vhost_worker *w = &dev->workers[0];
> +
> + if (!w->worker)
> return;
>
> - if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) {
> - /* We can only add the work to the list after we're
> - * sure it was not in the list.
> - * test_and_set_bit() implies a memory barrier.
> - */
> - llist_add(&work->node, &dev->work_list);
> - wake_up_process(dev->worker);
> - }
> + vhost_work_queue_at_worker(w, work);
> }
> EXPORT_SYMBOL_GPL(vhost_work_queue);
>
> @@ -339,11 +347,32 @@ static void vhost_vq_reset(struct vhost_dev *dev,
> vq->iotlb = NULL;
> vhost_vring_call_reset(&vq->call_ctx);
> __vhost_vq_meta_reset(vq);
> + vq->worker = NULL;
> +}
> +
> +static void vhost_worker_reset(struct vhost_worker *w)
> +{
> + init_llist_head(&w->work_list);
> + w->worker = NULL;
> +}
> +
> +void vhost_cleanup_workers(struct vhost_dev *dev)
> +{
> + int i;
> +
> + for (i = 0; i < dev->nworkers; ++i) {
> + WARN_ON(!llist_empty(&dev->workers[i].work_list));
> + kthread_stop(dev->workers[i].worker);
> + vhost_worker_reset(&dev->workers[i]);
> + }
> +
> + dev->nworkers = 0;
> }
>
> static int vhost_worker(void *data)
> {
> - struct vhost_dev *dev = data;
> + struct vhost_worker *w = data;
> + struct vhost_dev *dev = w->dev;
> struct vhost_work *work, *work_next;
> struct llist_node *node;
>
> @@ -358,7 +387,7 @@ static int vhost_worker(void *data)
> break;
> }
>
> - node = llist_del_all(&dev->work_list);
> + node = llist_del_all(&w->work_list);
> if (!node)
> schedule();
>
> @@ -481,7 +510,6 @@ void vhost_dev_init(struct vhost_dev *dev,
> dev->umem = NULL;
> dev->iotlb = NULL;
> dev->mm = NULL;
> - dev->worker = NULL;
> dev->iov_limit = iov_limit;
> dev->weight = weight;
> dev->byte_weight = byte_weight;
> @@ -493,6 +521,11 @@ void vhost_dev_init(struct vhost_dev *dev,
> INIT_LIST_HEAD(&dev->pending_list);
> spin_lock_init(&dev->iotlb_lock);
>
> + dev->nworkers = 0;
> + for (i = 0; i < VHOST_MAX_WORKERS; ++i) {
> + dev->workers[i].dev = dev;
> + vhost_worker_reset(&dev->workers[i]);
> + }
>
> for (i = 0; i < dev->nvqs; ++i) {
> vq = dev->vqs[i];
> @@ -602,7 +635,8 @@ long vhost_dev_set_owner(struct vhost_dev *dev)
> goto err_worker;
> }
>
> - dev->worker = worker;
> + dev->workers[0].worker = worker;
> + dev->nworkers = 1;
> wake_up_process(worker); /* avoid contributing to loadavg */
>
> err = vhost_attach_cgroups(dev);
> @@ -616,9 +650,10 @@ long vhost_dev_set_owner(struct vhost_dev *dev)
>
> return 0;
> err_cgroup:
> - if (dev->worker) {
> - kthread_stop(dev->worker);
> - dev->worker = NULL;
> + dev->nworkers = 0;
> + if (dev->workers[0].worker) {
> + kthread_stop(dev->workers[0].worker);
> + dev->workers[0].worker = NULL;
> }
> err_worker:
> vhost_detach_mm(dev);
> @@ -701,6 +736,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
> eventfd_ctx_put(dev->vqs[i]->call_ctx.ctx);
> vhost_vq_reset(dev, dev->vqs[i]);
> }
> +
> vhost_dev_free_iovecs(dev);
> if (dev->log_ctx)
> eventfd_ctx_put(dev->log_ctx);
> @@ -712,10 +748,8 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
> dev->iotlb = NULL;
> vhost_clear_msg(dev);
> wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM);
> - WARN_ON(!llist_empty(&dev->work_list));
> - if (dev->worker) {
> - kthread_stop(dev->worker);
> - dev->worker = NULL;
> + if (dev->use_worker) {
> + vhost_cleanup_workers(dev);
> dev->kcov_handle = 0;
> }
> vhost_detach_mm(dev);
> diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
> index 638bb640d6b4..634ea828cbba 100644
> --- a/drivers/vhost/vhost.h
> +++ b/drivers/vhost/vhost.h
> @@ -25,6 +25,13 @@ struct vhost_work {
> unsigned long flags;
> };
>
> +#define VHOST_MAX_WORKERS 4
> +struct vhost_worker {
> + struct task_struct *worker;
> + struct llist_head work_list;
> + struct vhost_dev *dev;
> +};
> +
> /* Poll a file (eventfd or socket) */
> /* Note: there's nothing vhost specific about this structure. */
> struct vhost_poll {
> @@ -149,7 +156,8 @@ struct vhost_dev {
> int nvqs;
> struct eventfd_ctx *log_ctx;
> struct llist_head work_list;
> - struct task_struct *worker;
> + struct vhost_worker workers[VHOST_MAX_WORKERS];
> + int nworkers;
> struct vhost_iotlb *umem;
> struct vhost_iotlb *iotlb;
> spinlock_t iotlb_lock;
--
Best regards, Tikhomirov Pavel
Software Developer, Virtuozzo.
More information about the Devel
mailing list