mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RFC PATCH 0/6] Introduce file handler dependency level
@ 2026-10-01  0:57 Samiullah Khawaja
  2026-10-01  0:57 ` [RFC PATCH 1/6] liveupdate: " Samiullah Khawaja
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Samiullah Khawaja @ 2026-10-01  0:57 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Alexander Graf
  Cc: Samiullah Khawaja, David Matlack, tarunsahu, open list,
	open list:KEXEC HANDOVER (KHO), open list:KEXEC HANDOVER (KHO)

LUO allows preservation of FDs into sessions. An FD can depend on other
FDs, and for some FDs this can mean the dependency must be preserved
before it due to various reasons including immutability and performance.
See discussion on FD dependency patch series [1] and documentation [2]
for details. Also see the Liveupdate IOMMU [3] and guest_memfd
preservation [4] patch series for examples. These dependencies are
enforced by the file handlers, and userspace is responsible for
preserving the FDs in the correct order.

This RFC proposes a mechanism that allows userspace to preserve the FDs
as a batch, and the kernel preserves them in the required order. This
allows the VMM to preserve a bag of FDs without worrying about the
order. A new ioctl is added that allows userspace to provide an array of
FDs and tokens for preservation. This gives the kernel the token and the
intent to preserve every FD in the batch up front.

This RFC introduces the concept of file handler levels. Each file
handler offers a certain type of resource or functionality that relates
to other file handlers. These can be represented by levels. This RFC
adds the following levels and more can be added later:

 - Default (no level set)
 - Memory Providers
 - Memory Mappers (or users)
 - Devices

The levels are optional static configurations of how the file handlers
relate to each other. Each level represents a class of file handler,
which fixes the order of preservation between them.

The levels are spaced out to allow addition of new levels. LUO can use
these levels to deduce the order of preservation of a batch of FDs.

The batch is atomic: either all FDs are preserved or none are, and on
failure the index of the failing FD is returned to userspace. The
existing LIVEUPDATE_SESSION_PRESERVE_FD ioctl is unchanged and behaves
as a batch of one. Note that this does not break compatibility and
userspace can still attempt to preserve FDs individually using the
existing preservation ioctl.

The patch series builds on top of the Liveupdate IOMMU series [3] to
demonstrate the FD dependency. The full tree, including the
dependencies, is available at:
https://github.com/samikhawaja/linux/tree/luo/fd-dependency-rfc

I will present this at the Live Update MC at LPC 2026. I will also talk
about alternative solutions I considered.

Future work:

 - Allow file handlers to be preserved at multiple levels to allow
   resolving circular dependencies.

Looking forward to your feedback on this.

[1] https://lore.kernel.org/all/alrDpAMknlYN9jL9@google.com/#t
[2] https://lore.kernel.org/all/20260910173659.1945246-2-skhawaja@google.com/
[3] https://lore.kernel.org/all/20260921004834.2601285-1-skhawaja@google.com/
[4] https://lore.kernel.org/all/20260728121138.1103610-9-tarunsahu@google.com/

Samiullah Khawaja (6):
  liveupdate: Introduce file handler dependency level
  mm/memfd_luo: Set Liveupdate level of a memfd file handler
  iommufd: Set liveupdate file handler level
  vfio/pci: Set live update file handler level
  selftests/liveupdate: Add API to preserve a batch of FDs
  iommufd/selftests: Preserve all the FDs in a batch

 drivers/iommu/iommufd/liveupdate.c            |   1 +
 drivers/vfio/pci/vfio_pci_liveupdate.c        |   1 +
 include/linux/liveupdate.h                    |  24 ++
 include/uapi/linux/liveupdate.h               |  39 +++
 kernel/liveupdate/luo_file.c                  | 316 ++++++++++++------
 kernel/liveupdate/luo_internal.h              |   2 +
 kernel/liveupdate/luo_session.c               |  45 +++
 mm/memfd_luo.c                                |   1 +
 .../iommu/iommufd_liveupdate_kexec_test.c     |  27 +-
 .../liveupdate/lib/include/libliveupdate.h    |   2 +
 .../selftests/liveupdate/lib/lu_utils.c       |  20 ++
 11 files changed, 379 insertions(+), 99 deletions(-)


base-commit: 945d61765894dda2f0344de50cb1ade2e51b66fd
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC PATCH 1/6] liveupdate: Introduce file handler dependency level
  2026-10-01  0:57 [RFC PATCH 0/6] Introduce file handler dependency level Samiullah Khawaja
@ 2026-10-01  0:57 ` Samiullah Khawaja
  2026-10-01  0:57 ` [RFC PATCH 2/6] mm/memfd_luo: Set Liveupdate level of a memfd file handler Samiullah Khawaja
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Samiullah Khawaja @ 2026-10-01  0:57 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Alexander Graf
  Cc: Samiullah Khawaja, David Matlack, tarunsahu, open list,
	open list:KEXEC HANDOVER (KHO), open list:KEXEC HANDOVER (KHO)

Dependency level is an optional level in the file handler that can be
used to indicate the order in which FDs are preserved. The level define
the type of state an FD preserved and how it relates to other type of
FDs. For example a memory provider FD might be a dependency of an FD
that uses that memory.

Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
---
 include/linux/liveupdate.h       |  24 +++
 include/uapi/linux/liveupdate.h  |  39 ++++
 kernel/liveupdate/luo_file.c     | 316 +++++++++++++++++++++----------
 kernel/liveupdate/luo_internal.h |   2 +
 kernel/liveupdate/luo_session.c  |  45 +++++
 5 files changed, 330 insertions(+), 96 deletions(-)

diff --git a/include/linux/liveupdate.h b/include/linux/liveupdate.h
index 6051abc0612c..ba0af91126e1 100644
--- a/include/linux/liveupdate.h
+++ b/include/linux/liveupdate.h
@@ -87,6 +87,27 @@ struct liveupdate_file_ops {
 	struct module *owner;
 };
 
+/**
+ * enum liveupdate_level - Preservation order of a file handler.
+ * @LIVEUPDATE_LEVEL_NONE:   Level not set. The handler does not depend on
+ *                           any other preserved file. Preserved first.
+ * @LIVEUPDATE_LEVEL_MEM:    Files that provide memory.
+ * @LIVEUPDATE_LEVEL_MAPPER: Files that map memory provided by a lower level.
+ * @LIVEUPDATE_LEVEL_DEVICE: Files that represent devices.
+ *
+ * When a batch of files is preserved with LIVEUPDATE_SESSION_PRESERVE_FDS,
+ * LUO calls the handlers' .preserve() in ascending level order.
+ *
+ * The values are spaced so that new levels can be inserted without
+ * renumbering. The level is kernel internal and not part of any ABI.
+ */
+enum liveupdate_level {
+	LIVEUPDATE_LEVEL_NONE	= 0x0,
+	LIVEUPDATE_LEVEL_MEM	= 0x10,
+	LIVEUPDATE_LEVEL_MAPPER	= 0x20,
+	LIVEUPDATE_LEVEL_DEVICE	= 0x30,
+};
+
 /**
  * struct liveupdate_file_handler - Represents a handler for a live-updatable file type.
  * @ops:                Callback functions
@@ -94,6 +115,8 @@ struct liveupdate_file_ops {
  *                      that uniquely identifies the file type this handler
  *                      supports. This is matched against the compatible string
  *                      associated with individual &struct file instances.
+ * @level:              Optional. Preservation order of this handler. See &enum
+ *                      liveupdate_level.
  *
  * Modules that want to support live update for specific file types should
  * register an instance of this structure. LUO uses this registration to
@@ -103,6 +126,7 @@ struct liveupdate_file_ops {
 struct liveupdate_file_handler {
 	const struct liveupdate_file_ops *ops;
 	const char compatible[LIVEUPDATE_HNDL_COMPAT_LENGTH];
+	enum liveupdate_level level;
 
 	/* private: */
 
diff --git a/include/uapi/linux/liveupdate.h b/include/uapi/linux/liveupdate.h
index 4043d4038712..122275ab7ca2 100644
--- a/include/uapi/linux/liveupdate.h
+++ b/include/uapi/linux/liveupdate.h
@@ -60,6 +60,7 @@ enum {
 	LIVEUPDATE_CMD_SESSION_RETRIEVE_FD = 0x41,
 	LIVEUPDATE_CMD_SESSION_FINISH = 0x42,
 	LIVEUPDATE_CMD_SESSION_GET_NAME = 0x43,
+	LIVEUPDATE_CMD_SESSION_PRESERVE_FDS = 0x44,
 };
 
 /**
@@ -236,4 +237,42 @@ struct liveupdate_session_get_name {
 #define LIVEUPDATE_SESSION_GET_NAME					\
 	_IO(LIVEUPDATE_IOCTL_TYPE, LIVEUPDATE_CMD_SESSION_GET_NAME)
 
+/**
+ * struct liveupdate_session_preserve_fds - ioctl(LIVEUPDATE_SESSION_PRESERVE_FDS)
+ * @size:             Input; sizeof(struct liveupdate_session_preserve_fds)
+ * @nr:               Input; Number of entries in @fds and @tokens. Must not be
+ *                    zero.
+ * @fds:              Input; User pointer to an array of @nr __s32 file
+ *                    descriptors to be preserved.
+ * @tokens:           Input; User pointer to an array of @nr __u64 opaque,
+ *                    unique tokens, one for each entry in @fds.
+ * @out_failed_index: Output; On failure, the index of the entry in @fds that
+ *                    caused the failure, or @nr if the failure is not
+ *                    specific to an entry.
+ * @__reserved:       Input; Must be zero.
+ *
+ * Preserve a batch of file descriptors, some of which may depend on others in
+ * the same batch. The entries may be given in any order; the kernel preserves
+ * them in dependency order.
+ *
+ * All dependencies of a file must either be part of the same batch or have
+ * been preserved earlier in this session.
+ *
+ * The operation is atomic: either all file descriptors in the batch are
+ * preserved, or none are and the session is unchanged.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+struct liveupdate_session_preserve_fds {
+	__u32		size;
+	__u32		nr;
+	__aligned_u64	fds;
+	__aligned_u64	tokens;
+	__u32		out_failed_index;
+	__u32		__reserved;
+};
+
+#define LIVEUPDATE_SESSION_PRESERVE_FDS					\
+	_IO(LIVEUPDATE_IOCTL_TYPE, LIVEUPDATE_CMD_SESSION_PRESERVE_FDS)
+
 #endif /* _UAPI_LIVEUPDATE_H */
diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index 9c10cf3748a4..d83dc7966a81 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -43,10 +43,13 @@
  *
  * File Preservation Lifecycle happy path:
  *
- * 1. Preserve (Normal Operation): A userspace agent preserves files one by one
- *    via an ioctl. For each file, luo_preserve_file() finds a compatible
- *    handler, calls its .preserve() operation, and creates an internal &struct
- *    luo_file to track the live state.
+ * 1. Preserve (Normal Operation): A userspace agent preserves files via an
+ *    ioctl, either one by one or in batches. For each batch,
+ *    luo_preserve_files() finds a compatible handler for every file, then
+ *    calls the handlers' .preserve() operations in ascending handler level
+ *    order (see &enum liveupdate_level) so that dependencies are preserved
+ *    before their users, and creates an internal &struct luo_file to track
+ *    the live state of each file.
  *
  * 2. Freeze (Pre-Reboot): Just before the kexec, luo_file_freeze() is called.
  *    It iterates through all preserved files, calls their respective .freeze()
@@ -105,6 +108,7 @@
 #include <linux/kexec_handover.h>
 #include <linux/kho/abi/luo.h>
 #include <linux/list_private.h>
+#include <linux/list_sort.h>
 #include <linux/liveupdate.h>
 #include <linux/module.h>
 #include <linux/sizes.h>
@@ -175,7 +179,8 @@ static unsigned long luo_get_id(struct liveupdate_file_handler *fh,
 	return fh->ops->get_id ? fh->ops->get_id(file) : (unsigned long)file;
 }
 
-static bool luo_token_is_used(struct luo_file_set *file_set, u64 token)
+static bool luo_token_is_used(struct luo_file_set *file_set,
+			      struct list_head *pending, u64 token)
 {
 	struct luo_file *iter;
 
@@ -184,69 +189,36 @@ static bool luo_token_is_used(struct luo_file_set *file_set, u64 token)
 			return true;
 	}
 
+	list_for_each_entry(iter, pending, list) {
+		if (iter->token == token)
+			return true;
+	}
+
 	return false;
 }
 
-/**
- * luo_preserve_file - Initiate the preservation of a file descriptor.
- * @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.
- *
- * 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
- * a co-owner of the file. This reference is held until the file is either
- * unpreserved or successfully finished in the next kernel, preventing the file
- * from being prematurely destroyed.
- *
- * 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.
- *
- * On success, LUO takes a reference to the 'struct file' and considers it
- * under its management until it is unpreserved or finished.
+/*
+ * luo_file_alloc - Allocate a luo_file for one file of a batch.
  *
- * In case of any failure, all intermediate allocations (file reference, memory
- * for the 'luo_file' struct, etc.) are cleaned up before returning an error.
+ * Checks the token, takes a reference on the file, finds the handler and claims
+ * the file globally.
  *
- * Context: Can be called from an ioctl handler during normal system operation.
- * Return: 0 on success. Returns a negative errno on failure:
- *         -EEXIST if the token is already used.
- *         -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.
- *         -ENOMEM on memory allocation failure.
- *         Other erros might be returned by .preserve().
+ * On success the new luo_file is added to @pending.
  */
-int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
+static int luo_file_alloc(struct luo_file_set *file_set,
+			  struct list_head *pending, u64 token, int fd)
 {
-	struct liveupdate_file_op_args args = {0};
 	struct liveupdate_file_handler *fh;
 	struct luo_file *luo_file;
 	struct file *file;
 	int err;
 
-	if (luo_token_is_used(file_set, token))
+	if (luo_token_is_used(file_set, pending, token))
 		return -EEXIST;
 
-	err = kho_block_set_grow(&file_set->block_set, file_set->count + 1);
-	if (err)
-		return err;
-
 	file = fget(fd);
-	if (!file) {
-		err = -EBADF;
-		goto err_shrink;
-	}
+	if (!file)
+		return -EBADF;
 
 	err = -ENOENT;
 	down_read(&luo_register_rwlock);
@@ -282,23 +254,10 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
 	luo_file->fh = fh;
 	luo_file->token = token;
 	mutex_init(&luo_file->mutex);
-
-	args.handler = fh;
-	args.session = luo_session_from_file_set(file_set);
-	args.file = file;
-	err = fh->ops->preserve(&args);
-	if (err)
-		goto err_kfree;
-
-	luo_file->serialized_data = args.serialized_data;
-	luo_file->private_data = args.private_data;
-	list_add_tail(&luo_file->list, &file_set->files_list);
-	file_set->count++;
+	list_add_tail(&luo_file->list, pending);
 
 	return 0;
 
-err_kfree:
-	kfree(luo_file);
 err_flb_unpreserve:
 	luo_flb_file_unpreserve(fh);
 err_erase_xa:
@@ -307,12 +266,199 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
 	module_put(fh->ops->owner);
 err_fput:
 	fput(file);
-err_shrink:
+
+	return err;
+}
+
+static void luo_file_free(struct luo_file *luo_file)
+{
+	struct liveupdate_file_handler *fh = luo_file->fh;
+
+	list_del(&luo_file->list);
+	luo_flb_file_unpreserve(fh);
+	xa_erase(&luo_preserved_files, luo_get_id(fh, luo_file->file));
+	module_put(fh->ops->owner);
+	fput(luo_file->file);
+	mutex_destroy(&luo_file->mutex);
+	kfree(luo_file);
+}
+
+/*
+ * luo_file_preserve_internal - Preserve one file of a batch.
+ *
+ * Calls the handler's .preserve() and, on success, moves the file from the
+ * batch's pending list to the tail of @file_set->files_list, after which it
+ * is visible to liveupdate_get_token_outgoing().
+ */
+static int luo_file_preserve_internal(struct luo_file_set *file_set,
+				      struct luo_file *luo_file)
+{
+	struct liveupdate_file_op_args args = {0};
+	int err;
+
+	args.handler = luo_file->fh;
+	args.session = luo_session_from_file_set(file_set);
+	args.file = luo_file->file;
+	err = luo_file->fh->ops->preserve(&args);
+	if (err)
+		return err;
+
+	luo_file->serialized_data = args.serialized_data;
+	luo_file->private_data = args.private_data;
+	list_move_tail(&luo_file->list, &file_set->files_list);
+	file_set->count++;
+
+	return 0;
+}
+
+static void luo_file_unpreserve_one(struct luo_file_set *file_set,
+				    struct luo_file *luo_file)
+{
+	struct liveupdate_file_op_args args = {0};
+
+	args.handler = luo_file->fh;
+	args.session = luo_session_from_file_set(file_set);
+	args.file = luo_file->file;
+	args.serialized_data = luo_file->serialized_data;
+	args.private_data = luo_file->private_data;
+	luo_file->fh->ops->unpreserve(&args);
+	luo_flb_file_unpreserve(luo_file->fh);
+
+	xa_erase(&luo_preserved_files,
+		 luo_get_id(luo_file->fh, luo_file->file));
+	module_put(luo_file->fh->ops->owner);
+
+	list_del(&luo_file->list);
+	file_set->count--;
+	kho_block_set_shrink(&file_set->block_set, file_set->count);
+
+	fput(luo_file->file);
+	mutex_destroy(&luo_file->mutex);
+	kfree(luo_file);
+}
+
+static int luo_file_level_cmp(void *priv, const struct list_head *a,
+			      const struct list_head *b)
+{
+	const struct luo_file *fa = list_entry(a, struct luo_file, list);
+	const struct luo_file *fb = list_entry(b, struct luo_file, list);
+
+	return fa->fh->level > fb->fh->level;
+}
+
+/**
+ * luo_preserve_files - Preserve a batch of file descriptors.
+ * @file_set:   The file_set to which the preserved files will be added.
+ * @tokens:     Array of @nr unique, user-provided identifiers.
+ * @fds:        Array of @nr file descriptors to be preserved.
+ * @nr:         Number of entries in @tokens and @fds.
+ * @failed_idx: Output; on failure, the index into @tokens/@fds of the entry
+ *              that failed, or @nr if the failure is not specific to an entry.
+ *
+ * The file handler's .preserve() is called in the level ascending order, so a
+ * dependency in the same batch is preserved before the file that needs it,
+ * regardless of the order userspace passed the fds in.
+ *
+ * The operation is atomic: on any failure, the files of this batch that were
+ * already preserved are unpreserved in reverse order, and the file_set is left
+ * as it was before the call.
+ *
+ * On success, LUO takes a reference to each 'struct file' and considers it
+ * under its management until it is unpreserved or finished.
+ *
+ * Context: Called from an ioctl handler with the session mutex held.
+ * Return: 0 on success. Returns a negative errno on failure:
+ *         -EEXIST if a token is already used.
+ *         -EBUSY if a file descriptor is already preserved (in this batch or
+ *                by another session).
+ *         -EBADF if a file descriptor is invalid.
+ *         -ENOSPC if the file_set is full.
+ *         -ENOENT if no compatible handler is found, or a dependency of a
+ *                 file is not preserved.
+ *         -ENOMEM on memory allocation failure.
+ *         Other errors might be returned by .preserve().
+ */
+int luo_preserve_files(struct luo_file_set *file_set, const u64 *tokens,
+		       const int *fds, u32 nr, u32 *failed_idx)
+{
+	struct luo_file *luo_file, *tmp;
+	struct list_head *mark;
+	LIST_HEAD(pending);
+	u32 i;
+	int err;
+
+	*failed_idx = nr;
+
+	err = kho_block_set_grow(&file_set->block_set, file_set->count + nr);
+	if (err)
+		return err;
+
+	for (i = 0; i < nr; i++) {
+		err = luo_file_alloc(file_set, &pending, tokens[i], fds[i]);
+		if (err) {
+			*failed_idx = i;
+			goto err_abort;
+		}
+	}
+
+	list_sort(NULL, &pending, luo_file_level_cmp);
+
+	/* Everything after @mark on files_list belongs to this batch */
+	mark = file_set->files_list.prev;
+	while (!list_empty(&pending)) {
+		luo_file = list_first_entry(&pending, struct luo_file, list);
+		err = luo_file_preserve_internal(file_set, luo_file);
+		if (err) {
+			for (i = 0; i < nr; i++) {
+				if (tokens[i] == luo_file->token) {
+					*failed_idx = i;
+					break;
+				}
+			}
+			goto err_unpreserve;
+		}
+	}
+
+	return 0;
+
+err_unpreserve:
+	/*
+	 * files_list is in dependency order, so nothing before @mark can
+	 * depend on anything after it. Unpreserving the tail in reverse order
+	 * is the same as session teardown, stopped at @mark.
+	 */
+	while (file_set->files_list.prev != mark) {
+		luo_file = list_last_entry(&file_set->files_list,
+					   struct luo_file, list);
+		luo_file_unpreserve_one(file_set, luo_file);
+	}
+err_abort:
+	list_for_each_entry_safe(luo_file, tmp, &pending, list)
+		luo_file_free(luo_file);
 	kho_block_set_shrink(&file_set->block_set, file_set->count);
 
 	return err;
 }
 
+/**
+ * luo_preserve_file - Preserve a single file descriptor.
+ * @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.
+ *
+ * Equivalent to luo_preserve_files() with a batch of one. Any dependency of
+ * @fd must have been preserved by an earlier call.
+ *
+ * Context: Called from an ioctl handler with the session mutex held.
+ * Return: See luo_preserve_files().
+ */
+int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
+{
+	u32 failed_idx;
+
+	return luo_preserve_files(file_set, &token, &fd, 1, &failed_idx);
+}
+
 /**
  * luo_file_unpreserve_files - Unpreserves all files from a file_set.
  * @file_set: The files to be cleaned up.
@@ -320,12 +466,13 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
  * This function serves as the primary cleanup path for a file_set. It is
  * invoked when the userspace agent closes the file_set's file descriptor.
  *
- * For each file, it performs the following cleanup actions:
+ * Files are unpreserved in reverse order of preservation, i.e. in reverse
+ * dependency order. For each file, it performs the following cleanup actions:
  *   1. Calls the handler's .unpreserve() callback to allow the handler to
  *      release any resources it allocated.
  *   2. Removes the file from the file_set's internal tracking list.
  *   3. Releases the reference to the 'struct file' that was taken by
- *      luo_preserve_file() via fput(), returning ownership.
+ *      luo_preserve_files() via fput(), returning ownership.
  *   4. Frees the memory associated with the internal 'struct luo_file'.
  *
  * After all individual files are unpreserved, it frees the contiguous memory
@@ -336,30 +483,9 @@ void luo_file_unpreserve_files(struct luo_file_set *file_set)
 	struct luo_file *luo_file;
 
 	while (!list_empty(&file_set->files_list)) {
-		struct liveupdate_file_op_args args = {0};
-
 		luo_file = list_last_entry(&file_set->files_list,
 					   struct luo_file, list);
-
-		args.handler = luo_file->fh;
-		args.session = luo_session_from_file_set(file_set);
-		args.file = luo_file->file;
-		args.serialized_data = luo_file->serialized_data;
-		args.private_data = luo_file->private_data;
-		luo_file->fh->ops->unpreserve(&args);
-		luo_flb_file_unpreserve(luo_file->fh);
-
-		xa_erase(&luo_preserved_files,
-			 luo_get_id(luo_file->fh, luo_file->file));
-		module_put(luo_file->fh->ops->owner);
-
-		list_del(&luo_file->list);
-		file_set->count--;
-		kho_block_set_shrink(&file_set->block_set, file_set->count);
-
-		fput(luo_file->file);
-		mutex_destroy(&luo_file->mutex);
-		kfree(luo_file);
+		luo_file_unpreserve_one(file_set, luo_file);
 	}
 
 	kho_block_set_destroy(&file_set->block_set);
@@ -956,18 +1082,16 @@ int liveupdate_get_token_outgoing(struct liveupdate_session *s,
 {
 	struct luo_file_set *file_set = luo_file_set_from_session_locked(s);
 	struct luo_file *luo_file;
-	int err = -ENOENT;
 
 	list_for_each_entry(luo_file, &file_set->files_list, list) {
 		if (luo_file->file == file) {
 			if (tokenp)
 				*tokenp = luo_file->token;
-			err = 0;
-			break;
+			return 0;
 		}
 	}
 
-	return err;
+	return -ENOENT;
 }
 EXPORT_SYMBOL_GPL(liveupdate_get_token_outgoing);
 
diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h
index dac6644bfb18..98ff5c629ac0 100644
--- a/kernel/liveupdate/luo_internal.h
+++ b/kernel/liveupdate/luo_internal.h
@@ -102,6 +102,8 @@ 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_files(struct luo_file_set *file_set, const u64 *tokens,
+		       const int *fds, u32 nr, u32 *failed_idx);
 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..7fa389f73f2a 100644
--- a/kernel/liveupdate/luo_session.c
+++ b/kernel/liveupdate/luo_session.c
@@ -278,6 +278,47 @@ static int luo_session_preserve_fd(struct luo_session *session,
 	return err;
 }
 
+static int luo_session_preserve_fds(struct luo_session *session,
+				    struct luo_ucmd *ucmd)
+{
+	struct liveupdate_session_preserve_fds *argp = ucmd->cmd;
+	u64 *tokens __free(kfree) = NULL;
+	int *fds __free(kfree) = NULL;
+	int err;
+
+	if (argp->__reserved)
+		return -EINVAL;
+
+	if (!argp->nr)
+		return -EINVAL;
+
+	fds = memdup_array_user(u64_to_user_ptr(argp->fds), argp->nr,
+				sizeof(*fds));
+	if (IS_ERR(fds))
+		return PTR_ERR(fds);
+
+	tokens = memdup_array_user(u64_to_user_ptr(argp->tokens), argp->nr,
+				   sizeof(*tokens));
+	if (IS_ERR(tokens))
+		return PTR_ERR(tokens);
+
+	mutex_lock(&session->mutex);
+	err = luo_preserve_files(&session->file_set, tokens, fds, argp->nr,
+				 &argp->out_failed_index);
+	mutex_unlock(&session->mutex);
+	if (err) {
+		/* Best effort, the preserve error takes precedence */
+		luo_ucmd_respond(ucmd, sizeof(*argp));
+		return err;
+	}
+
+	err = luo_ucmd_respond(ucmd, sizeof(*argp));
+	if (err)
+		pr_warn("The files were successfully preserved, but response to user failed\n");
+
+	return err;
+}
+
 static int luo_session_retrieve_fd(struct luo_session *session,
 				   struct luo_ucmd *ucmd)
 {
@@ -345,6 +386,7 @@ union ucmd_buffer {
 	struct liveupdate_session_preserve_fd preserve;
 	struct liveupdate_session_retrieve_fd retrieve;
 	struct liveupdate_session_get_name get_name;
+	struct liveupdate_session_preserve_fds preserve_fds;
 };
 
 /* Type of sessions the ioctl applies to. */
@@ -382,6 +424,9 @@ static const struct luo_ioctl_op luo_session_ioctl_ops[] = {
 		 struct liveupdate_session_retrieve_fd, token, LUO_IOCTL_INCOMING),
 	IOCTL_OP(LIVEUPDATE_SESSION_GET_NAME, luo_session_get_name,
 		 struct liveupdate_session_get_name, name, LUO_IOCTL_ALL),
+	IOCTL_OP(LIVEUPDATE_SESSION_PRESERVE_FDS, luo_session_preserve_fds,
+		 struct liveupdate_session_preserve_fds, __reserved,
+		 LUO_IOCTL_OUTGOING),
 };
 
 static bool luo_ioctl_type_valid(struct luo_session *session,
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC PATCH 2/6] mm/memfd_luo: Set Liveupdate level of a memfd file handler
  2026-10-01  0:57 [RFC PATCH 0/6] Introduce file handler dependency level Samiullah Khawaja
  2026-10-01  0:57 ` [RFC PATCH 1/6] liveupdate: " Samiullah Khawaja
