From: Vladimir Riabchun <vladimir.riabchun@virtuozzo.com>
To: Liu Kui <kui.liu@virtuozzo.com>
Cc: devel@openvz.org, azaitsev@virtuozzo.com
Subject: Re: [Devel] [PATCH hci-8.1] fs/fuse kio: start connect once per rpc_queue_work batch
Date: Mon, 21 Sep 2026 22:52:49 +0200 [thread overview]
Message-ID: <b586e233-2472-4421-a2f0-66edaa0afacf@virtuozzo.com> (raw)
In-Reply-To: <20260921-acssp872-batch-connect-v1-1-ded37d934f28@virtuozzo.com>
On 9/21/26 13:28, Liu Kui wrote:
> pcs_rpc_connect() is synchronous: it performs a full connect+auth
> cycle while holding ep->mutex. rpc_queue_work() splices the entire
> ep->input_queue onto an on-stack list and used to trigger the connect
> from pcs_rpc_send() on the first staged message. When the connect
> fails, pcs_rpc_reset() purges ep->input_queue and ep->state_queue,
> but the messages still sitting on the on-stack list are invisible to
> the purge - each of them re-triggers another blocking connect attempt
> under the same mutex hold. With a large backlog and an unreachable
> peer this keeps ep->mutex held for O(messages * connect timeout):
> in one crashdump the rescuer of pcs_wq ground through such a batch
> for days, starving calendar_work/rpc_close_work on the same ep and
> wedging umount in flush_workqueue(pcs_wq).
>
> Stage all messages from the batch on ep->state_queue first and start
> the connect once afterwards. A failed connect now aborts the whole
> batch in a single rpc_abort(), bounding the mutex hold to one connect
> attempt. This also restores the meaning of state_queue, which
> otherwise never held more than one message.
>
> https://virtuozzo.atlassian.net/browse/VSTOR-135626
>
> Signed-off-by: Liu Kui <kui.liu@virtuozzo.com>> ---
> Fix a pathological case seen in ACSSP-872 (and ASUP-3562) crashdumps:
> a single rpc_queue_work() invocation could hold ep->mutex for days,
> re-running a blocking connect+auth once per queued message to an
> unreachable peer, wedging the pcs_wq rescuer, calendar/close works
> and umount in flush_workqueue().
>
> https://virtuozzo.atlassian.net/browse/ACSSP-872
> ---
> fs/fuse/kio/pcs/pcs_rpc.c | 18 +++++++++++++++---
> 1 file changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/fs/fuse/kio/pcs/pcs_rpc.c b/fs/fuse/kio/pcs/pcs_rpc.c
> index 540225006726..c50e31c08a31 100644
> --- a/fs/fuse/kio/pcs/pcs_rpc.c
> +++ b/fs/fuse/kio/pcs/pcs_rpc.c
> @@ -702,9 +702,6 @@ static void pcs_rpc_send(struct pcs_rpc * ep, struct pcs_msg * msg, bool requeue
>
> list_add_tail(&msg->list, &ep->state_queue);
> msg->stage = PCS_MSG_STAGE_UNSENT;
> -
> - if (ep->state == PCS_RPC_UNCONN)
> - pcs_rpc_connect(ep);
> }
>
> void pcs_rpc_kick_queue(struct pcs_rpc * ep)
> @@ -930,6 +927,21 @@ static void rpc_queue_work(struct work_struct *w)
> list_del_init(&msg->list);
> pcs_rpc_send(ep, msg, 0);
> }
> +
> + /* pcs_rpc_connect() is synchronous: it can block for a full
> + * connect+auth cycle while holding ep->mutex. Start it once, after
> + * every message from input_q has been staged on ep->state_queue,
> + * instead of from pcs_rpc_send() on the first message. This way a
> + * failed connect aborts the whole batch at once: rpc_abort() purges
> + * ep->state_queue, whereas messages still sitting on the on-stack
> + * input_q are invisible to the purge and would each trigger another
> + * blocking connect attempt under the same mutex hold. It also
> + * restores the meaning of state_queue, which otherwise never holds
> + * more than one message.
> + */
> + if (ep->state == PCS_RPC_UNCONN && !list_empty(&ep->state_queue))
> + pcs_rpc_connect(ep);
> +
Now I seem to get the problem we are fixing. This will work fine when
no problems pre-existed, but if the thread already collected a bunch of
messages in its private list, it will prevent live patching.
Ref: https://docs.kernel.org/livepatch/livepatch.html#consistency-model
rpc_queue_work task has patched function on its stack (itself), so
approach 1 is not for us. We can't poke kernel thread task with any signals
and waking it up in klp_send_signals will not help as well.
The doc I referenced above describes /sys/kernel/livepatch/<patch>/force
mechanism, that can force patch transition for all tasks.
We may make use of it to fixup the thread.
I checked disassembly and pcs_rpc_send is _not_ inlined in rpc_queue_work,
so after forcing livepatch, new versions of pcs_rpc_send will be executed.
However, rpc_queue_work will be old one - jump to new function version
happens in ftrace header, we missed it and never come there for a running
kthread.
So with this forced scenario we can clear local input_q list, but nothing
here (I don't know about other places) will then call pcs_rpc_connect
and flush ep->state_queue.
After moving all input_q to ep->state_queue, without pcs_rpc_connect
this state_queue will move to local state_q, which will then do
patched pcs_rpc_send with requeue = 1, again without pcs_rpc_connect,
and put these messages back to ep->state_queue.
My question is:
Will anything blow up in this case if we just move these messages
from one queue to another without calling connect?
For me it seems that it will be a fast journey, all messages will
go to ep->state_queue and we will leave the kthread (repeat = 0).
Am I right and just forcing livepatch will work, or we need something
smarter to fix stuck threads?
> list_splice_tail_init(&ep->state_queue, &state_q);
> while (!list_empty(&state_q)) {
> struct pcs_msg * msg = list_first_entry(&state_q, struct pcs_msg, list);
>
> ---
> base-commit: 3851feefb321d7dee9e57cbe7926410aa6dd043f
> change-id: 20260921-acssp872-batch-connect-bec05e9db04d
>
> Best regards,
> --
> Liu Kui <kui.liu@virtuozzo.com>
>
> _______________________________________________
> Devel mailing list
> Devel@openvz.org
> https://lists.openvz.org/mailman/listinfo/devel
--
Best regards, Riabchun Vladimir
Linux Kernel Developer, Virtuozzo
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
next prev parent reply other threads:[~2026-09-21 20:54 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-21 11:28 Liu Kui
2026-09-21 12:13 ` Alexey Kuznetsov
2026-09-21 20:52 ` Vladimir Riabchun [this message]
2026-09-21 21:17 ` Alexey Kuznetsov
2026-09-22 9:38 ` Vladimir Riabchun
2026-09-22 10:46 ` Alexey Kuznetsov
2026-09-22 11:36 ` Vladimir Riabchun
2026-09-22 13:12 ` Alexey Kuznetsov
2026-09-22 14:10 ` Vladimir Riabchun
2026-09-22 15:01 ` Alexey Kuznetsov
2026-09-22 15:19 ` Vladimir Riabchun
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=b586e233-2472-4421-a2f0-66edaa0afacf@virtuozzo.com \
--to=vladimir.riabchun@virtuozzo.com \
--cc=azaitsev@virtuozzo.com \
--cc=devel@openvz.org \
--cc=kui.liu@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