[PATCH RFC 2/8] SUNRPC: Execute initial async RPC states in caller's context

From: Chuck Lever

Date: Mon Aug 31 2026 - 16:44:14 EST


Each async RPC task is dispatched to the rpciod workqueue before its
first FSM state runs, though the initial states (call_start through
call_allocate) typically complete without blocking. Under high
concurrency this adds a workqueue enqueue, dequeue, and context
switch per RPC and contributes to rpciod pool lock contention.

Have rpc_execute() call __rpc_execute() directly for async tasks as
well. The initial states then run in the caller's context, and
__rpc_execute() returns to the caller when the task first sleeps on
a wait queue. Later wake-ups still dispatch to rpciod via
rpc_make_runnable().

Commit d6a1ed08c6ac ("SUNRPC: Reduce asynchronous RPC task stack
usage") moved async dispatch onto rpciod to bound caller stack
depth. Inline execution preserves that bound because __rpc_execute()
still runs each state from the same stack frame.

Signed-off-by: Chuck Lever <cel@xxxxxxxxxx>
---
net/sunrpc/sched.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 016f16ca5779..9b2800f6bfc7 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -1003,8 +1003,9 @@ static void __rpc_execute(struct rpc_task *task)
current_restore_flags(pflags, PF_MEMALLOC);
}

-/*
- * User-visible entry point to the scheduler.
+/**
+ * rpc_execute - Consumer entry point to the RPC scheduler
+ * @task: RPC task to be scheduled
*
* This may be called recursively if e.g. an async NFS task updates
* the attributes and finds that dirty pages must be flushed.
@@ -1014,15 +1015,12 @@ static void __rpc_execute(struct rpc_task *task)
*/
void rpc_execute(struct rpc_task *task)
{
- bool is_async = RPC_IS_ASYNC(task);
+ unsigned int pflags = memalloc_nofs_save();

rpc_set_active(task);
- rpc_make_runnable(rpciod_workqueue, task);
- if (!is_async) {
- unsigned int pflags = memalloc_nofs_save();
- __rpc_execute(task);
- memalloc_nofs_restore(pflags);
- }
+ rpc_test_and_set_running(task);
+ __rpc_execute(task);
+ memalloc_nofs_restore(pflags);
}

static void rpc_async_schedule(struct work_struct *work)

--
2.55.0