@ 2026-10-01  0:57 ` Samiullah Khawaja
  2026-10-01  0:57 ` [RFC PATCH 3/6] iommufd: Set liveupdate file handler level Samiullah Khawaja
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Samiullah Khawaja @ 2026-10-01  0:57 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Alexander Graf
  Cc: Samiullah Khawaja, David Matlack, tarunsahu, open list,
	open list:KEXEC HANDOVER (KHO), open list:KEXEC HANDOVER (KHO)

Set level of the memfd file handler to LIVEUPDATE_LEVEL_MEM as it is a
memory provider.

Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
---
 mm/memfd_luo.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/mm/memfd_luo.c b/mm/memfd_luo.c
index 59de210bee5f..91ddd7ae64b3 100644
--- a/mm/memfd_luo.c
+++ b/mm/memfd_luo.c
@@ -604,6 +604,7 @@ static const struct liveupdate_file_ops memfd_luo_file_ops = {
 static struct liveupdate_file_handler memfd_luo_handler = {
 	.ops = &memfd_luo_file_ops,
 	.compatible = MEMFD_LUO_FH_COMPATIBLE,
+	.level = LIVEUPDATE_LEVEL_MEM,
 };
 
 static int __init memfd_luo_init(void)
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC PATCH 3/6] iommufd: Set liveupdate file handler level
  2026-10-01  0:57 [RFC PATCH 0/6] Introduce file handler dependency level Samiullah Khawaja
  2026-10-01  0:57 ` [RFC PATCH 1/6] liveupdate: " Samiullah Khawaja
  2026-10-01  0:57 ` [RFC PATCH 2/6] mm/memfd_luo: Set Liveupdate level of a memfd file handler Samiullah Khawaja
