public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Pratyush Yadav <pratyush@kernel.org>
To: Leo Timmins <leotimmins1974@gmail.com>
Cc: pasha.tatashin@soleen.com,  rppt@kernel.org,
	linux-kernel@vger.kernel.org,  pratyush@kernel.org,
	akpm@linux-foundation.org
Subject: Re: [PATCH v3 2/2] liveupdate: initialize incoming FLB state before finish
Date: Thu, 02 Apr 2026 13:28:33 +0000	[thread overview]
Message-ID: <2vxzmrzlfq4e.fsf@kernel.org> (raw)
In-Reply-To: <20260326042546.8031-3-leotimmins1974@gmail.com> (Leo Timmins's message of "Thu, 26 Mar 2026 12:25:35 +0800")

On Thu, Mar 26 2026, Leo Timmins wrote:

> luo_flb_file_finish_one() decremented incoming.count before making sure
> that the incoming FLB state had been materialized. If no earlier incoming
> retrieval had populated that state, the first decrement ran from zero and
> skipped the last-user finish path.
>
> Initialize the incoming FLB state before the first decrement so finish
> uses the serialized refcount instead of an uninitialized value.

This commit message makes it very hard to understand what the problem it
fixes. It took me 20 minutes of reading this patch and looking at the
FLB code to figure out what is going on. Here is what I'd suggest:

    The state of an incoming FLB object is initialized when it is first
    used. The initialization is done via luo_flb_retrieve_one(), which looks
    at all the incoming FLBs, matches the FLB to its serialized entry, and
    initializes the incoming data and count.

    luo_flb_file_finish_one() is called when finish is called for a file
    registered with this FLB. If no file handler has used the FLB by this
    point, the count stays un-initialized at 0. luo_flb_file_finish_one()
    then decrements this un-initialized count, leading to an underflow. This
    results in the FLB finish never being called since the count has
    underflowed to a very large value.

    Fix this by making sure the FLB is retrieved before using its count.

>
> Fixes: cab056f2aae7 ("liveupdate: luo_flb: introduce File-Lifecycle-Bound global state")
> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Signed-off-by: Leo Timmins <leotimmins1974@gmail.com>
> ---
>  kernel/liveupdate/luo_flb.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c
> index f52e8114837e..855af655b09b 100644
> --- a/kernel/liveupdate/luo_flb.c
> +++ b/kernel/liveupdate/luo_flb.c
> @@ -192,10 +192,27 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
>  static void luo_flb_file_finish_one(struct liveupdate_flb *flb)
>  {
>  	struct luo_flb_private *private = luo_flb_get_private(flb);
> +	bool needs_retrieve = false;
>  	u64 count;
>  
> -	scoped_guard(mutex, &private->incoming.lock)
> +	scoped_guard(mutex, &private->incoming.lock) {
> +		if (!private->incoming.count && !private->incoming.finished)
> +			needs_retrieve = true;
> +	}
> +
> +	if (needs_retrieve) {
> +		int err = luo_flb_retrieve_one(flb);
> +
> +		if (err) {
> +			pr_warn("Failed to retrieve FLB '%s' during finish: %pe\n",
> +				flb->compatible, ERR_PTR(err));
> +			return;
> +		}
> +	}
> +
> +	scoped_guard(mutex, &private->incoming.lock) {
>  		count = --private->incoming.count;
> +	}

This looks way too overcomplicated. We just need to move the retrieve
call before we check the count.

Pasha, side note: I think FLB suffers from the same problem I fixed for
LUO files with f85b1c6af5bc ("liveupdate: luo_file: remember retrieve()
status"). If retrieve fails, it doesn't remember the error code and will
retry retrieve() on next usage, causing all sorts of problems.

Pasha, another side note: I think incoming.private should be initialized
when the FLB is registered, not when it is first used. This will make
this simpler overall. This would need liveupdate_register_flb() to not
call kzalloc(), but that can be done I think.

Anyway, for this problem, how about the patch below (only
compile-tested) addressing my comments. The diff looks bigger but the
end result is a lot cleaner IMO. In effect it just moves the retrieve
call outside the if (!count). Everything else is just cleaning up the
locking situation.

--- 8< ---
From 775565e72d9b851839d37088549f0fc247cac2e1 Mon Sep 17 00:00:00 2001
From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
Date: Thu, 2 Apr 2026 13:22:05 +0000
Subject: [PATCH] liveupdate: initialize incoming FLB state before finish

The state of an incoming FLB object is initialized when it is first
used. The initialization is done via luo_flb_retrieve_one(), which looks
at all the incoming FLBs, matches the FLB to its serialized entry, and
initializes the incoming data and count.

luo_flb_file_finish_one() is called when finish is called for a file
registered with this FLB. If no file handler has used the FLB by this
point, the count stays un-initialized at 0. luo_flb_file_finish_one()
then decrements this un-initialized count, leading to an underflow. This
results in the FLB finish never being called since the count has
underflowed to a very large value.

Fix this by making sure the FLB is retrieved before using its count.

Fixes: cab056f2aae7 ("liveupdate: luo_flb: introduce File-Lifecycle-Bound global state")
Suggested-by: Leo Timmins <leotimmins1974@gmail.com>
Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
---
 kernel/liveupdate/luo_flb.c | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c
index f52e8114837e..be141620751e 100644
--- a/kernel/liveupdate/luo_flb.c
+++ b/kernel/liveupdate/luo_flb.c
@@ -194,28 +194,26 @@ static void luo_flb_file_finish_one(struct liveupdate_flb *flb)
 	struct luo_flb_private *private = luo_flb_get_private(flb);
 	u64 count;
 
-	scoped_guard(mutex, &private->incoming.lock)
-		count = --private->incoming.count;
+	if (!private->incoming.retrieved) {
+		int err = luo_flb_retrieve_one(flb);
 
+		if (WARN_ON(err))
+			return;
+	}
+
+	guard(mutex)(&private->incoming.lock);
+
+	count = --private->incoming.count;
 	if (!count) {
 		struct liveupdate_flb_op_args args = {0};
 
-		if (!private->incoming.retrieved) {
-			int err = luo_flb_retrieve_one(flb);
+		args.flb = flb;
+		args.obj = private->incoming.obj;
+		flb->ops->finish(&args);
 
-			if (WARN_ON(err))
-				return;
-		}
-
-		scoped_guard(mutex, &private->incoming.lock) {
-			args.flb = flb;
-			args.obj = private->incoming.obj;
-			flb->ops->finish(&args);
-
-			private->incoming.data = 0;
-			private->incoming.obj = NULL;
-			private->incoming.finished = true;
-		}
+		private->incoming.data = 0;
+		private->incoming.obj = NULL;
+		private->incoming.finished = true;
 	}
 }
 
-- 
Regards,
Pratyush Yadav

  parent reply	other threads:[~2026-04-02 13:28 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-26  4:25 [PATCH v3 0/2] liveupdate: fix incoming error handling and teardown paths Leo Timmins
2026-03-26  4:25 ` [PATCH v3 1/2] liveupdate: propagate file deserialization failures Leo Timmins
2026-04-02 12:17   ` Pratyush Yadav
2026-03-26  4:25 ` [PATCH v3 2/2] liveupdate: initialize incoming FLB state before finish Leo Timmins
2026-03-26 14:50   ` Pasha Tatashin
2026-04-02 13:28   ` Pratyush Yadav [this message]
2026-04-02 18:15     ` Andrew Morton
2026-04-03  9:04       ` Pratyush Yadav
2026-04-03 17:26         ` Andrew Morton
     [not found]           ` <CA+uuG7Lnc94vTmZPEhbvQXgAzWJDL28Zf=QR=uAkmiWvoW+Uxw@mail.gmail.com>
2026-04-04 15:43             ` Leo Timmins
2026-04-05  7:35               ` Pratyush Yadav
2026-03-28  0:32 ` [PATCH v3 0/2] liveupdate: fix incoming error handling and teardown paths Andrew Morton
2026-03-28  1:47   ` Pasha Tatashin

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=2vxzmrzlfq4e.fsf@kernel.org \
    --to=pratyush@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=leotimmins1974@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pasha.tatashin@soleen.com \
    --cc=rppt@kernel.org \
    /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