Virtuozzo QEMU development (svt-core@virtuozzo.com)
 help / color / mirror / Atom feed
From: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
To: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>,
	andrey.zhadchenko@virtuozzo.com
Cc: svt-core@virtuozzo.com
Subject: Re: [PATCH hci-8.1 v2 1/2] vhost-blk: create kernel threads with the mainstream worker ioctls
Date: Wed, 28 Oct 2026 12:48:50 +0100	[thread overview]
Message-ID: <6e8b3fa4-b100-4044-ba32-67087f9d970d@virtuozzo.com> (raw)
In-Reply-To: <1b58bb6c-b384-4925-bdfa-a2021c59a2bd@virtuozzo.com>

> The overall logic is fine, but I'd like patch to be simplified.
>
> First, there're dedicated vhost_ops->vhost_new_worker() and
> vhost_ops->vhost_attach_vring_worker() calls.  We should reuse them.
> For consistency, let's add another patch "vhost-backend: add
> vhost_set_fork_from_owner op".  Smth like:
>
>>    /* hw/virtio/vhost-backend.c */
>>    static int vhost_kernel_set_fork_from_owner(struct vhost_dev *dev,
>>                                                uint8_t fork_owner)
>>    {
>>        return vhost_kernel_call(dev, VHOST_SET_FORK_FROM_OWNER, &fork_owner);
>>    }
Done.
> Other issues (by Claude):
>
> 1. Dead fallback in vhost_blk_set_workers(). The ENOTTY && i == 1 branch
> handles a kernel that has VHOST_SET_FORK_FROM_OWNER (6.17 / vz10) but
> not VHOST_NEW_WORKER (6.4) — no such kernel exists. Once the fork-mode
> ioctl succeeded, a worker-ioctl failure is a real error.  Drop, do a
> single fallback point in start().
The fallback is not dead. VHOST_SET_FORK_FROM_OWNER is in our
6.12 kernel as a RHEL 10 backport. The worker ioctls are generic,
but each vhost driver has to route them to vhost_worker_ioctl(),
and vhost-blk only does that with "drivers/vhost/blk: add support
for worker ioctls" (VSTOR-107537), which is not merged yet.
> 2. Fork-mode block in vhost_blk_start() is hard to read. A declaration
> inside the if, the ENOTTY test nested under 'ret != -ENOTTY', the
> 'nworkers = 1' fall-through at the bottom. Switch to flat three-way if
> (ret == -ENOTTY) … else if (ret < 0) … at the call site, ioctl plumbing
> in the backend.
Done.
> 3. Redundant clamp. MIN(nworkers, VHOST_BLK_MAX_QUEUES) is already
> guaranteed by nworkers ≤ nvqs ≤ VHOST_BLK_MAX_QUEUES (realize, :666); a
> clamp hides an invariant. Switch to assert(nworkers <= ARRAY_SIZE(ids)).
Done, switched to the assert. To make it hold, I added a patch that rejects
num-queues above VHOST_BLK_MAX_QUEUES at realize: before, only the
auto value was capped there.
> 4. memset() + field stores for two structs per iteration. Switch to
> designated initializers, and the two loops merged into one: thread w is
> created by its first user vq (i < nworkers), then attached — same ioctl
> count, one error path per ioctl, loop body reads as "which thread,
> create if first, attach".
Done.  The structs use designated initializers, and the two loops
are merged into one: a thread is created by its first vq, then attached.
> 5. s->dev. repeated throughout. Use struct vhost_dev *hdev = &s->dev;
> once, as vhost-scsi does; vhost_blk_set_workers() takes hdev and no
> longer needs VHostBlk.
Done. vhost_blk_start() uses hdev throughout, and vhost_blk_set_workers()
takes hdev instead of VHostBlk.
> 6. Commit message nits (1/2). "The kernel is dropping it" needs the
> kernel change/ticket; say that VHOST_NEW_WORKER returns -EFAULT (not
> ENOTTY) in kthread mode, which is why the mode switch — not the worker
> ioctl — is the capability probe; "default worker being the first one"
> belongs in the code comment, where it already is.
>
> Here's what the changed version might look like:
>
>> /*
>>     * Spread the virtqueues round-robin over nworkers kernel threads. Thread 0
>>     * is the default worker VHOST_SET_OWNER created; vq 0 and every nworkers-th
>>     * vq after it stay on it.
>>     */
>>    static int vhost_blk_set_workers(struct vhost_dev *hdev, int nworkers)
>>    {
>>        uint32_t ids[VHOST_BLK_MAX_QUEUES];     /* ids[0]: default worker, unused */
>>        int i, ret;
>>
>>        assert(nworkers <= ARRAY_SIZE(ids));
>>
>>        for (i = 1; i < hdev->nvqs; i++) {
>>            int w = i % nworkers;
>>            struct vhost_vring_worker vq_worker = { .index = i };
>>
>>            if (w == 0) {
>>                continue;
>>            }
>>
>>            /* vq i < nworkers is the first user of thread i: create it here */
>>            if (i < nworkers) {
>>                struct vhost_worker_state worker = { };
>>
>>                ret = hdev->vhost_ops->vhost_new_worker(hdev, &worker);
>>                if (ret < 0) {
>>                    error_report("vhost-blk: unable to create kernel thread: %s",
>>                                 strerror(-ret));
>>                    return ret;
>>                }
>>                ids[w] = worker.worker_id;
>>            }
>>
>>            vq_worker.worker_id = ids[w];
>>            ret = hdev->vhost_ops->vhost_attach_vring_worker(hdev, &vq_worker);
>>            if (ret < 0) {
>>                error_report("vhost-blk: unable to attach kernel thread to "
>>                             "queue %d: %s", i, strerror(-ret));
>>                return ret;
>>            }
>>        }
>>
>>        return 0;
>>    }
>>
>>    static int vhost_blk_start(VirtIODevice *vdev)
>>    {
>>        VHostBlk *s = VHOST_BLK(vdev);
>>        struct vhost_dev *hdev = &s->dev;
>>        ...
>>        int ret, i, nworkers;
>>        ...
>>        if (s->vhost_started) {
>>            return 0;
>>        }
>>
>>        nworkers = MIN(s->conf.num_threads, hdev->nvqs);
>>        if (nworkers > 1) {
>>            /*
>>             * VHOST_NEW_WORKER needs vhost_task mode; our kernel defaults to
>>             * kthreads and VHOST_RESET_OWNER brings that default back, so ask
>>             * on every start. Must precede VHOST_SET_OWNER.
>>             */
>>            ret = hdev->vhost_ops->vhost_set_fork_from_owner(hdev,
>>                                                             VHOST_FORK_OWNER_TASK);
>>            if (ret == -ENOTTY) {
>>                warn_report_once("vhost-blk: kernel does not support vhost tasks, "
>>                                 "using a single kernel thread");
>>                nworkers = 1;
>>            } else if (ret < 0) {
>>                error_report("vhost-blk: unable to set vhost task mode: %s",
>>                             strerror(-ret));
>>                return ret;
>>            }
>>        }
>>
>>        if (ioctl(s->vhostfd, VHOST_SET_OWNER, NULL)) {
>>            error_report("vhost-blk: unable to set owner");
>>            return -ENOSYS;
>>        }
>>
>>        if (nworkers > 1) {
>>            ret = vhost_blk_set_workers(hdev, nworkers);
>>            if (ret < 0) {
>>                return ret;
>>            }
>>        }
>>
>>        if (s->conf.serial) {
>>        ...
Done.

  reply	other threads:[~2026-10-28 11:48 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-27 12:47 [PATCH hci-8.1 v2 0/2] vhost-blk: switch from VHOST_SET_NWORKERS to " Alexander Ivanov
2026-10-27 12:47 ` [PATCH hci-8.1 v2 1/2] vhost-blk: create kernel threads with " Alexander Ivanov
2026-10-27 12:52   ` no-reply
2026-10-27 13:05     ` Alexander Ivanov
2026-10-27 14:22   ` Andrey Drobyshev
2026-10-28 11:48     ` Alexander Ivanov [this message]
2026-10-27 12:47 ` [PATCH hci-8.1 v2 2/2] linux-headers: drop VHOST_SET_NWORKERS Alexander Ivanov
2026-10-27 12:50   ` no-reply
2026-10-27 14:22   ` Andrey Drobyshev

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=6e8b3fa4-b100-4044-ba32-67087f9d970d@virtuozzo.com \
    --to=alexander.ivanov@virtuozzo.com \
    --cc=andrey.drobyshev@virtuozzo.com \
    --cc=andrey.zhadchenko@virtuozzo.com \
    --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