@ 2026-10-01  0:57 ` Samiullah Khawaja
  2026-10-01  0:57 ` [RFC PATCH 4/6] vfio/pci: Set live update " Samiullah Khawaja
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Samiullah Khawaja @ 2026-10-01  0:57 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Alexander Graf
  Cc: Samiullah Khawaja, David Matlack, tarunsahu, open list,
	open list:KEXEC HANDOVER (KHO), open list:KEXEC HANDOVER (KHO)

Set level of iommufd preservation file handler to
LIVEUPDATE_LEVEL_MAPPER.

Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
---
 drivers/iommu/iommufd/liveupdate.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/iommufd/liveupdate.c b/drivers/iommu/iommufd/liveupdate.c
index 423369e3a8af..2f2ae1a52be4 100644
--- a/drivers/iommu/iommufd/liveupdate.c
+++ b/drivers/iommu/iommufd/liveupdate.c
@@ -351,6 +351,7 @@ static struct liveupdate_file_ops iommufd_ser_file_ops = {
 static struct liveupdate_file_handler iommufd_ser_handler = {
 	.compatible = IOMMUFD_LUO_COMPATIBLE,
 	.ops = &iommufd_ser_file_ops,
+	.level = LIVEUPDATE_LEVEL_MAPPER,
 };
 
 int iommufd_liveupdate_register(void)
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC PATCH 4/6] vfio/pci: Set live update file handler level
  2026-10-01  0:57 [RFC PATCH 0/6] Introduce file handler dependency level Samiullah Khawaja
                   ` (2 preceding siblings ...)
  2026-10-01  0:57 ` [RFC PATCH 3/6] iommufd: Set liveupdate file handler level Samiullah Khawaja
