From nobody Mon Feb 9 05:59:22 2026 Received: from sender4-pp-f112.zoho.com (sender4-pp-f112.zoho.com [136.143.188.112]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF62231BC95 for ; Fri, 30 Jan 2026 14:52:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.112 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769784726; cv=pass; b=YpuAGtk4tXz+grA1zgFr5edwQMcPRCSFmTYMsj8e7Pb1d/BHVDOnDeknJaoIt1yt08w2+qmMsFbJCH0phbwwMAjsFSYljdKllvLb0jsHbjI2DHx5V7xSW/1sY1a+fcylfJVXclJ+WO3yqcAWjyxscy1J6cWi0yDmKJ85J3AxOVA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769784726; c=relaxed/simple; bh=G3cVWgppnU3vtnRghKGnQe00FA3N59jD//FdPtFoDrc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=B+pVAfDLyGGll/DELjdVHgPQI3w1WgFmXDUM+Vkh3fBNYWRlVF3IpixMwIJ1pNFBwSEQmA8KVLCF4ysyFF0utxNd+lKD/jfXPeCMqRsWatqAl68/ViFBWcrrfCnFvPPQmkgslgsMf3OodW8/d6h4pzFZ6WX3Y+EGhUA6qfovICA= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=linux.beauty; spf=pass smtp.mailfrom=linux.beauty; dkim=pass (1024-bit key) header.d=linux.beauty header.i=me@linux.beauty header.b=KwVXalqP; arc=pass smtp.client-ip=136.143.188.112 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=linux.beauty Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.beauty Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.beauty header.i=me@linux.beauty header.b="KwVXalqP" ARC-Seal: i=1; a=rsa-sha256; t=1769784704; cv=none; d=zohomail.com; s=zohoarc; b=ixrk4YN/BNj96DVXlh7TlQpAdw/V8EHGk0zRYG+vgiroBAujzSMQ2/COjDDUwq1AyQyP1ESnxu974V0WjM7SYxx6k+bToxubcoUvOPbrx1L20AFRS+sv66ZFTnWur3PgiJCA4XIdz2/oYl9X73fTlgO4QoL+Cr511p7p/IrEBtw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769784704; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=0sigC7NiTxNLAax7/+B9OkXqoq3ARjs97hBD6xuCTuA=; b=m/sX8x/SCeT5gsu1KTBzuzTu6R0XibY+BMzo5hyZ8yaVvGaVZqpczBZPptBv93nqkoMSWDs4RAB7lRlIzg2BipB65RN2FB3uri1U3FDU4Ir6iBud/XotdgwOl+oig5enBGmtiej/tFP0RlRMUf3Rm1uEs3kPsQ8i2p01HHWRsxk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=linux.beauty; spf=pass smtp.mailfrom=me@linux.beauty; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1769784704; s=zmail; d=linux.beauty; i=me@linux.beauty; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=0sigC7NiTxNLAax7/+B9OkXqoq3ARjs97hBD6xuCTuA=; b=KwVXalqPC1Xuhzj70eoLsGzNiTwNQvrl0IQeVKBrH/wBSREcn5QjWxBSrt2Ua9Fm J9WT8ROb05WI9zMyV+XDrV3OV/NJ+J4wl8z92SkC9lEcqmJOF+pSj6id8mVT/nEqNa4 RiSZO8wqoCOuYpBttMG6FzShBr5v6t8cHLrzX8I0= Received: by mx.zohomail.com with SMTPS id 1769784701372338.8712380432893; Fri, 30 Jan 2026 06:51:41 -0800 (PST) From: Li Chen To: Pasha Tatashin , Mike Rapoport , Pratyush Yadav , linux-kernel@vger.kernel.org Cc: Li Chen Subject: [PATCH v1 1/3] liveupdate: track post-kexec restore window Date: Fri, 30 Jan 2026 22:51:17 +0800 Message-ID: <20260130145122.368748-2-me@linux.beauty> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260130145122.368748-1-me@linux.beauty> References: <20260130145122.368748-1-me@linux.beauty> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" A kexec-based live update introduces a window after the new kernel boots where userspace needs to retrieve and restore preserved sessions. Provide liveupdate_restore_in_progress() backed by a counter of incoming sessions left, and make session finishing idempotent to avoid double finish paths causing counter underflow. Signed-off-by: Li Chen --- include/linux/liveupdate.h | 11 +++++++++ kernel/liveupdate/luo_core.c | 2 ++ kernel/liveupdate/luo_internal.h | 4 ++++ kernel/liveupdate/luo_session.c | 41 +++++++++++++++++++++++++++++++- 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/include/linux/liveupdate.h b/include/linux/liveupdate.h index ed81e7b31a9f..406a6e2dd4a1 100644 --- a/include/linux/liveupdate.h +++ b/include/linux/liveupdate.h @@ -217,6 +217,12 @@ struct liveupdate_flb { /* Return true if live update orchestrator is enabled */ bool liveupdate_enabled(void); =20 +/* + * Return true during a kexec-based live update boot while userspace is st= ill + * restoring preserved sessions/resources. + */ +bool liveupdate_restore_in_progress(void); + /* Called during kexec to tell LUO that entered into reboot */ int liveupdate_reboot(void); =20 @@ -238,6 +244,11 @@ static inline bool liveupdate_enabled(void) return false; } =20 +static inline bool liveupdate_restore_in_progress(void) +{ + return false; +} + static inline int liveupdate_reboot(void) { return 0; diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c index 7a9ef16b37d8..19c91843fbdb 100644 --- a/kernel/liveupdate/luo_core.c +++ b/kernel/liveupdate/luo_core.c @@ -128,6 +128,8 @@ static int __init luo_early_startup(void) if (err) return err; =20 + luo_session_restore_window_init(); + err =3D luo_flb_setup_incoming(luo_global.fdt_in); =20 return err; diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_inter= nal.h index 6115d6a4054d..8aa4c5b0101b 100644 --- a/kernel/liveupdate/luo_internal.h +++ b/kernel/liveupdate/luo_internal.h @@ -72,6 +72,8 @@ struct luo_file_set { * previous kernel) sessions. * @retrieved: A boolean flag indicating whether this session has been * retrieved by a consumer in the new kernel. + * @finished: A boolean flag indicating whether this session has been + * successfully finished in the new kernel. * @file_set: A set of files that belong to this session. * @mutex: protects fields in the luo_session. */ @@ -80,6 +82,7 @@ struct luo_session { struct luo_session_ser *ser; struct list_head list; bool retrieved; + bool finished; struct luo_file_set file_set; struct mutex mutex; }; @@ -88,6 +91,7 @@ int luo_session_create(const char *name, struct file **fi= lep); int luo_session_retrieve(const char *name, struct file **filep); int __init luo_session_setup_outgoing(void *fdt); int __init luo_session_setup_incoming(void *fdt); +void __init luo_session_restore_window_init(void); int luo_session_serialize(void); int luo_session_deserialize(void); bool luo_session_quiesce(void); diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_sessio= n.c index dbdbc3bd7929..e1d1ab795c40 100644 --- a/kernel/liveupdate/luo_session.c +++ b/kernel/liveupdate/luo_session.c @@ -50,6 +50,7 @@ =20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt =20 +#include #include #include #include @@ -117,6 +118,31 @@ static struct luo_session_global luo_session_global = =3D { }, }; =20 +static atomic_long_t liveupdate_incoming_sessions_left =3D ATOMIC_LONG_INI= T(0); + +bool liveupdate_restore_in_progress(void) +{ + return atomic_long_read(&liveupdate_incoming_sessions_left) > 0; +} + +void __init luo_session_restore_window_init(void) +{ + struct luo_session_header *sh =3D &luo_session_global.incoming; + u64 count; + + if (!sh->active) + return; + + count =3D sh->header_ser->count; + if (count > LUO_SESSION_MAX) { + pr_warn("incoming session count %llu exceeds max %lu\n", + count, LUO_SESSION_MAX); + count =3D LUO_SESSION_MAX; + } + + atomic_long_set(&liveupdate_incoming_sessions_left, (long)count); +} + static struct luo_session *luo_session_alloc(const char *name) { struct luo_session *session =3D kzalloc(sizeof(*session), GFP_KERNEL); @@ -182,8 +208,21 @@ static void luo_session_remove(struct luo_session_head= er *sh, =20 static int luo_session_finish_one(struct luo_session *session) { + int err; + guard(mutex)(&session->mutex); - return luo_file_finish(&session->file_set); + if (session->finished) + return 0; + + err =3D luo_file_finish(&session->file_set); + if (err) + return err; + + session->finished =3D true; + if (session->retrieved) + atomic_long_dec(&liveupdate_incoming_sessions_left); + + return 0; } =20 static void luo_session_unfreeze_one(struct luo_session *session, --=20 2.52.0