[PATCH v2] vhost: add a new ioctl VHOST_GET_VRING_WORKER_INFO and use in net.c

Nick Hudson posted 1 patch 3 months, 1 week ago
drivers/vhost/net.c              |  5 +++++
drivers/vhost/vhost.c            | 19 +++++++++++++++++++
include/linux/sched/vhost_task.h |  2 ++
include/uapi/linux/vhost.h       |  3 +++
include/uapi/linux/vhost_types.h | 13 +++++++++++++
kernel/vhost_task.c              | 12 ++++++++++++
6 files changed, 54 insertions(+)
[PATCH v2] vhost: add a new ioctl VHOST_GET_VRING_WORKER_INFO and use in net.c
Posted by Nick Hudson 3 months, 1 week ago
The vhost_net (and vhost_sock) drivers create worker tasks to handle
the virtual queues. Provide a new ioctl VHOST_GET_VRING_WORKER_INFO that
can be used to determine the PID of these tasks so that, for example,
they can be pinned to specific CPU(s).

Signed-off-by: Nick Hudson <nhudson@akamai.com>
Reviewed-by: Max Tottenham <mtottenh@akamai.com>
---
 drivers/vhost/net.c              |  5 +++++
 drivers/vhost/vhost.c            | 19 +++++++++++++++++++
 include/linux/sched/vhost_task.h |  2 ++
 include/uapi/linux/vhost.h       |  3 +++
 include/uapi/linux/vhost_types.h | 13 +++++++++++++
 kernel/vhost_task.c              | 12 ++++++++++++
 6 files changed, 54 insertions(+)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 35ded4330431..e86bd5d7d202 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -1804,6 +1804,11 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
 		return vhost_net_reset_owner(n);
 	case VHOST_SET_OWNER:
 		return vhost_net_set_owner(n);