@ 2026-10-01  0:57 ` Samiullah Khawaja
  2026-10-01  0:57 ` [RFC PATCH 5/6] selftests/liveupdate: Add API to preserve a batch of FDs Samiullah Khawaja
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Samiullah Khawaja @ 2026-10-01  0:57 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Alexander Graf
  Cc: Samiullah Khawaja, David Matlack, tarunsahu, open list,
	open list:KEXEC HANDOVER (KHO), open list:KEXEC HANDOVER (KHO)

Set live update file handler to LIVEUPDATE_LEVEL_DEVICE.

Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
---
 drivers/vfio/pci/vfio_pci_liveupdate.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/vfio/pci/vfio_pci_liveupdate.c b/drivers/vfio/pci/vfio_pci_liveupdate.c
index fb2141ee8942..4b8a350b867a 100644
--- a/drivers/vfio/pci/vfio_pci_liveupdate.c
+++ b/drivers/vfio/pci/vfio_pci_liveupdate.c
@@ -335,6 +335,7 @@ static const struct liveupdate_file_ops vfio_pci_liveupdate_file_ops = {
 static struct liveupdate_file_handler vfio_pci_liveupdate_fh = {
 	.ops = &vfio_pci_liveupdate_file_ops,
 	.compatible = VFIO_PCI_LUO_FH_COMPATIBLE,
+	.level = LIVEUPDATE_LEVEL_DEVICE,
 };
 
 int __init vfio_pci_liveupdate_init(void)
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC PATCH 5/6] selftests/liveupdate: Add API to preserve a batch of FDs
  2026-10-01  0:57 [RFC PATCH 0/6] Introduce file handler dependency level Samiullah Khawaja
                   ` (3 preceding siblings ...)
  2026-10-01  0:57 ` [RFC PATCH 4/6] vfio/pci: Set live update " Samiullah Khawaja
