From: Mike Rapoport <rppt@kernel.org>
To: Pasha Tatashin <pasha.tatashin@soleen.com>
Cc: pratyush@kernel.org, jasonmiu@google.com, graf@amazon.com,
dmatlack@google.com, rientjes@google.com, corbet@lwn.net,
rdunlap@infradead.org, ilpo.jarvinen@linux.intel.com,
kanie@linux.alibaba.com, ojeda@kernel.org, aliceryhl@google.com,
masahiroy@kernel.org, akpm@linux-foundation.org, tj@kernel.org,
yoann.congal@smile.fr, mmaurer@google.com,
roman.gushchin@linux.dev, chenridong@huawei.com, axboe@kernel.dk,
mark.rutland@arm.com, jannh@google.com,
vincent.guittot@linaro.org, hannes@cmpxchg.org,
dan.j.williams@intel.com, david@redhat.com,
joel.granados@kernel.org, rostedt@goodmis.org,
anna.schumaker@oracle.com, song@kernel.org,
zhangguopeng@kylinos.cn, linux@weissschuh.net,
linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
linux-mm@kvack.org, gregkh@linuxfoundation.org,
tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com,
rafael@kernel.org, dakr@kernel.org,
bartosz.golaszewski@linaro.org, cw00.choi@samsung.com,
myungjoo.ham@samsung.com, yesanishhere@gmail.com,
Jonathan.Cameron@huawei.com, quic_zijuhu@quicinc.com,
aleksander.lobakin@intel.com, ira.weiny@intel.com,
andriy.shevchenko@linux.intel.com, leon@kernel.org,
lukas@wunner.de, bhelgaas@google.com, wagi@kernel.org,
djeffery@redhat.com, stuart.w.hayes@gmail.com, ptyadav@amazon.de,
lennart@poettering.net, brauner@kernel.org,
linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org,
saeedm@nvidia.com, ajayachandra@nvidia.com, jgg@nvidia.com,
parav@nvidia.com, leonro@nvidia.com, witu@nvidia.com,
hughd@google.com, skhawaja@google.com, chrisl@kernel.org
Subject: Re: [PATCH v5 06/22] liveupdate: luo_session: add sessions support
Date: Fri, 14 Nov 2025 14:49:38 +0200 [thread overview]
Message-ID: <aRclYgHYXQFJ2Fpn@kernel.org> (raw)
In-Reply-To: <20251107210526.257742-7-pasha.tatashin@soleen.com>
On Fri, Nov 07, 2025 at 04:03:04PM -0500, Pasha Tatashin wrote:
> Introduce concept of "Live Update Sessions" within the LUO framework.
> LUO sessions provide a mechanism to group and manage `struct file *`
> instances (representing file descriptors) that need to be preserved
> across a kexec-based live update.
>
> Each session is identified by a unique name and acts as a container
> for file objects whose state is critical to a userspace workload, such
> as a virtual machine or a high-performance database, aiming to maintain
> their functionality across a kernel transition.
>
> This groundwork establishes the framework for preserving file-backed
> state across kernel updates, with the actual file data preservation
> mechanisms to be implemented in subsequent patches.
>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> ---
> include/linux/liveupdate/abi/luo.h | 81 ++++++
> include/uapi/linux/liveupdate.h | 3 +
> kernel/liveupdate/Makefile | 3 +-
> kernel/liveupdate/luo_core.c | 9 +
> kernel/liveupdate/luo_internal.h | 39 +++
> kernel/liveupdate/luo_session.c | 405 +++++++++++++++++++++++++++++
> 6 files changed, 539 insertions(+), 1 deletion(-)
> create mode 100644 kernel/liveupdate/luo_session.c
>
> diff --git a/include/linux/liveupdate/abi/luo.h b/include/linux/liveupdate/abi/luo.h
> index 9483a294287f..37b9fecef3f7 100644
> --- a/include/linux/liveupdate/abi/luo.h
> +++ b/include/linux/liveupdate/abi/luo.h
> @@ -28,6 +28,11 @@
> * / {
> * compatible = "luo-v1";
> * liveupdate-number = <...>;
> + *
> + * luo-session {
> + * compatible = "luo-session-v1";
> + * luo-session-head = <phys_addr_of_session_head_ser>;
> + * };
> * };
> *
> * Main LUO Node (/):
> @@ -36,11 +41,37 @@
> * Identifies the overall LUO ABI version.
> * - liveupdate-number: u64
> * A counter tracking the number of successful live updates performed.
> + *
> + * Session Node (luo-session):
> + * This node describes all preserved user-space sessions.
> + *
> + * - compatible: "luo-session-v1"
> + * Identifies the session ABI version.
> + * - luo-session-head: u64
> + * The physical address of a `struct luo_session_head_ser`. This structure is
> + * the header for a contiguous block of memory containing an array of
> + * `struct luo_session_ser`, one for each preserved session.
> + *
> + * Serialization Structures:
> + * The FDT properties point to memory regions containing arrays of simple,
> + * `__packed` structures. These structures contain the actual preserved state.
> + *
> + * - struct luo_session_head_ser:
> + * Header for the session array. Contains the total page count of the
> + * preserved memory block and the number of `struct luo_session_ser`
> + * entries that follow.
> + *
> + * - struct luo_session_ser:
> + * Metadata for a single session, including its name and a physical pointer
> + * to another preserved memory block containing an array of
> + * `struct luo_file_ser` for all files in that session.
> */
>
> #ifndef _LINUX_LIVEUPDATE_ABI_LUO_H
> #define _LINUX_LIVEUPDATE_ABI_LUO_H
>
> +#include <uapi/linux/liveupdate.h>
> +
> /*
> * The LUO FDT hooks all LUO state for sessions, fds, etc.
> * In the root it allso carries "liveupdate-number" 64-bit property that
> @@ -51,4 +82,54 @@
> #define LUO_FDT_COMPATIBLE "luo-v1"
> #define LUO_FDT_LIVEUPDATE_NUM "liveupdate-number"
>
> +/*
> + * LUO FDT session node
> + * LUO_FDT_SESSION_HEAD: is a u64 physical address of struct
> + * luo_session_head_ser
> + */
> +#define LUO_FDT_SESSION_NODE_NAME "luo-session"
> +#define LUO_FDT_SESSION_COMPATIBLE "luo-session-v1"
> +#define LUO_FDT_SESSION_HEAD "luo-session-head"
> +
> +/**
> + * struct luo_session_head_ser - Header for the serialized session data block.
> + * @pgcnt: The total size, in pages, of the entire preserved memory block
> + * that this header describes.
> + * @count: The number of 'struct luo_session_ser' entries that immediately
> + * follow this header in the memory block.
> + *
> + * This structure is located at the beginning of a contiguous block of
> + * physical memory preserved across the kexec. It provides the necessary
> + * metadata to interpret the array of session entries that follow.
> + */
> +struct luo_session_head_ser {
> + u64 pgcnt;
> + u64 count;
> +} __packed;
> +
> +/**
> + * struct luo_session_ser - Represents the serialized metadata for a LUO session.
> + * @name: The unique name of the session, copied from the `luo_session`
> + * structure.
> + * @files: The physical address of a contiguous memory block that holds
> + * the serialized state of files.
> + * @pgcnt: The number of pages occupied by the `files` memory block.
> + * @count: The total number of files that were part of this session during
> + * serialization. Used for iteration and validation during
> + * restoration.
> + *
> + * This structure is used to package session-specific metadata for transfer
> + * between kernels via Kexec Handover. An array of these structures (one per
> + * session) is created and passed to the new kernel, allowing it to reconstruct
> + * the session context.
> + *
> + * If this structure is modified, LUO_SESSION_COMPATIBLE must be updated.
> + */
> +struct luo_session_ser {
> + char name[LIVEUPDATE_SESSION_NAME_LENGTH];
> + u64 files;
> + u64 pgcnt;
> + u64 count;
> +} __packed;
> +
> #endif /* _LINUX_LIVEUPDATE_ABI_LUO_H */
> diff --git a/include/uapi/linux/liveupdate.h b/include/uapi/linux/liveupdate.h
> index df34c1642c4d..d2ef2f7e0dbd 100644
> --- a/include/uapi/linux/liveupdate.h
> +++ b/include/uapi/linux/liveupdate.h
> @@ -43,4 +43,7 @@
> /* The ioctl type, documented in ioctl-number.rst */
> #define LIVEUPDATE_IOCTL_TYPE 0xBA
>
> +/* The maximum length of session name including null termination */
> +#define LIVEUPDATE_SESSION_NAME_LENGTH 56
Out of curiosity, why 56? :)
> +
> #endif /* _UAPI_LIVEUPDATE_H */
> diff --git a/kernel/liveupdate/Makefile b/kernel/liveupdate/Makefile
> index 413722002b7a..83285e7ad726 100644
> --- a/kernel/liveupdate/Makefile
> +++ b/kernel/liveupdate/Makefile
> @@ -2,7 +2,8 @@
>
> luo-y := \
> luo_core.o \
> - luo_ioctl.o
> + luo_ioctl.o \
> + luo_session.o
>
> obj-$(CONFIG_KEXEC_HANDOVER) += kexec_handover.o
> obj-$(CONFIG_KEXEC_HANDOVER_DEBUG) += kexec_handover_debug.o
> diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c
> index c1bd236bccb0..83257ab93ebb 100644
> --- a/kernel/liveupdate/luo_core.c
> +++ b/kernel/liveupdate/luo_core.c
> @@ -116,6 +116,10 @@ static int __init luo_early_startup(void)
> pr_info("Retrieved live update data, liveupdate number: %lld\n",
> luo_global.liveupdate_num);
>
> + err = luo_session_setup_incoming(luo_global.fdt_in);
> + if (err)
> + return err;
> +
> return 0;
> }
>
> @@ -149,6 +153,7 @@ static int __init luo_fdt_setup(void)
> err |= fdt_begin_node(fdt_out, "");
> err |= fdt_property_string(fdt_out, "compatible", LUO_FDT_COMPATIBLE);
> err |= fdt_property(fdt_out, LUO_FDT_LIVEUPDATE_NUM, &ln, sizeof(ln));
> + err |= luo_session_setup_outgoing(fdt_out);
> err |= fdt_end_node(fdt_out);
> err |= fdt_finish(fdt_out);
> if (err)
> @@ -202,6 +207,10 @@ int liveupdate_reboot(void)
> if (!liveupdate_enabled())
> return 0;
>
> + err = luo_session_serialize();
> + if (err)
> + return err;
> +
> err = kho_finalize();
> if (err) {
> pr_err("kho_finalize failed %d\n", err);
> diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h
> index 29f47a69be0b..b4f2d1443c76 100644
> --- a/kernel/liveupdate/luo_internal.h
> +++ b/kernel/liveupdate/luo_internal.h
> @@ -14,4 +14,43 @@ void *luo_alloc_preserve(size_t size);
> void luo_free_unpreserve(void *mem, size_t size);
> void luo_free_restore(void *mem, size_t size);
>
> +/**
> + * struct luo_session - Represents an active or incoming Live Update session.
> + * @name: A unique name for this session, used for identification and
> + * retrieval.
> + * @files_list: An ordered list of files associated with this session, it is
> + * ordered by preservation time.
> + * @ser: Pointer to the serialized data for this session.
> + * @count: A counter tracking the number of files currently stored in the
> + * @files_xa for this session.
^@files_list
> + * @list: A list_head member used to link this session into a global list
> + * of either outgoing (to be preserved) or incoming (restored from
> + * previous kernel) sessions.
> + * @retrieved: A boolean flag indicating whether this session has been
> + * retrieved by a consumer in the new kernel.
> + * @mutex: Session lock, protects files_list, and count.
> + * @files: The physically contiguous memory block that holds the serialized
> + * state of files.
> + * @pgcnt: The number of pages files occupy.
^ @files
> + */
> +struct luo_session {
> + char name[LIVEUPDATE_SESSION_NAME_LENGTH];
> + struct list_head files_list;
> + struct luo_session_ser *ser;
> + long count;
> + struct list_head list;
> + bool retrieved;
> + struct mutex mutex;
> + struct luo_file_ser *files;
> + u64 pgcnt;
> +};
> +
> +int luo_session_create(const char *name, struct file **filep);
> +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);
> +int luo_session_serialize(void);
> +int luo_session_deserialize(void);
The last four deal with all the sessions, maybe use plural in the function
names.
> +bool luo_session_is_deserialized(void);
> +
> #endif /* _LINUX_LUO_INTERNAL_H */
> diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
> new file mode 100644
> index 000000000000..a3513118aa74
> --- /dev/null
> +++ b/kernel/liveupdate/luo_session.c
> @@ -0,0 +1,405 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/*
> + * Copyright (c) 2025, Google LLC.
> + * Pasha Tatashin <pasha.tatashin@soleen.com>
> + */
> +
> +/**
> + * DOC: LUO Sessions
> + *
> + * LUO Sessions provide the core mechanism for grouping and managing `struct
> + * file *` instances that need to be preserved across a kexec-based live
> + * update. Each session acts as a named container for a set of file objects,
> + * allowing a userspace agent to manage the lifecycle of resources critical to a
> + * workload.
> + *
> + * Core Concepts:
> + *
> + * - Named Containers: Sessions are identified by a unique, user-provided name,
> + * which is used for both creation in the current kernel and retrieval in the
> + * next kernel.
> + *
> + * - Userspace Interface: Session management is driven from userspace via
> + * ioctls on /dev/liveupdate.
> + *
> + * - Serialization: Session metadata is preserved using the KHO framework. When
> + * a live update is triggered via kexec, an array of `struct luo_session_ser`
> + * is populated and placed in a preserved memory region. An FDT node is also
> + * created, containing the count of sessions and the physical address of this
> + * array.
> + *
> + * Session Lifecycle:
> + *
> + * 1. Creation: A userspace agent calls `luo_session_create()` to create a
> + * new, empty session and receives a file descriptor for it.
> + *
> + * 2. Serialization: When the `reboot(LINUX_REBOOT_CMD_KEXEC)` syscall is
> + * made, `luo_session_serialize()` is called. It iterates through all
> + * active sessions and writes their metadata into a memory area preserved
> + * by KHO.
> + *
> + * 3. Deserialization (in new kernel): After kexec, `luo_session_deserialize()`
> + * runs, reading the serialized data and creating a list of `struct
> + * luo_session` objects representing the preserved sessions.
> + *
> + * 4. Retrieval: A userspace agent in the new kernel can then call
> + * `luo_session_retrieve()` with a session name to get a new file
> + * descriptor and access the preserved state.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/anon_inodes.h>
> +#include <linux/errno.h>
> +#include <linux/file.h>
> +#include <linux/fs.h>
> +#include <linux/libfdt.h>
> +#include <linux/liveupdate.h>
> +#include <linux/liveupdate/abi/luo.h>
> +#include <uapi/linux/liveupdate.h>
> +#include "luo_internal.h"
> +
> +/* 16 4K pages, give space for 819 sessions */
> +#define LUO_SESSION_PGCNT 16ul
> +#define LUO_SESSION_MAX (((LUO_SESSION_PGCNT << PAGE_SHIFT) - \
> + sizeof(struct luo_session_head_ser)) / \
> + sizeof(struct luo_session_ser))
> +
> +/**
> + * struct luo_session_head - Head struct for managing LUO sessions.
Head of what? ;-)
Maybe luo_session_list? Or even luo_sessions?
> + * @count: The number of sessions currently tracked in the @list.
> + * @list: The head of the linked list of `struct luo_session` instances.
> + * @rwsem: A read-write semaphore providing synchronized access to the
> + * session list and other fields in this structure.
> + * @head_ser: The head data of serialization array.
^ header?
> + * @ser: The serialized session data (an array of
> + * `struct luo_session_ser`).
> + * @active: Set to true when first initialized. If previous kernel did not
> + * send session data, active stays false for incoming.
> + */
> +struct luo_session_head {
> + long count;
> + struct list_head list;
> + struct rw_semaphore rwsem;
> + struct luo_session_head_ser *head_ser;
> + struct luo_session_ser *ser;
> + bool active;
> +};
> +
> +/**
> + * struct luo_session_global - Global container for managing LUO sessions.
> + * @incoming: The sessions passed from the previous kernel.
> + * @outgoing: The sessions that are going to be passed to the next kernel.
> + * @deserialized: The sessions have been deserialized once /dev/liveupdate
> + * has been opened.
> + */
> +struct luo_session_global {
> + struct luo_session_head incoming;
> + struct luo_session_head outgoing;
> + bool deserialized;
> +} luo_session_global;
Should be static. And frankly, I don't think grouping two global variables
into a struct gains much.
static struct luo_sessions luo_sessions_incoming;
static struct luo_sessions luo_sessions_outgoing;
reads clearer to me.
> +
> +static struct luo_session *luo_session_alloc(const char *name)
> +{
> + struct luo_session *session = kzalloc(sizeof(*session), GFP_KERNEL);
> +
> + if (!session)
> + return NULL;
> +
> + strscpy(session->name, name, sizeof(session->name));
> + INIT_LIST_HEAD(&session->files_list);
> + session->count = 0;
I'd move this after mutex_init(), a bit more readable IMHO.
> + INIT_LIST_HEAD(&session->list);
> + mutex_init(&session->mutex);
> +
> + return session;
> +}
> +
> +static void luo_session_free(struct luo_session *session)
> +{
> + WARN_ON(session->count);
> + WARN_ON(!list_empty(&session->files_list));
> + mutex_destroy(&session->mutex);
> + kfree(session);
> +}
> +
> +static int luo_session_insert(struct luo_session_head *sh,
> + struct luo_session *session)
> +{
> + struct luo_session *it;
> +
> + guard(rwsem_write)(&sh->rwsem);
> +
> + /*
> + * For outgoing we should make sure there is room in serialization array
> + * for new session.
> + */
> + if (sh == &luo_session_global.outgoing) {
> + if (sh->count == LUO_SESSION_MAX)
> + return -ENOMEM;
> + }
Not a big deal, but this could be outside the guard().
> +
> + /*
> + * For small number of sessions this loop won't hurt performance
> + * but if we ever start using a lot of sessions, this might
> + * become a bottle neck during deserialization time, as it would
> + * cause O(n*n) complexity.
> + */
The loop is always O(n*n) in the worst case, no matter how many sessions
there are ;-)
> + list_for_each_entry(it, &sh->list, list) {
> + if (!strncmp(it->name, session->name, sizeof(it->name)))
> + return -EEXIST;
> + }
> + list_add_tail(&session->list, &sh->list);
> + sh->count++;
> +
> + return 0;
> +}
> +
> +static void luo_session_remove(struct luo_session_head *sh,
> + struct luo_session *session)
> +{
> + guard(rwsem_write)(&sh->rwsem);
> + list_del(&session->list);
> + sh->count--;
> +}
> +
> +static int luo_session_release(struct inode *inodep, struct file *filep)
> +{
> + struct luo_session *session = filep->private_data;
> + struct luo_session_head *sh;
> +
> + /* If retrieved is set, it means this session is from incoming list */
> + if (session->retrieved)
> + sh = &luo_session_global.incoming;
> + else
> + sh = &luo_session_global.outgoing;
Maybe just add a backpointer to the list to struct luo_session?
> +
> + luo_session_remove(sh, session);
> + luo_session_free(session);
> +
> + return 0;
> +}
> +
> +static const struct file_operations luo_session_fops = {
> + .owner = THIS_MODULE,
> + .release = luo_session_release,
> +};
> +
> +/* Create a "struct file" for session */
> +static int luo_session_getfile(struct luo_session *session, struct file **filep)
> +{
> + char name_buf[128];
> + struct file *file;
> +
> + guard(mutex)(&session->mutex);
> + snprintf(name_buf, sizeof(name_buf), "[luo_session] %s", session->name);
> + file = anon_inode_getfile(name_buf, &luo_session_fops, session, O_RDWR);
> + if (IS_ERR(file))
> + return PTR_ERR(file);
> +
> + *filep = file;
> +
> + return 0;
> +}
> +
> +int luo_session_create(const char *name, struct file **filep)
> +{
> + struct luo_session *session;
> + int err;
> +
> + session = luo_session_alloc(name);
> + if (!session)
> + return -ENOMEM;
> +
> + err = luo_session_insert(&luo_session_global.outgoing, session);
> + if (err) {
> + luo_session_free(session);
> + return err;
Please goto err_free
> + }
> +
> + err = luo_session_getfile(session, filep);
> + if (err) {
> + luo_session_remove(&luo_session_global.outgoing, session);
> + luo_session_free(session);
and goto err_remove
> + }
> +
> + return err;
> +}
> +
> +int luo_session_retrieve(const char *name, struct file **filep)
> +{
> + struct luo_session_head *sh = &luo_session_global.incoming;
> + struct luo_session *session = NULL;
> + struct luo_session *it;
> + int err;
> +
> + scoped_guard(rwsem_read, &sh->rwsem) {
> + list_for_each_entry(it, &sh->list, list) {
> + if (!strncmp(it->name, name, sizeof(it->name))) {
> + session = it;
> + break;
> + }
> + }
> + }
> +
> + if (!session)
> + return -ENOENT;
> +
> + scoped_guard(mutex, &session->mutex) {
> + if (session->retrieved)
> + return -EINVAL;
> + }
> +
> + err = luo_session_getfile(session, filep);
> + if (!err) {
> + scoped_guard(mutex, &session->mutex)
> + session->retrieved = true;
> + }
> +
> + return err;
> +}
> +
> +int __init luo_session_setup_outgoing(void *fdt_out)
> +{
> + struct luo_session_head_ser *head_ser;
> + u64 head_ser_pa;
> + int err;
> +
> + head_ser = luo_alloc_preserve(LUO_SESSION_PGCNT << PAGE_SHIFT);
> + if (IS_ERR(head_ser))
> + return PTR_ERR(head_ser);
> + head_ser_pa = __pa(head_ser);
virt_to_phys please
> +
> + err = fdt_begin_node(fdt_out, LUO_FDT_SESSION_NODE_NAME);
> + err |= fdt_property_string(fdt_out, "compatible",
> + LUO_FDT_SESSION_COMPATIBLE);
> + err |= fdt_property(fdt_out, LUO_FDT_SESSION_HEAD, &head_ser_pa,
> + sizeof(head_ser_pa));
> + err |= fdt_end_node(fdt_out);
> +
> + if (err)
> + goto err_unpreserve;
> +
> + head_ser->pgcnt = LUO_SESSION_PGCNT;
> + INIT_LIST_HEAD(&luo_session_global.outgoing.list);
> + init_rwsem(&luo_session_global.outgoing.rwsem);
> + luo_session_global.outgoing.head_ser = head_ser;
> + luo_session_global.outgoing.ser = (void *)(head_ser + 1);
> + luo_session_global.outgoing.active = true;
> +
> + return 0;
> +
> +err_unpreserve:
> + luo_free_unpreserve(head_ser, LUO_SESSION_PGCNT << PAGE_SHIFT);
> + return err;
> +}
> +
> +int __init luo_session_setup_incoming(void *fdt_in)
> +{
> + struct luo_session_head_ser *head_ser;
> + int err, head_size, offset;
> + const void *ptr;
> + u64 head_ser_pa;
> +
> + offset = fdt_subnode_offset(fdt_in, 0, LUO_FDT_SESSION_NODE_NAME);
> + if (offset < 0) {
> + pr_err("Unable to get session node: [%s]\n",
> + LUO_FDT_SESSION_NODE_NAME);
> + return -EINVAL;
> + }
> +
> + err = fdt_node_check_compatible(fdt_in, offset,
> + LUO_FDT_SESSION_COMPATIBLE);
> + if (err) {
> + pr_err("Session node incompatibale [%s]\n",
> + LUO_FDT_SESSION_COMPATIBLE);
> + return -EINVAL;
> + }
> +
> + head_size = 0;
> + ptr = fdt_getprop(fdt_in, offset, LUO_FDT_SESSION_HEAD, &head_size);
> + if (!ptr || head_size != sizeof(u64)) {
> + pr_err("Unable to get session head '%s' [%d]\n",
> + LUO_FDT_SESSION_HEAD, head_size);
> + return -EINVAL;
> + }
> +
> + memcpy(&head_ser_pa, ptr, sizeof(u64));
> + head_ser = __va(head_ser_pa);
> +
> + luo_session_global.incoming.head_ser = head_ser;
> + luo_session_global.incoming.ser = (void *)(head_ser + 1);
> + INIT_LIST_HEAD(&luo_session_global.incoming.list);
> + init_rwsem(&luo_session_global.incoming.rwsem);
> + luo_session_global.incoming.active = true;
> +
> + return 0;
> +}
> +
> +bool luo_session_is_deserialized(void)
> +{
> + return luo_session_global.deserialized;
> +}
> +
> +int luo_session_deserialize(void)
> +{
> + struct luo_session_head *sh = &luo_session_global.incoming;
> +
> + if (luo_session_is_deserialized())
> + return 0;
> +
> + luo_session_global.deserialized = true;
Shouldn't this be set after deserialization succeeded?
> + if (!sh->active) {
> + INIT_LIST_HEAD(&sh->list);
> + init_rwsem(&sh->rwsem);
> + return 0;
> + }
> +
> + for (int i = 0; i < sh->head_ser->count; i++) {
> + struct luo_session *session;
> +
> + session = luo_session_alloc(sh->ser[i].name);
> + if (!session) {
> + pr_warn("Failed to allocate session [%s] during deserialization\n",
> + sh->ser[i].name);
> + return -ENOMEM;
> + }
> +
> + if (luo_session_insert(sh, session)) {
> + pr_warn("Failed to insert session due to name conflict [%s]\n",
> + session->name);
> + return -EEXIST;
Need to free allocated sessions if an insert fails.
> + }
> +
> + session->count = sh->ser[i].count;
> + session->files = __va(sh->ser[i].files);
> + session->pgcnt = sh->ser[i].pgcnt;
> + }
> +
> + luo_free_restore(sh->head_ser, sh->head_ser->pgcnt << PAGE_SHIFT);
> + sh->head_ser = NULL;
> + sh->ser = NULL;
> +
> + return 0;
> +}
> +
> +int luo_session_serialize(void)
> +{
> + struct luo_session_head *sh = &luo_session_global.outgoing;
> + struct luo_session *session;
> + int i = 0;
> +
> + guard(rwsem_write)(&sh->rwsem);
> + list_for_each_entry(session, &sh->list, list) {
> + strscpy(sh->ser[i].name, session->name,
> + sizeof(sh->ser[i].name));
> + sh->ser[i].count = session->count;
> + sh->ser[i].files = __pa(session->files);
> + sh->ser[i].pgcnt = session->pgcnt;
> + i++;
> + }
> + sh->head_ser->count = sh->count;
> +
> + return 0;
> +}
> --
> 2.51.2.1041.gc1ab5b90ca-goog
>
>
--
Sincerely yours,
Mike.
next prev parent reply other threads:[~2025-11-14 12:50 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-07 21:02 [PATCH v5 00/22] Live Update Orchestrator Pasha Tatashin
2025-11-07 21:02 ` [PATCH v5 01/22] liveupdate: luo_core: luo_ioctl: " Pasha Tatashin
2025-11-13 13:37 ` Mike Rapoport
2025-11-13 13:56 ` Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 02/22] liveupdate: luo_core: integrate with KHO Pasha Tatashin
2025-11-10 13:00 ` Mike Rapoport
2025-11-10 15:43 ` Pasha Tatashin
2025-11-11 20:16 ` Mike Rapoport
2025-11-11 20:57 ` Pasha Tatashin
2025-11-12 13:25 ` Mike Rapoport
2025-11-12 14:58 ` Pasha Tatashin
2025-11-13 16:31 ` Mike Rapoport
2025-11-13 18:38 ` Pasha Tatashin
2025-11-11 20:25 ` Mike Rapoport
2025-11-11 20:39 ` Pasha Tatashin
2025-11-11 20:42 ` Pasha Tatashin
2025-11-12 10:21 ` Mike Rapoport
2025-11-12 12:46 ` Pasha Tatashin
2025-11-12 13:33 ` Mike Rapoport
2025-11-12 15:14 ` Pasha Tatashin
2025-11-12 17:39 ` Pasha Tatashin
2025-11-14 11:29 ` Mike Rapoport
2025-11-14 14:48 ` Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 03/22] reboot: call liveupdate_reboot() before kexec Pasha Tatashin
2025-11-14 11:30 ` Mike Rapoport
2025-11-07 21:03 ` [PATCH v5 04/22] liveupdate: Kconfig: Make debugfs optional Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 05/22] liveupdate: kho: when live update add KHO image during kexec load Pasha Tatashin
2025-11-10 12:47 ` Mike Rapoport
2025-11-10 15:31 ` Pasha Tatashin
2025-11-11 20:18 ` Mike Rapoport
2025-11-11 20:59 ` Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 06/22] liveupdate: luo_session: add sessions support Pasha Tatashin
2025-11-12 20:39 ` Mike Rapoport
2025-11-12 20:47 ` Pasha Tatashin
2025-11-14 12:49 ` Mike Rapoport [this message]
2025-11-14 14:07 ` Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 07/22] liveupdate: luo_ioctl: add user interface Pasha Tatashin
2025-11-14 12:57 ` Mike Rapoport
2025-11-14 14:09 ` Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 08/22] liveupdate: luo_file: implement file systems callbacks Pasha Tatashin
2025-11-10 17:27 ` Pratyush Yadav
2025-11-10 17:42 ` Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 09/22] liveupdate: luo_session: Add ioctls for file preservation and state management Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 10/22] liveupdate: luo_flb: Introduce File-Lifecycle-Bound global state Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 11/22] docs: add luo documentation Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 12/22] MAINTAINERS: add liveupdate entry Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 13/22] mm: shmem: use SHMEM_F_* flags instead of VM_* flags Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 14/22] mm: shmem: allow freezing inode mapping Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 15/22] mm: shmem: export some functions to internal.h Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 16/22] liveupdate: luo_file: add private argument to store runtime state Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 17/22] mm: memfd_luo: allow preserving memfd Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 18/22] docs: add documentation for memfd preservation via LUO Pasha Tatashin
2025-11-13 16:55 ` Pasha Tatashin
2025-11-13 16:59 ` Pratyush Yadav
2025-11-07 21:03 ` [PATCH v5 19/22] selftests/liveupdate: Add userspace API selftests Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 20/22] selftests/liveupdate: Add kexec-based selftest for session lifecycle Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 21/22] selftests/liveupdate: Add kexec test for multiple and empty sessions Pasha Tatashin
2025-11-07 21:03 ` [PATCH v5 22/22] tests/liveupdate: Add in-kernel liveupdate test Pasha Tatashin
2025-11-12 20:23 ` Mike Rapoport
2025-11-12 20:40 ` Pasha Tatashin
2025-11-16 18:36 ` Mike Rapoport
2025-11-17 14:09 ` Pasha Tatashin
2025-11-07 22:33 ` [PATCH v5 00/22] Live Update Orchestrator Andrew Morton
2025-11-08 18:13 ` Pasha Tatashin
2025-11-08 18:36 ` Andrew Morton
2025-11-09 2:31 ` 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=aRclYgHYXQFJ2Fpn@kernel.org \
--to=rppt@kernel.org \
--cc=Jonathan.Cameron@huawei.com \
--cc=ajayachandra@nvidia.com \
--cc=akpm@linux-foundation.org \
--cc=aleksander.lobakin@intel.com \
--cc=aliceryhl@google.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=anna.schumaker@oracle.com \
--cc=axboe@kernel.dk \
--cc=bartosz.golaszewski@linaro.org \
--cc=bhelgaas@google.com \
--cc=bp@alien8.de \
--cc=brauner@kernel.org \
--cc=chenridong@huawei.com \
--cc=chrisl@kernel.org \
--cc=corbet@lwn.net \
--cc=cw00.choi@samsung.com \
--cc=dakr@kernel.org \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=david@redhat.com \
--cc=djeffery@redhat.com \
--cc=dmatlack@google.com \
--cc=graf@amazon.com \
--cc=gregkh@linuxfoundation.org \
--cc=hannes@cmpxchg.org \
--cc=hpa@zytor.com \
--cc=hughd@google.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=ira.weiny@intel.com \
--cc=jannh@google.com \
--cc=jasonmiu@google.com \
--cc=jgg@nvidia.com \
--cc=joel.granados@kernel.org \
--cc=kanie@linux.alibaba.com \
--cc=lennart@poettering.net \
--cc=leon@kernel.org \
--cc=leonro@nvidia.com \
--cc=linux-api@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux@weissschuh.net \
--cc=lukas@wunner.de \
--cc=mark.rutland@arm.com \
--cc=masahiroy@kernel.org \
--cc=mingo@redhat.com \
--cc=mmaurer@google.com \
--cc=myungjoo.ham@samsung.com \
--cc=ojeda@kernel.org \
--cc=parav@nvidia.com \
--cc=pasha.tatashin@soleen.com \
--cc=pratyush@kernel.org \
--cc=ptyadav@amazon.de \
--cc=quic_zijuhu@quicinc.com \
--cc=rafael@kernel.org \
--cc=rdunlap@infradead.org \
--cc=rientjes@google.com \
--cc=roman.gushchin@linux.dev \
--cc=rostedt@goodmis.org \
--cc=saeedm@nvidia.com \
--cc=skhawaja@google.com \
--cc=song@kernel.org \
--cc=stuart.w.hayes@gmail.com \
--cc=tglx@linutronix.de \
--cc=tj@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=wagi@kernel.org \
--cc=witu@nvidia.com \
--cc=x86@kernel.org \
--cc=yesanishhere@gmail.com \
--cc=yoann.congal@smile.fr \
--cc=zhangguopeng@kylinos.cn \
/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.