From: tarunsahu@google.com
To: Pasha Tatashin <pasha.tatashin@soleen.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
joro@8bytes.org, Mike Rapoport <rppt@kernel.org>,
Pratyush Yadav <pratyush@kernel.org>,
maz@kernel.org, arnd@arndb.de,
David Matlack <dmatlack@google.com>,
jgg@nvidia.com, robin.murphy@arm.com, loganodell@google.com,
oupton@kernel.org, kevin.tian@intel.com, alex@shazbot.org,
dwmw2@infradead.org, pbonzini@redhat.com, seanjc@google.com,
will@kernel.org, Alexander Graf <graf@amazon.com>,
Bjorn Helgaas <bhelgaas@google.com>,
baolu.lu@linux.intel.com, linux-arm-kernel@lists.infradead.org,
linux-arch@vger.kernel.org, sagis@google.com,
linux-mm@kvack.org, kvmarm@lists.linux.dev,
iommu@lists.linux.dev, linux-pci@vger.kernel.org,
kexec@lists.infradead.org, skhawaja@google.com,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [RFC PATCH v2 2/4] liveupdate: Select file handler by name in the preserve ioctl
Date: Thu, 22 Oct 2026 12:50:06 +0000 [thread overview]
Message-ID: <9huzik2t5281.fsf@tarunix.c.googlers.com> (raw)
In-Reply-To: <CA+CK2bCnS8wcVDbOymBGeJB6pDUkknOpF22EynbwSV=D5=J4ow@mail.gmail.com>
I have gone through the discussion in reply to this thread between
@dmatlack and @pasha
I am not sure If I understood the discussion correctly.
userspace IOCTL for FLB compatiblity might not necessary as each FLBs are
registered with the file handler. So when new file handler introduced in the
system, new flb handlers can be registered that is compatible with this
new file handler. I have tried to explain this below.
Pasha Tatashin <pasha.tatashin@soleen.com> writes:
> On Wed, Oct 21, 2026 at 11:25 AM Tarun Sahu <tarunsahu@google.com> wrote:
>>
>> Currently luo_preserve_file() iterates over luo_file_handler_list and
>> picks the first registered handler whose .can_preserve() callback
>> returns true. When a subsystem introduces a new, backwards-incompatible
>> file handler alongside an existing one for the same file type, userspace
>> has no way to choose which handler preserves a file descriptor, nor can
>> the kernel keep the existing rollback-safe handler as the default while
>> allowing callers to opt into the new handler.
>
> That is not how it will work.
> If we are in the .can_preserve() call,
> it means the user has already decided which file handlers to use.
That is not true.
From the documentation of the luo_preserve_file(): 3rd point.
* This function orchestrates the first phase of preserving a file. It performs
* the following steps:
*
* 1. Validates that the @token is not already in use within the file_set.
* 2. Ensures the file_set's memory for files serialization is allocated
* (allocates if needed).
=>* 3. Iterates through registered handlers, calling can_preserve() to find one
* compatible with the given @fd.
* 4. Calls the handler's .preserve() operation, which saves the file's state
* and returns an opaque private data handle.
* 5. Adds the new instance to the file_set's internal list.
*
luo_preserve_file():
list_private_for_each_entry(fh, &luo_file_handler_list, list) {
if (fh->ops->can_preserve(fh, file)) {
if (try_module_get(fh->ops->owner))
err = 0;
break;
}
}
the first handler whose can_preserve return true will be selected as the
FH;
later in code:
err = fh->ops->preserve(&args);
So can_preserve() is called on every handler for a fd and once it finds
the FH which reutrns true, it uses its preserve call to preserve the file.
> We
> need to do that before any preservation happens; otherwise, we could
> run into conflicts on FLBs i.e. FH of different version require
> different FLBs.
My change below will select the user passed handler directly if it is
valid otherwise it fallbacks to looping .can_preserve based selection.
****For flb****:
Registration of flb handlers happens with original
subsytem fd handler, for example, for iommu
iommu_liveupdate_register_flb(&iommufd_ser_handler); ->liveupdate_register_flb(fh, flb);
This function takes the FH argument. So every FH has direct relation
with their flbs.
If new FH will be introduced within the system, it must register
compatible flbs handlers with it by liveupdate_register_flb.
Currently, FLB objects are preserved with the first dependent file's
preservation. and each flb handler in fh->flb_list (was associated
using each flb handler registration) will call its ops to preserve itself.
Same on retrieval side, handler name is preserved so the flb name is
also preserved. And they can just call their respects ops to retrieve
themselves.
What about If user try to preserve other dependent but same subsystem
files with different handler. Kernel must reject this. I have not
integrated this support. Which can also be added as part of this series.
Let me know if this sounds good, Then I will add that in the V3?
~Tarun
>
> Therefore, there should be a luoctl call (i.e via a new ioctl to set
> compatability) that provides the kernel with the specs file of the
> target kernel we are updating to, allowing the kernel to select the
> compatible file handlers. Since .can_preserve() is called when the
> user is already preserving files, the specification must have already
> been supplied, or the kernel should fall back to using the default
> (i.e., latest) file handlers.
>
>>
>> Append char handler[LIVEUPDATE_HNDL_NAME_LENGTH] to struct
>> liveupdate_session_preserve_fd immediately after token, keeping
>> IOCTL_OP min_size at offsetofend(..., token) so callers passing the
>> original 16-byte structure continue to work:
>> - When handler is empty (all-zero, or zero-filled when userspace
>> passes the 16-byte structure), luo_preserve_file() selects the first
>> registered handler whose .can_preserve() callback accepts the fd.
>> - When handler is non-empty, it must be null-terminated within
>> LIVEUPDATE_HNDL_NAME_LENGTH bytes (returning -EINVAL otherwise);
>> luo_preserve_file() looks up the registered handler with that exact
>> name (returning -ENOENT if unknown) and verifies that its
>> .can_preserve() callback accepts the fd (returning -EINVAL if not).
>>
>> The retrieve ioctl is unchanged because the handler is identified by the
>> name stored in the serialized payload from the source kernel.
>>
>> Signed-off-by: Tarun Sahu <tarunsahu@google.com>
>> ---
>> include/uapi/linux/liveupdate.h | 12 +++++++++---
>> kernel/liveupdate/luo_file.c | 21 ++++++++++++++++++---
>> kernel/liveupdate/luo_internal.h | 3 ++-
>> kernel/liveupdate/luo_session.c | 7 ++++++-
>> 4 files changed, 35 insertions(+), 8 deletions(-)
>>
>> diff --git a/include/uapi/linux/liveupdate.h b/include/uapi/linux/liveupdate.h
>> index 509c6236720d..2413b19dabc1 100644
>> --- a/include/uapi/linux/liveupdate.h
>> +++ b/include/uapi/linux/liveupdate.h
>> @@ -126,9 +126,14 @@ struct liveupdate_ioctl_retrieve_session {
>>
>> /**
>> * struct liveupdate_session_preserve_fd - ioctl(LIVEUPDATE_SESSION_PRESERVE_FD)
>> - * @size: Input; sizeof(struct liveupdate_session_preserve_fd)
>> - * @fd: Input; The user-space file descriptor to be preserved.
>> - * @token: Input; An opaque, unique token for preserved resource.
>> + * @size: Input; sizeof(struct liveupdate_session_preserve_fd)
>> + * @fd: Input; The user-space file descriptor to be preserved.
>> + * @token: Input; An opaque, unique token for preserved resource.
>> + * @handler: Input; Optional null-terminated file handler name (max length
>> + * %LIVEUPDATE_HNDL_NAME_LENGTH including null terminator) selecting
>> + * which registered handler preserves @fd. If empty (all-zero, or
>> + * omitted when passing the 16-byte structure), the kernel selects
>> + * the first registered handler whose .can_preserve() accepts @fd.
>> *
>> * Holds parameters for preserving a file descriptor.
>> *
>> @@ -152,6 +157,7 @@ struct liveupdate_session_preserve_fd {
>> __u32 size;
>> __s32 fd;
>> __aligned_u64 token;
>> + char handler[LIVEUPDATE_HNDL_NAME_LENGTH];
>> };
>>
>> #define LIVEUPDATE_SESSION_PRESERVE_FD \
>> diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
>> index fb81239bedf3..be20e0f1e0aa 100644
>> --- a/kernel/liveupdate/luo_file.c
>> +++ b/kernel/liveupdate/luo_file.c
>> @@ -207,6 +207,8 @@ static bool luo_token_is_used(struct luo_file_set *file_set, u64 token)
>> * @file_set: The file_set to which the preserved file will be added.
>> * @token: A unique, user-provided identifier for the file.
>> * @fd: The file descriptor to be preserved.
>> + * @handler: Optional NUL-terminated handler name. If NULL or empty, the first
>> + * registered handler whose .can_preserve() accepts @fd is selected.
>> *
>> * This function orchestrates the first phase of preserving a file. Upon entry,
>> * it takes a reference to the 'struct file' via fget(), effectively making LUO
>> @@ -238,11 +240,13 @@ static bool luo_token_is_used(struct luo_file_set *file_set, u64 token)
>> * -EBUSY if the file descriptor is already preserved by another session.
>> * -EBADF if the file descriptor is invalid.
>> * -ENOSPC if the file_set is full.
>> - * -ENOENT if no compatible handler is found for the file type.
>> + * -ENOENT if no matching handler is registered or accepts @fd.
>> + * -EINVAL if the named handler cannot preserve @fd.
>> * -ENOMEM on memory allocation failure.
>> * Other erros might be returned by .preserve().
>> */
>> -int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
>> +int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd,
>> + const char *handler)
>> {
>> struct liveupdate_file_op_args args = {0};
>> struct liveupdate_file_handler *fh;
>> @@ -266,6 +270,18 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
>> err = -ENOENT;
>> down_read(&luo_register_rwlock);
>> list_private_for_each_entry(fh, &luo_file_handler_list, list) {
>> + if (handler && handler[0]) {
>> + if (strcmp(fh->name, handler))
>> + continue;
>> + if (!fh->ops->can_preserve(fh, file)) {
>> + err = -EINVAL;
>> + break;
>> + }
>> + if (try_module_get(fh->ops->owner))
>> + err = 0;
>> + break;
>> + }
>> +
>> if (fh->ops->can_preserve(fh, file)) {
>> if (try_module_get(fh->ops->owner))
>> err = 0;
>> @@ -274,7 +290,6 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
>> }
>> up_read(&luo_register_rwlock);
>>
>> - /* err is still -ENOENT if no handler was found */
>> if (err)
>> goto err_fput;
>>
>> diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h
>> index dac6644bfb18..911ffedec9f3 100644
>> --- a/kernel/liveupdate/luo_internal.h
>> +++ b/kernel/liveupdate/luo_internal.h
>> @@ -101,7 +101,8 @@ int __init luo_session_setup_incoming(u64 sessions_pa);
>> int luo_session_serialize(void);
>> int luo_session_deserialize(void);
>>
>> -int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd);
>> +int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd,
>> + const char *handler);
>> void luo_file_unpreserve_files(struct luo_file_set *file_set);
>> int luo_file_freeze(struct luo_file_set *file_set,
>> struct luo_file_set_ser *file_set_ser);
>> diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
>> index f48e9a4185f9..194ef45907c1 100644
>> --- a/kernel/liveupdate/luo_session.c
>> +++ b/kernel/liveupdate/luo_session.c
>> @@ -266,8 +266,13 @@ static int luo_session_preserve_fd(struct luo_session *session,
>> struct liveupdate_session_preserve_fd *argp = ucmd->cmd;
>> int err;
>>
>> + if (strnlen(argp->handler, sizeof(argp->handler)) ==
>> + sizeof(argp->handler))
>> + return -EINVAL;
>> +
>> guard(mutex)(&session->mutex);
>> - err = luo_preserve_file(&session->file_set, argp->token, argp->fd);
>> + err = luo_preserve_file(&session->file_set, argp->token, argp->fd,
>> + argp->handler);
>> if (err)
>> return err;
>>
>> --
>> 2.56.0.212.g129ede20d9-goog
>>
next prev parent reply other threads:[~2026-10-22 12:50 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 15:25 [RFC PATCH v2 0/4] liveupdate: Feature header ABI and named handler Tarun Sahu
2026-10-21 15:25 ` [RFC PATCH v2 1/4] liveupdate: Rename handler compatible to name Tarun Sahu
2026-10-21 17:11 ` Pasha Tatashin
2026-10-21 18:16 ` tarunsahu
2026-10-21 19:11 ` Pasha Tatashin
2026-10-21 19:35 ` tarunsahu
2026-10-21 15:25 ` [RFC PATCH v2 2/4] liveupdate: Select file handler by name in the preserve ioctl Tarun Sahu
2026-10-21 17:17 ` Pasha Tatashin
2026-10-21 23:02 ` David Matlack
2026-10-22 1:14 ` Pasha Tatashin
2026-10-22 17:57 ` David Matlack
2026-10-22 12:50 ` tarunsahu [this message]
2026-10-22 13:42 ` Pasha Tatashin
2026-10-21 15:25 ` [RFC PATCH v2 3/4] liveupdate: Replace compatibility string with a 2-bit pair feature header Tarun Sahu
2026-10-21 17:27 ` Pasha Tatashin
2026-10-21 17:40 ` Jason Gunthorpe
2026-10-21 17:55 ` Pasha Tatashin
2026-10-21 18:40 ` tarunsahu
2026-10-21 18:46 ` David Matlack
2026-10-21 18:50 ` Pasha Tatashin
2026-10-21 23:28 ` David Matlack
2026-10-22 1:26 ` Pasha Tatashin
2026-10-22 2:57 ` David Matlack
2026-10-22 3:32 ` Pasha Tatashin
2026-10-22 3:52 ` David Matlack
2026-10-22 4:11 ` Pasha Tatashin
2026-10-22 17:51 ` David Matlack
2026-10-21 23:55 ` David Matlack
2026-10-22 0:04 ` David Matlack
2026-10-21 15:25 ` [RFC PATCH v2 4/4] mm: memfd_luo: Add the " Tarun Sahu
2026-10-21 17:38 ` Pasha Tatashin
2026-10-21 23:18 ` David Matlack
2026-10-22 0:41 ` Pasha Tatashin
2026-10-22 2:51 ` David Matlack
2026-10-22 3:50 ` 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=9huzik2t5281.fsf@tarunix.c.googlers.com \
--to=tarunsahu@google.com \
--cc=akpm@linux-foundation.org \
--cc=alex@shazbot.org \
--cc=arnd@arndb.de \
--cc=baolu.lu@linux.intel.com \
--cc=bhelgaas@google.com \
--cc=dmatlack@google.com \
--cc=dwmw2@infradead.org \
--cc=graf@amazon.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@nvidia.com \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=kexec@lists.infradead.org \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arch@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-pci@vger.kernel.org \
--cc=loganodell@google.com \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=pasha.tatashin@soleen.com \
--cc=pbonzini@redhat.com \
--cc=pratyush@kernel.org \
--cc=robin.murphy@arm.com \
--cc=rppt@kernel.org \
--cc=sagis@google.com \
--cc=seanjc@google.com \
--cc=skhawaja@google.com \
--cc=will@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
all inboxes | Powered by JetHome®