@ 2026-10-01  0:57 ` Samiullah Khawaja
  2026-10-01  0:57 ` [RFC PATCH 6/6] iommufd/selftests: Preserve all the FDs in a batch Samiullah Khawaja
  2026-10-04 17:21 ` [RFC PATCH 0/6] Introduce file handler dependency level Pratyush Yadav
  6 siblings, 0 replies; 8+ messages in thread
From: Samiullah Khawaja @ 2026-10-01  0:57 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Alexander Graf
  Cc: Samiullah Khawaja, David Matlack, tarunsahu, open list,
	open list:KEXEC HANDOVER (KHO), open list:KEXEC HANDOVER (KHO)

Add luo_session_preserve_fds() that can be used to preserve a batch of
FDs using the LIVEUPDATE_SESSION_PRESERVE_FDS ioctl.

Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
---
 .../liveupdate/lib/include/libliveupdate.h    |  2 ++
 .../selftests/liveupdate/lib/lu_utils.c       | 20 +++++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/tools/testing/selftests/liveupdate/lib/include/libliveupdate.h b/tools/testing/selftests/liveupdate/lib/include/libliveupdate.h
index fa07fed08364..9aaf6f28ef56 100644
--- a/tools/testing/selftests/liveupdate/lib/include/libliveupdate.h
+++ b/tools/testing/selftests/liveupdate/lib/include/libliveupdate.h
@@ -29,6 +29,8 @@ int luo_get_session_name(int session_fd, char *name, size_t name_len);
 
 int luo_ensure_nofile_limit(long min_limit);
 int luo_session_preserve_fd(int session_fd, int fd, __u64 token);
+int luo_session_preserve_fds(int session_fd, const int *fds,
+			     const __u64 *tokens, __u32 nr, __u32 *failed_idx);
 int luo_session_retrieve_fd(int session_fd, __u64 token);
 
 int create_and_preserve_memfd(int session_fd, int token, const char *data);
diff --git a/tools/testing/selftests/liveupdate/lib/lu_utils.c b/tools/testing/selftests/liveupdate/lib/lu_utils.c
index 74d41115c281..1290f27ff004 100644
--- a/tools/testing/selftests/liveupdate/lib/lu_utils.c
+++ b/tools/testing/selftests/liveupdate/lib/lu_utils.c
@@ -93,6 +93,26 @@ int luo_session_preserve_fd(int session_fd, int fd, __u64 token)
 	return 0;
 }
 
+int luo_session_preserve_fds(int session_fd, const int *fds,
+			     const __u64 *tokens, __u32 nr, __u32 *failed_idx)
+{
+	struct liveupdate_session_preserve_fds arg = {
+		.size = sizeof(arg),
+		.nr = nr,
+		.fds = (__u64)(uintptr_t)fds,
+		.tokens = (__u64)(uintptr_t)tokens,
+	};
+	int ret = 0;
+
+	if (ioctl(session_fd, LIVEUPDATE_SESSION_PRESERVE_FDS, &arg))
+		ret = -errno;
+
+	if (failed_idx)
+		*failed_idx = arg.out_failed_index;
+
+	return ret;
+}
+
 int luo_session_retrieve_fd(int session_fd, __u64 token)
 {
 	struct liveupdate_session_retrieve_fd arg = {
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC PATCH 6/6] iommufd/selftests: Preserve all the FDs in a batch
  2026-10-01  0:57 [RFC PATCH 0/6] Introduce file handler dependency level Samiullah Khawaja
                   ` (4 preceding siblings ...)
  2026-10-01  0:57 ` [RFC PATCH 5/6] selftests/liveupdate: Add API to preserve a batch of FDs Samiullah Khawaja
@ 2026-10-01  0:57 ` Samiullah Khawaja
  2026-10-04 17:21 ` [RFC PATCH 0/6] Introduce file handler dependency level Pratyush Yadav
  6 siblings, 0 replies; 8+ messages in thread
From: Samiullah Khawaja @ 2026-10-01  0:57 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Alexander Graf
  Cc: Samiullah Khawaja, David Matlack, tarunsahu, open list,
	open list:KEXEC HANDOVER (KHO), open list:KEXEC HANDOVER (KHO)

Use the luo_session_preserve_fds() to preserve vfio cdev, iommufd and
memfd together in a batch.

Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
---
 .../iommu/iommufd_liveupdate_kexec_test.c     | 27 ++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/iommu/iommufd_liveupdate_kexec_test.c b/tools/testing/selftests/iommu/iommufd_liveupdate_kexec_test.c
index 26c7e15b6187..3ce282fc1a33 100644
--- a/tools/testing/selftests/iommu/iommufd_liveupdate_kexec_test.c
+++ b/tools/testing/selftests/iommu/iommufd_liveupdate_kexec_test.c
@@ -153,6 +153,9 @@ static void setup_iommufd(int iommufd, int memfd, int cdev_fd)
 static void before_kexec(int luo_fd)
 {
 	int iommufd, cdev_fd, memfd, session;
+	__u64 tokens[3];
+	__u32 failed;
+	int fds[3];
 
 	create_state_file(luo_fd, state_session, STATE_TOKEN, /*next_stage=*/2);
 
@@ -174,9 +177,27 @@ static void before_kexec(int luo_fd)
 	if (!luo_session_preserve_fd(session, iommufd, IOMMUFD_TOKEN))
 		fail_exit("Preserving iommufd without memfd should fail");
 
-	test_luo_session_preserve_fd(session, memfd, MEMFD_TOKEN);
-	test_luo_session_preserve_fd(session, iommufd, IOMMUFD_TOKEN);
-	test_luo_session_preserve_fd(session, cdev_fd, CDEV_TOKEN);
+	/*
+	 * Batch without iommufd: memfd is preserved first, then cdev fails.
+	 * The whole batch must be rolled back, including the memfd.
+	 */
+	fds[0] = cdev_fd;
+	tokens[0] = CDEV_TOKEN;
+	fds[1] = memfd;
+	tokens[1] = MEMFD_TOKEN;
+	if (!luo_session_preserve_fds(session, fds, tokens, 2, &failed))
+		fail_exit("Batch preserve without iommufd should fail");
+	ksft_assert(failed == 0);
+
+	/* Full batch, passed in reverse dependency order. */
+	fds[0] = cdev_fd;
+	tokens[0] = CDEV_TOKEN;
+	fds[1] = iommufd;
+	tokens[1] = IOMMUFD_TOKEN;
+	fds[2] = memfd;
+	tokens[2] = MEMFD_TOKEN;
+	if (luo_session_preserve_fds(session, fds, tokens, 3, &failed))
+		fail_exit("Batch preserve failed at index %u", failed);
 
 	close(session);
 	session = luo_create_session(luo_fd, iommufd_session);
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH 0/6] Introduce file handler dependency level
  2026-10-01  0:57 [RFC PATCH 0/6] Introduce file handler dependency level Samiullah Khawaja
                   ` (5 preceding siblings ...)
  2026-10-01  0:57 ` [RFC PATCH 6/6] iommufd/selftests: Preserve all the FDs in a batch Samiullah Khawaja
@ 2026-10-04 17:21 ` Pratyush Yadav
  6 siblings, 0 replies; 8+ messages in thread