+	case VHOST_GET_VRING_WORKER_INFO:
+		mutex_lock(&n->dev.mutex);
+		r = vhost_worker_ioctl(&n->dev, ioctl, argp);
+		mutex_unlock(&n->dev.mutex);
+		return r;
 	default:
 		mutex_lock(&n->dev.mutex);
 		r = vhost_dev_ioctl(&n->dev, ioctl, argp);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 8570fdf2e14a..20ad9d190dc3 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1012,6 +1012,7 @@ long vhost_worker_ioctl(struct vhost_dev *dev, unsigned int ioctl,
 			void __user *argp)
 {
 	struct vhost_vring_worker ring_worker;
+	struct vhost_vring_worker_info ring_worker_info;
 	struct vhost_worker_state state;
 	struct vhost_worker *worker;
 	struct vhost_virtqueue *vq;
@@ -1050,6 +1051,7 @@ long vhost_worker_ioctl(struct vhost_dev *dev, unsigned int ioctl,
 	/* vring worker ioctls */
 	case VHOST_ATTACH_VRING_WORKER:
 	case VHOST_GET_VRING_WORKER:
+	case VHOST_GET_VRING_WORKER_INFO:
 		break;
 	default:
 		return -ENOIOCTLCMD;
@@ -1082,6 +1084,23 @@ long vhost_worker_ioctl(struct vhost_dev *dev, unsigned int ioctl,
 		if (copy_to_user(argp, &ring_worker, sizeof(ring_worker)))
 			ret = -EFAULT;
 		break;
+	case VHOST_GET_VRING_WORKER_INFO:
+		worker = rcu_dereference_check(vq->worker,
+					       lockdep_is_held(&dev->mutex));
+		if (!worker) {
+			ret = -EINVAL;
+			break;
+		}
+
+		memset(&ring_worker_info, 0, sizeof(ring_worker_info));
+		ring_worker_info.index = idx;
+		ring_worker_info.worker_id = worker->id;
+		ring_worker_info.worker_pid = task_pid_vnr(vhost_get_task(worker->vtsk));
+
+		if (copy_to_user(argp, &ring_worker_info, sizeof(ring_worker_info)))
+			ret = -EFAULT;
+		break;
+
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
diff --git a/include/linux/sched/vhost_task.h b/include/linux/sched/vhost_task.h
index 25446c5d3508..568f9596f29e 100644
--- a/include/linux/sched/vhost_task.h
+++ b/include/linux/sched/vhost_task.h
@@ -11,4 +11,6 @@ void vhost_task_start(struct vhost_task *vtsk);
 void vhost_task_stop(struct vhost_task *vtsk);
 void vhost_task_wake(struct vhost_task *vtsk);
 
+struct task_struct *vhost_get_task(struct vhost_task *vtsk);
+
 #endif /* _LINUX_SCHED_VHOST_TASK_H */
diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
index c57674a6aa0d..c32aa8c71952 100644
--- a/include/uapi/linux/vhost.h
+++ b/include/uapi/linux/vhost.h
@@ -101,6 +101,9 @@
 /* Return the vring worker's ID */
 #define VHOST_GET_VRING_WORKER _IOWR(VHOST_VIRTIO, 0x16,		\
 				     struct vhost_vring_worker)
+/* Return the vring worker's ID and PID */
+#define VHOST_GET_VRING_WORKER_INFO _IOWR(VHOST_VIRTIO, 0x17,	\
+				     struct vhost_vring_worker_info)
 
 /* The following ioctls use eventfd file descriptors to signal and poll
  * for events. */
diff --git a/include/uapi/linux/vhost_types.h b/include/uapi/linux/vhost_types.h
index 1c39cc5f5a31..28e00f8ade85 100644
--- a/include/uapi/linux/vhost_types.h
+++ b/include/uapi/linux/vhost_types.h
@@ -63,6 +63,19 @@ struct vhost_vring_worker {
 	unsigned int worker_id;
 };
 
+/* Per-virtqueue worker mapping entry */
+struct vhost_vring_worker_info {
+	/* vring index */
+	unsigned int index;
+	/*
+	 * The id of the vhost_worker returned from VHOST_NEW_WORKER or
+	 * allocated as part of vhost_dev_set_owner.
+	 */
+	unsigned int worker_id;
+
+	__kernel_pid_t worker_pid;  /* PID/TID of worker thread, -1 if none */
+};
+
 /* no alignment requirement */
 struct vhost_iotlb_msg {
 	__u64 iova;
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index 27107dcc1cbf..aa87a7f0c98a 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -67,6 +67,18 @@ static int vhost_task_fn(void *data)
 	do_exit(0);
 }
 
+/**
+ * vhost_get_task - get a pointer to the vhost_task's task_struct
+ * @vtsk: vhost_task to return the task for
+ *
+ * return the vhost_task's task.
+ */
+struct task_struct *vhost_get_task(struct vhost_task *vtsk)
+{
+	return vtsk->task;
+}
+EXPORT_SYMBOL_GPL(vhost_get_task);
+
 /**
  * vhost_task_wake - wakeup the vhost_task
  * @vtsk: vhost_task to wake
-- 
2.34.1
Re: [PATCH v2] vhost: add a new ioctl VHOST_GET_VRING_WORKER_INFO and use in net.c
Posted by Andrew Lunn 3 months, 1 week ago
On Tue, Oct 28, 2025 at 03:28:54PM +0000, Nick Hudson wrote:
> The vhost_net (and vhost_sock) drivers create worker tasks to handle
> the virtual queues. Provide a new ioctl VHOST_GET_VRING_WORKER_INFO that
> can be used to determine the PID of these tasks so that, for example,
> they can be pinned to specific CPU(s).

Could you add something about the lifetime of the PID. How do you know
the PID still belongs to the worker by the time you come to use it?

	Andrew
Re: [PATCH v2] vhost: add a new ioctl VHOST_GET_VRING_WORKER_INFO and use in net.c
Posted by Lei Yang 3 months ago
Tested this patch with virtio-net regression tests, everything works fine.

Tested-by: Lei Yang <leiyang@redhat.com>

On Wed, Oct 29, 2025 at 5:14 AM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Tue, Oct 28, 2025 at 03:28:54PM +0000, Nick Hudson wrote:
> > The vhost_net (and vhost_sock) drivers create worker tasks to handle
> > the virtual queues. Provide a new ioctl VHOST_GET_VRING_WORKER_INFO that
> > can be used to determine the PID of these tasks so that, for example,
> > they can be pinned to specific CPU(s).
>
> Could you add something about the lifetime of the PID. How do you know
> the PID still belongs to the worker by the time you come to use it?
>
>         Andrew
>