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
next 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.