From: Pratyush Yadav @ 2026-10-04 17:21 UTC (permalink / raw)
  To: Samiullah Khawaja
  Cc: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Alexander Graf,
	David Matlack, tarunsahu, open list,
	open list:KEXEC HANDOVER (KHO), open list:KEXEC HANDOVER (KHO)

Hi Sami,

I've skimmed the patches. I didn't dive too deep into the code, but here
is at least my first reaction.

On Thu, Oct 01 2026, Samiullah Khawaja wrote:

> LUO allows preservation of FDs into sessions. An FD can depend on other
> FDs, and for some FDs this can mean the dependency must be preserved
> before it due to various reasons including immutability and performance.
> See discussion on FD dependency patch series [1] and documentation [2]
> for details. Also see the Liveupdate IOMMU [3] and guest_memfd
> preservation [4] patch series for examples. These dependencies are
> enforced by the file handlers, and userspace is responsible for
> preserving the FDs in the correct order.
>
> This RFC proposes a mechanism that allows userspace to preserve the FDs
> as a batch, and the kernel preserves them in the required order. This
> allows the VMM to preserve a bag of FDs without worrying about the
> order. A new ioctl is added that allows userspace to provide an array of
> FDs and tokens for preservation. This gives the kernel the token and the
> intent to preserve every FD in the batch up front.
>
> This RFC introduces the concept of file handler levels. Each file
> handler offers a certain type of resource or functionality that relates
> to other file handlers. These can be represented by levels. This RFC
> adds the following levels and more can be added later:
>
>  - Default (no level set)
>  - Memory Providers
>  - Memory Mappers (or users)
>  - Devices
>
> The levels are optional static configurations of how the file handlers
> relate to each other. Each level represents a class of file handler,
> which fixes the order of preservation between them.
>
> The levels are spaced out to allow addition of new levels. LUO can use
> these levels to deduce the order of preservation of a batch of FDs.

