All of lore.kernel.org
 help / color / mirror / Atom feed
From: Shakeel Butt <shakeel.butt@linux.dev>
To: "Michael S . Tsirkin" <mst@redhat.com>,
	"Jason Wang" <jasowangio@gmail.com>,
	"Eugenio Pérez" <eperezma@redhat.com>
Cc: Meta kernel team <kernel-team@meta.com>,
	cgroups@vger.kernel.org, linux-mmc@vger.kernel.org,
	kvm@vger.kernel.org, virtualization@lists.linux.dev,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] vhost_task: do the return-to-userspace work between work items
Date: Sat, 31 Oct 2026 11:10:04 -0700	[thread overview]
Message-ID: <20261031181004.4193627-1-shakeel.butt@linux.dev> (raw)

A vhost task is a user worker: a thread of a user process that runs only
kernel code. It never returns to userspace, so it never runs the work
that is queued for the way back. resume_user_mode_work() does that work
when TIF_NOTIFY_RESUME is set. For a vhost task this means:

- memory.high is handled at the wrong time. When a charge goes over
  memory.high, the task counts the pages, and should reclaim, and sleep
  if needed, on its way back to userspace. A vhost task only reclaims
  when more than a batch of pages has built up and the charge can block.
  Then it reclaims and sleeps in the middle of the charge, maybe while
  it holds a lock. vhost-scsi, for example, can fault in guest memory
  while it holds vq->mutex. If the charges can't block, nothing is done
  at all, and the count keeps growing.

- Block cgroup throttling never runs. blkcg_schedule_throttle() asks for
  it, but only resume_user_mode_work() acts on it.

- Task work queued with TWA_RESUME, like a deferred fput() or a NUMA
  balancing scan, waits until the task gets a signal or exits.

io_uring workers had the same problem, and io_run_task_work() calls
resume_user_mode_work() for them. Do the same in vhost_task_fn(): if
TIF_NOTIFY_RESUME is set, call resume_user_mode_work() at the top of the
loop. That is between work items, no locks are held there, and the task
is running. Passing a NULL regs is fine, io_uring and KVM already do it.

This covers every user of vhost_task_create(): the vhost workers and
KVM's NX huge page recovery thread.

Tested in a VM with a version of tools/virtio/vhost_net_test that puts
each RX buffer on a new page, so the vhost worker faults in, and
charges, 256M while its cgroup has memory.high=64M. Before, all 285
calls to __mem_cgroup_handle_over_high() came from try_charge_memcg(),
inside handle_rx() with vq->mutex held. After, all 589 came from
vhost_task_fn(). memory.peak stayed at 64M, and the run took about the
same time (0.66s before, 0.67s after). A lockdep kernel showed no
warnings.

Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
---
 kernel/vhost_task.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
index 3717885a5992..f0ab21aa2a1c 100644
--- a/kernel/vhost_task.c
+++ b/kernel/vhost_task.c
@@ -7,6 +7,7 @@
 #include <linux/sched/task.h>
 #include <linux/sched/vhost_task.h>
 #include <linux/sched/signal.h>
+#include <linux/resume_user_mode.h>
 
 enum vhost_task_flags {
 	VHOST_TASK_FLAGS_STOP,
@@ -38,6 +39,14 @@ static int vhost_task_fn(void *data)
 				break;
 		}
 
+		/*
+		 * A vhost task never returns to userspace. Do the work that
+		 * would run on the way back, like memory.high reclaim, here
+		 * between work items, while no locks are held.
+		 */
+		if (test_thread_flag(TIF_NOTIFY_RESUME))
+			resume_user_mode_work(NULL);
+
 		/* mb paired w/ vhost_task_stop */
 		set_current_state(TASK_INTERRUPTIBLE);
 
-- 
2.53.0-Meta


             reply	other threads:[~2026-10-31 18:10 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-31 18:10 Shakeel Butt [this message]
2026-10-31 18:15 ` [PATCH] vhost_task: do the return-to-userspace work between work items Michael S. Tsirkin
2026-10-31 18:58   ` Shakeel Butt

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=20261031181004.4193627-1-shakeel.butt@linux.dev \
    --to=shakeel.butt@linux.dev \
    --cc=cgroups@vger.kernel.org \
    --cc=eperezma@redhat.com \
    --cc=jasowangio@gmail.com \
    --cc=kernel-team@meta.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=virtualization@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.