Re: [PATCH 1/5] liveupdate: Remove limit on the number of sessions

Pasha Tatashin
2026-04-20T13:26:41Z

On 04-20 10:13, Mike Rapoport wrote:
> On Tue, Apr 14, 2026 at 08:02:33PM +0000, Pasha Tatashin wrote:
> > Currently, the number of LUO sessions is limited by a fixed number of
> > pre-allocated pages for serialization (16 pages, allowing for ~819
> > sessions).
> >
> > This limitation is problematic if LUO is used to support things such as
> > systemd file descriptor store, and would be used not just as VM memory
> > but to save other states on the machine.
> >
> > Remove this limit by transitioning to a linked-block approach for
> > session metadata serialization. Instead of a single contiguous block,
> > session metadata is now stored in a chain of 16-page blocks. Each block
> > starts with a header containing the physical address of the next block
> > and the number of session entries in the current block.
> >
> > - Bump session ABI version to v3.
> > - Update struct luo_session_header_ser to include a 'next' pointer.
> > - Implement dynamic block allocation in luo_session_insert().
> > - Update setup, serialization, and deserialization logic to traverse
> > the block chain.
> > - Remove LUO_SESSION_MAX limit.
> >
> > Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> > ---
> > include/linux/kho/abi/luo.h | 19 +--
> > kernel/liveupdate/luo_internal.h | 12 +-
> > kernel/liveupdate/luo_session.c | 237 +++++++++++++++++++++++--------
> > 3 files changed, 197 insertions(+), 71 deletions(-)
>
> ...
>
> > +/**
> > + * struct luo_session_block - Internal representation of a session serialization block.
> > + * @list: List head for linking blocks in memory.
> > + * @ser: Pointer to the serialized header in preserved memory.
> > + */
> > +struct luo_session_block {
> > + struct list_head list;
> > + struct luo_session_header_ser *ser;
> > +};
> > +
> > /**
> > * struct luo_session_header - Header struct for managing LUO sessions.
> > * @count: The number of sessions currently tracked in the @list.
> > + * @nblocks: The number of allocated serialization blocks.
> > * @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.
> > - * @header_ser: The header data of serialization array.
> > - * @ser: The serialized session data (an array of
> > - * `struct luo_session_ser`).
> > + * @blocks: The list of serialization blocks (struct luo_session_block).
> > * @active: Set to true when first initialized. If previous kernel did not
> > * send session data, active stays false for incoming.
> > */
> > struct luo_session_header {
> > long count;
> > + long nblocks;
> > struct list_head list;
> > struct rw_semaphore rwsem;
> > - struct luo_session_header_ser *header_ser;
> > - struct luo_session_ser *ser;
> > + struct list_head blocks;
>
> Don't we need some sort of locking for blocks?

The rwsem right above the blocks field protects it. New blocks are only
created when luo_session_insert() is called, which takes
rwsem_write(&sh->rwsem).

For simplicity, once blocks are created, we never free them. This is
safe given that sessions can only be created by a single privileged
agent.

>
> > bool active;
> > };
>
> > @@ -147,15 +222,6 @@ static int luo_session_insert(struct luo_session_header *sh,
> >
> > 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;
> > - }
> > -
> > /*
> > * For small number of sessions this loop won't hurt performance
> > * but if we ever start using a lot of sessions, this might
>
> For ~8.1 million sessions this comment does not seem valid anymore ;-)

Fair point! However, in all reasonable use cases we expect to have at
most hundreds of sessions, so this should still be fine. To extend on
this: the O(N^2) complexity mentioned in the comment is really only a
problem during restoration, which happens during our performance
critical blackout time. However, it is used there only for sanity
checking, if we trust the previous kernel, we can remove this
duplication check entirely.

Let's keep this sanity check for now. If it ever becomes a performance
bottleneck, we can remove it during the blackout time and optimize the
pre-blackout session creation to use an O(log(N)) search by storing them
in a sorted by name data structure.

>
> --
> Sincerely yours,
> Mike.