All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
From: Konstantin Khorenko <khorenko@virtuozzo.com>
To: Liu Kui <kui.liu@virtuozzo.com>
Cc: devel@openvz.org, azaitsev@virtuozzo.com
Subject: Re: [Devel] [PATCH VZ10] fs/fuse kio: track pending kRPC connect via state machine only
Date: Tue, 01 Sep 2026 22:59:10 +0200	[thread overview]
Message-ID: <178829635034.1186226.7726025563757909332.b4-review@b4> (raw)
In-Reply-To: <20260827123712.84476-1-kui.liu@virtuozzo.com>

> Rework the previous fix ("fs/fuse kio: fix kRPC connect issues") to not
> require the new struct pcs_krpc member "connect_req", so the fix can be
> shipped as a livepatch.
> 
> Both things connect_req was tracking are already derivable from the
> existing state machine once PCS_KRPC_STATE_CONNECT is made to mean
> exactly "a connect req is in flight":
> 
>  - krpc_connect_done() settles a failed connect back to UNCONN instead
>    of leaving the state in CONNECT forever;
> 
>  - pcs_krpc_abort() no longer resets CONNECT to UNCONN: the req is
>    still in flight, and only its completion settles the state;
> 
>  - pcs_krpc_connect() proceeds only from UNCONN or ABORTED, refusing
>    new connects (-EPERM) while a req is in flight - at most one connect
>    req exists at a time, same as with the connect_req check;
> 
>  - pcs_krpc_poll() reports EPOLLERR on UNCONN: poll bails out earlier
>    unless ctx->gen == krpc->gen, and the current session can only be in
>    UNCONN if its connect failed or was aborted, which is what the
>    (CONNECT && !connect_req) test used to detect.
> 
> gen only advances in pcs_krpc_connect(), which is blocked during
> CONNECT, so within that state the in-flight req always carries the
> current gen and krpc_connect_done()'s existing staleness check is
> sufficient.
> 
> Related to:
> https://virtuozzo.atlassian.net/browse/VSTOR-135626
> Fixes: d0d6034c36010 ("fs/fuse kio: fix kRPC connect issues")
> Feature: fuse: kRPC - single RPC for kernel and userspace
> 
> Signed-off-by: Liu Kui <kui.liu@virtuozzo.com>
>
> diff --git a/fs/fuse/kio/pcs/pcs_krpc.c b/fs/fuse/kio/pcs/pcs_krpc.c
> index 0930fb4adf125..f9fb6b3699062 100644
> --- a/fs/fuse/kio/pcs/pcs_krpc.c
> +++ b/fs/fuse/kio/pcs/pcs_krpc.c
> @@ -787,8 +787,12 @@ static int pcs_krpc_abort(struct pcs_krpc *krpc)
>       spin_lock(&krpc->lock);
>
>       if (krpc->state != PCS_KRPC_STATE_CONNECTED) {
> -             if (krpc->state == PCS_KRPC_STATE_CONNECT)
> -                     krpc->state = PCS_KRPC_STATE_UNCONN;
> +             /*
> +              * A pending connect stays in CONNECT state: its connect req
> +              * is still in flight and krpc_connect_done() will settle the
> +              * state to UNCONN when it completes.  Until then new connects
> +              * are refused, so at most one connect req exists at a time.
> +              */
>               spin_unlock(&krpc->lock);
>               return 0;
>       }

[Severity: High]
Can this change leave a krpc stuck in the connected state with no
session fd attached to it?

Consider a connect req in flight (state is CONNECT) whose fd is closed
by userspace after its connect timeout expires - the scenario the
original fix was written for:

pcs_krpc_release()
    if (ctx->gen == krpc->gen)
        pcs_krpc_abort(krpc);    /* state is CONNECT: does nothing now */

gen cannot advance while the state stays CONNECT, because
pcs_krpc_connect() refuses new connects with -EPERM in that state.  So
when the in-flight req later completes successfully (the peer became
reachable again), krpc_connect_done() passes its staleness check and
commits the dead session:

    if (req->gen != krpc->gen || krpc->state != PCS_KRPC_STATE_CONNECT) {
        spin_unlock(&krpc->lock);
        goto out;
    }

    if (!pcs_if_error(&msg->error)) {
        krpc->state = PCS_KRPC_STATE_CONNECTED;

Now the krpc is CONNECTED while its gen still names a session whose fd
is gone.  Every following PCS_IOC_KRPC_CONNECT returns -EPERM, there is
no fd left on which userspace could issue PCS_KRPC_IOC_ABORT, and no
kernel path resets the state, so the node stays unconnectable until the
krpc is destroyed.

The connect_req based code handled this case: pcs_krpc_abort() moved
CONNECT to UNCONN, a successful krpc_connect_done() then took the stale
path without transitioning to CONNECTED, and the next connect was
allowed as soon as the old req completed.

Does the abort/release path need to invalidate the pending connect, so
that a late successful completion settles the state to UNCONN instead
of resurrecting the closed session?

> @@ -956,8 +960,13 @@ static __poll_t pcs_krpc_poll(struct file *file, poll_table *wait)
>
>       spin_lock(&krpc->lock);
>
> +     /*
> +      * ctx->gen == krpc->gen (checked above) means this is the current
> +      * session, so UNCONN here can only mean its connect attempt has
> +      * failed (see krpc_connect_done()) or the session was aborted.
> +      */
>       if (krpc->state == PCS_KRPC_STATE_ABORTED ||
> -         (krpc->state == PCS_KRPC_STATE_CONNECT && !krpc->connect_req)) {
> +         krpc->state == PCS_KRPC_STATE_UNCONN) {
>               pollflags |= EPOLLERR;
>       } else if (krpc->state == PCS_KRPC_STATE_CONNECTED) {
>               pollflags |= EPOLLOUT;

[Severity: Low]
This isn't a bug, but after this change pcs_krpc_abort() never sets
UNCONN, and an aborted session is left in ABORTED, which the first
check already handles.

For a session with ctx->gen == krpc->gen, can UNCONN still be reached
through an abort as the comment says, or only through a failed
connect?  The commit message carries the same wording ("the current
session can only be in UNCONN if its connect failed or was aborted").

[ ... ]

-- 
Konstantin Khorenko <khorenko@virtuozzo.com>
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

      parent reply	other threads:[~2026-09-01 21:00 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-27 12:37 Liu Kui
2026-08-28 17:13 ` Konstantin Khorenko
2026-09-01 20:59 ` Konstantin Khorenko [this message]

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=178829635034.1186226.7726025563757909332.b4-review@b4 \
    --to=khorenko@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 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.