I think you need to explain what problem you actually solve here.

This seems like a lot of complexity to essentially turn file handler
dependencies into heuristics. Because you basically assign a "priority
number" to each file type. But dependencies can really be complicated
and I think modelling them as absolute integers is going to paint us in
a corner real quick.

And I don't get what this buys us. Why not take the much much simpler
path where a file handler just rejects a file if its dependency isn't
there? This would force userspace to preserve files in the right order.

And userspace doesn't necessarily have to to anything complicated
either. It just needs to write the code in a way that a memfd is
preserved before its iommufd. So we leave it up to userspace to figure
out the order, and in the kernel we only _enforce_ it.

This also lets us express the real dependencies and we don't have to do
the dance of giving each file type a number and trying to make sure the
number sits in the right place on the list for all use cases.

Or, if you _don't_ want to burden userspace with this work, why not take
the files in any order and do the final check at freeze()?

>
> The batch is atomic: either all FDs are preserved or none are, and on
> failure the index of the failing FD is returned to userspace. The
> existing LIVEUPDATE_SESSION_PRESERVE_FD ioctl is unchanged and behaves
> as a batch of one. Note that this does not break compatibility and
> userspace can still attempt to preserve FDs individually using the
> existing preservation ioctl.
>
> The patch series builds on top of the Liveupdate IOMMU series [3] to
> demonstrate the FD dependency. The full tree, including the
> dependencies, is available at:
> https://github.com/samikhawaja/linux/tree/luo/fd-dependency-rfc
>
> I will present this at the Live Update MC at LPC 2026. I will also talk
> about alternative solutions I considered.
>
> Future work:
>
>  - Allow file handlers to be preserved at multiple levels to allow
>    resolving circular dependencies.
>
> Looking forward to your feedback on this.
>
> [1] https://lore.kernel.org/all/alrDpAMknlYN9jL9@google.com/#t
> [2] https://lore.kernel.org/all/20260910173659.1945246-2-skhawaja@google.com/
> [3] https://lore.kernel.org/all/20260921004834.2601285-1-skhawaja@google.com/
> [4] https://lore.kernel.org/all/20260728121138.1103610-9-tarunsahu@google.com/
>
> Samiullah Khawaja (6):
>   liveupdate: Introduce file handler dependency level
>   mm/memfd_luo: Set Liveupdate level of a memfd file handler
>   iommufd: Set liveupdate file handler level
>   vfio/pci: Set live update file handler level
>   selftests/liveupdate: Add API to preserve a batch of FDs
>   iommufd/selftests: Preserve all the FDs in a batch
>
>  drivers/iommu/iommufd/liveupdate.c            |   1 +
>  drivers/vfio/pci/vfio_pci_liveupdate.c        |   1 +
>  include/linux/liveupdate.h                    |  24 ++
>  include/uapi/linux/liveupdate.h               |  39 +++
>  kernel/liveupdate/luo_file.c                  | 316 ++++++++++++------
>  kernel/liveupdate/luo_internal.h              |   2 +
>  kernel/liveupdate/luo_session.c               |  45 +++
>  mm/memfd_luo.c                                |   1 +
>  .../iommu/iommufd_liveupdate_kexec_test.c     |  27 +-
>  .../liveupdate/lib/include/libliveupdate.h    |   2 +
>  .../selftests/liveupdate/lib/lu_utils.c       |  20 ++
>  11 files changed, 379 insertions(+), 99 deletions(-)
>
>
> base-commit: 945d61765894dda2f0344de50cb1ade2e51b66fd

-- 
Regards,
Pratyush Yadav

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-10-04 17:21 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-01  0:57 [RFC PATCH 0/6] Introduce file handler dependency level Samiullah Khawaja
2026-10-01  0:57 ` [RFC PATCH 1/6] liveupdate: " Samiullah Khawaja
2026-10-01  0:57 ` [RFC PATCH 2/6] mm/memfd_luo: Set Liveupdate level of a memfd file handler Samiullah Khawaja
2026-10-01  0:57 ` [RFC PATCH 3/6] iommufd: Set liveupdate file handler level Samiullah Khawaja
2026-10-01  0:57 ` [RFC PATCH 4/6] vfio/pci: Set live update " Samiullah Khawaja
2026-10-01  0:57 ` [RFC PATCH 5/6] selftests/liveupdate: Add API to preserve a batch of FDs Samiullah Khawaja
2026-10-01  0:57 ` [RFC PATCH 6/6] iommufd/selftests: Preserve all the FDs in a batch Samiullah Khawaja
2026-10-04 17:21 ` [RFC PATCH 0/6] Introduce file handler dependency level Pratyush Yadav

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®