* [PATCH 0/6] liveupdate: Fix module unloading and unregister API
@ 2026-03-17 2:50 Pasha Tatashin
2026-03-17 2:50 ` [PATCH 1/6] liveupdate: Protect file handler list with rwsem Pasha Tatashin
` (5 more replies)
0 siblings, 6 replies; 12+ messages in thread
From: Pasha Tatashin @ 2026-03-17 2:50 UTC (permalink / raw)
To: pasha.tatashin, rppt, pratyush, linux-kernel, dmatlack, akpm,
linux-mm
This patch series addresses an issue with how LUO handles module
reference counting and unregistration during a module unload (e.g.,
via rmmod).
Currently, modules that register live update file handlers are pinned
for the entire duration they are registered. This prevents the modules
from being unloaded gracefully, even when no live update session is in
progress.
Furthermore, if a module is forcefully unloaded, the unregistration
functions return an error (e.g. -EBUSY) if a session is active, which
is ignored by the kernel's module unload path, leaving dangling
pointers in the LUO global lists.
As pointed out by Jason Gunthorpe and Alex Williamson during the review
of the VFIO PCI live update patches [1]:
> "destroy" functions that fail are evil. :)
> IMHO blow up the kernel or something in the core code, you can't stop
> module unloading once it starts so it is pointless to propagate this
To resolve these issues, this series introduces the following changes:
1. Adds read-write semaphores (luo_file_handler_lock, luo_flb_lock, and
a per-handler flb_lock) to protect the registration lists. This allows
highly scalable concurrent access for file preservation without
blocking, while still preventing traversal races during module unload.
2. Defers module reference counting (try_module_get / module_put)
so that modules are only pinned when their handlers or FLBs are
actively used in a live update session. This allows the core kernel
module code to correctly reject an unload attempt (-EWOULDBLOCK)
only when a session is actively running.
3. Changes the unregistration functions to return void instead of
an error code. If they fail to unregister due to dangling references,
they print a warning instead of aborting, aligning with standard
kernel destroy/unregister semantics.
4. Removes the global luo_session_quiesce() mechanism. Now that module
references properly handle the usage of file handlers and FLBs
during active sessions, we can safely remove the quiesce/resume logic.
[1] https://lore.kernel.org/all/20260303210733.GG972761@nvidia.com
Pasha Tatashin (6):
liveupdate: Protect file handler list with rwsem
liveupdate: Protect FLB lists with rwsem
liveupdate: Defer file handler module refcounting to active sessions
liveupdate: Defer FLB module refcounting to active sessions
liveupdate: Make unregister functions return void
liveupdate: Remove luo_session_quiesce()
include/linux/liveupdate.h | 16 +++--
kernel/liveupdate/luo_file.c | 118 ++++++++++++++-----------------
kernel/liveupdate/luo_flb.c | 108 ++++++++++++----------------
kernel/liveupdate/luo_internal.h | 2 -
kernel/liveupdate/luo_session.c | 44 ------------
lib/tests/liveupdate.c | 8 +--
6 files changed, 113 insertions(+), 183 deletions(-)
--
2.53.0.851.ga537e3e6e9-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/6] liveupdate: Protect file handler list with rwsem
2026-03-17 2:50 [PATCH 0/6] liveupdate: Fix module unloading and unregister API Pasha Tatashin
@ 2026-03-17 2:50 ` Pasha Tatashin
2026-03-17 2:50 ` [PATCH 2/6] liveupdate: Protect FLB lists " Pasha Tatashin
` (4 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Pasha Tatashin @ 2026-03-17 2:50 UTC (permalink / raw)
To: pasha.tatashin, rppt, pratyush, linux-kernel, dmatlack, akpm,
linux-mm
Because liveupdate file handlers will eventually no longer hold a
module reference when registered, we must ensure that the access to
the handler list is protected against concurrent module unloading.
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
kernel/liveupdate/luo_file.c | 61 +++++++++++++++++++++---------------
1 file changed, 35 insertions(+), 26 deletions(-)
diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index 5acee4174bf0..6a0ae29c6a24 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -112,6 +112,7 @@
#include <linux/string.h>
#include "luo_internal.h"
+static DECLARE_RWSEM(luo_file_handler_lock);
static LIST_HEAD(luo_file_handler_list);
/* 2 4K pages, give space for 128 files per file_set */
@@ -277,10 +278,12 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
goto err_fput;
err = -ENOENT;
- list_private_for_each_entry(fh, &luo_file_handler_list, list) {
- if (fh->ops->can_preserve(fh, file)) {
- err = 0;
- break;
+ scoped_guard(rwsem_read, &luo_file_handler_lock) {
+ list_private_for_each_entry(fh, &luo_file_handler_list, list) {
+ if (fh->ops->can_preserve(fh, file)) {
+ err = 0;
+ break;
+ }
}
}
@@ -777,10 +780,12 @@ int luo_file_deserialize(struct luo_file_set *file_set,
bool handler_found = false;
struct luo_file *luo_file;
- list_private_for_each_entry(fh, &luo_file_handler_list, list) {
- if (!strcmp(fh->compatible, file_ser[i].compatible)) {
- handler_found = true;
- break;
+ scoped_guard(rwsem_read, &luo_file_handler_lock) {
+ list_private_for_each_entry(fh, &luo_file_handler_list, list) {
+ if (!strcmp(fh->compatible, file_ser[i].compatible)) {
+ handler_found = true;
+ break;
+ }
}
}
@@ -850,25 +855,27 @@ int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
if (!luo_session_quiesce())
return -EBUSY;
- /* Check for duplicate compatible strings */
- list_private_for_each_entry(fh_iter, &luo_file_handler_list, list) {
- if (!strcmp(fh_iter->compatible, fh->compatible)) {
- pr_err("File handler registration failed: Compatible string '%s' already registered.\n",
- fh->compatible);
- err = -EEXIST;
+ scoped_guard(rwsem_write, &luo_file_handler_lock) {
+ /* Check for duplicate compatible strings */
+ list_private_for_each_entry(fh_iter, &luo_file_handler_list, list) {
+ if (!strcmp(fh_iter->compatible, fh->compatible)) {
+ pr_err("File handler registration failed: Compatible string '%s' already registered.\n",
+ fh->compatible);
+ err = -EEXIST;
+ goto err_resume;
+ }
+ }
+
+ /* Pin the module implementing the handler */
+ if (!try_module_get(fh->ops->owner)) {
+ err = -EAGAIN;
goto err_resume;
}
- }
- /* Pin the module implementing the handler */
- if (!try_module_get(fh->ops->owner)) {
- err = -EAGAIN;
- goto err_resume;
+ INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, flb_list));
+ INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, list));
+ list_add_tail(&ACCESS_PRIVATE(fh, list), &luo_file_handler_list);
}
-
- INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, flb_list));
- INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, list));
- list_add_tail(&ACCESS_PRIVATE(fh, list), &luo_file_handler_list);
luo_session_resume();
liveupdate_test_register(fh);
@@ -909,10 +916,12 @@ int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
if (!luo_session_quiesce())
goto err_register;
- if (!list_empty(&ACCESS_PRIVATE(fh, flb_list)))
- goto err_resume;
+ scoped_guard(rwsem_write, &luo_file_handler_lock) {
+ if (!list_empty(&ACCESS_PRIVATE(fh, flb_list)))
+ goto err_resume;
- list_del(&ACCESS_PRIVATE(fh, list));
+ list_del(&ACCESS_PRIVATE(fh, list));
+ }
module_put(fh->ops->owner);
luo_session_resume();
--
2.53.0.851.ga537e3e6e9-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/6] liveupdate: Protect FLB lists with rwsem
2026-03-17 2:50 [PATCH 0/6] liveupdate: Fix module unloading and unregister API Pasha Tatashin
2026-03-17 2:50 ` [PATCH 1/6] liveupdate: Protect file handler list with rwsem Pasha Tatashin
@ 2026-03-17 2:50 ` Pasha Tatashin
2026-03-17 2:50 ` [PATCH 3/6] liveupdate: Defer file handler module refcounting to active sessions Pasha Tatashin
` (3 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Pasha Tatashin @ 2026-03-17 2:50 UTC (permalink / raw)
To: pasha.tatashin, rppt, pratyush, linux-kernel, dmatlack, akpm,
linux-mm
Because liveupdate FLB objects will soon drop their persistent module
references when registered, list traversals must be protected against
concurrent module unloading.
Introduce two read-write semaphores to provide this protection:
1. A global luo_flb_lock protects the global registry of FLBs.
2. A per-handler flb_lock protects the handler's specific list of FLB
dependencies.
Read locks are used during concurrent list traversals (e.g., during
preservation and serialization). Write locks are taken during registration
and unregistration. When both locks are required, the global luo_flb_lock
is strictly acquired before the per-handler flb_lock to prevent deadlocks.
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
include/linux/liveupdate.h | 3 +++
kernel/liveupdate/luo_flb.c | 16 ++++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/include/linux/liveupdate.h b/include/linux/liveupdate.h
index dd11fdc76a5f..8394fb2d8774 100644
--- a/include/linux/liveupdate.h
+++ b/include/linux/liveupdate.h
@@ -12,6 +12,7 @@
#include <linux/kho/abi/luo.h>
#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/rwsem.h>
#include <linux/types.h>
#include <uapi/linux/liveupdate.h>
@@ -107,6 +108,8 @@ struct liveupdate_file_handler {
struct list_head __private list;
/* A list of FLB dependencies. */
struct list_head __private flb_list;
+ /* Protects flb_list */
+ struct rw_semaphore __private flb_lock;
};
/**
diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c
index f52e8114837e..91910d806d1d 100644
--- a/kernel/liveupdate/luo_flb.c
+++ b/kernel/liveupdate/luo_flb.c
@@ -49,6 +49,7 @@
#include <linux/liveupdate.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/rwsem.h>
#include <linux/slab.h>
#include <linux/unaligned.h>
#include "luo_internal.h"
@@ -70,6 +71,7 @@ struct luo_flb_global {
long count;
};
+static DECLARE_RWSEM(luo_flb_lock);
static struct luo_flb_global luo_flb_global = {
.list = LIST_HEAD_INIT(luo_flb_global.list),
};
@@ -240,6 +242,8 @@ int luo_flb_file_preserve(struct liveupdate_file_handler *fh)
struct luo_flb_link *iter;
int err = 0;
+ guard(rwsem_read)(&ACCESS_PRIVATE(fh, flb_lock));
+
list_for_each_entry(iter, flb_list, list) {
err = luo_flb_file_preserve_one(iter->flb);
if (err)
@@ -272,6 +276,8 @@ void luo_flb_file_unpreserve(struct liveupdate_file_handler *fh)
struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
struct luo_flb_link *iter;
+ guard(rwsem_read)(&ACCESS_PRIVATE(fh, flb_lock));
+
list_for_each_entry_reverse(iter, flb_list, list)
luo_flb_file_unpreserve_one(iter->flb);
}
@@ -292,6 +298,8 @@ void luo_flb_file_finish(struct liveupdate_file_handler *fh)
struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
struct luo_flb_link *iter;
+ guard(rwsem_read)(&ACCESS_PRIVATE(fh, flb_lock));
+
list_for_each_entry_reverse(iter, flb_list, list)
luo_flb_file_finish_one(iter->flb);
}
@@ -355,6 +363,9 @@ int liveupdate_register_flb(struct liveupdate_file_handler *fh,
if (!luo_session_quiesce())
return -EBUSY;
+ guard(rwsem_write)(&luo_flb_lock);
+ guard(rwsem_write)(&ACCESS_PRIVATE(fh, flb_lock));
+
/* Check that this FLB is not already linked to this file handler */
err = -EEXIST;
list_for_each_entry(iter, flb_list, list) {
@@ -444,6 +455,9 @@ int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
if (!luo_session_quiesce())
return -EBUSY;
+ guard(rwsem_write)(&luo_flb_lock);
+ guard(rwsem_write)(&ACCESS_PRIVATE(fh, flb_lock));
+
/* Find and remove the link from the file handler's list */
list_for_each_entry(iter, flb_list, list) {
if (iter->flb == flb) {
@@ -638,6 +652,8 @@ void luo_flb_serialize(void)
struct liveupdate_flb *gflb;
int i = 0;
+ guard(rwsem_read)(&luo_flb_lock);
+
list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) {
struct luo_flb_private *private = luo_flb_get_private(gflb);
--
2.53.0.851.ga537e3e6e9-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/6] liveupdate: Defer file handler module refcounting to active sessions
2026-03-17 2:50 [PATCH 0/6] liveupdate: Fix module unloading and unregister API Pasha Tatashin
2026-03-17 2:50 ` [PATCH 1/6] liveupdate: Protect file handler list with rwsem Pasha Tatashin
2026-03-17 2:50 ` [PATCH 2/6] liveupdate: Protect FLB lists " Pasha Tatashin
@ 2026-03-17 2:50 ` Pasha Tatashin
2026-03-17 16:38 ` David Matlack
2026-03-17 2:50 ` [PATCH 4/6] liveupdate: Defer FLB " Pasha Tatashin
` (2 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Pasha Tatashin @ 2026-03-17 2:50 UTC (permalink / raw)
To: pasha.tatashin, rppt, pratyush, linux-kernel, dmatlack, akpm,
linux-mm
Stop pinning modules indefinitely upon file handler registration.
Instead, dynamically increment the module reference count only when a
live update session actively uses the file handler (e.g., during
preservation or deserialization), and release it when the session ends.
This allows modules providing live update handlers to be gracefully
unloaded when no live update is in progress.
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
kernel/liveupdate/luo_file.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index 6a0ae29c6a24..6b2b49cb375e 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -253,6 +253,7 @@ static bool luo_token_is_used(struct luo_file_set *file_set, u64 token)
* -ENOSPC if the file_set is full.
* -ENOENT if no compatible handler is found.
* -ENOMEM on memory allocation failure.
+ * -ENODEV if the file handler's module is unloading.
* Other erros might be returned by .preserve().
*/
int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
@@ -281,7 +282,10 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
scoped_guard(rwsem_read, &luo_file_handler_lock) {
list_private_for_each_entry(fh, &luo_file_handler_list, list) {
if (fh->ops->can_preserve(fh, file)) {
- err = 0;
+ if (try_module_get(fh->ops->owner))
+ err = 0;
+ else
+ err = -ENODEV;
break;
}
}
@@ -293,7 +297,7 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
err = luo_flb_file_preserve(fh);
if (err)
- goto err_free_files_mem;
+ goto err_module_put;
luo_file = kzalloc_obj(*luo_file);
if (!luo_file) {
@@ -323,6 +327,8 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
kfree(luo_file);
err_flb_unpreserve:
luo_flb_file_unpreserve(fh);
+err_module_put:
+ module_put(fh->ops->owner);
err_free_files_mem:
luo_free_files_mem(file_set);
err_fput:
@@ -365,6 +371,7 @@ void luo_file_unpreserve_files(struct luo_file_set *file_set)
args.private_data = luo_file->private_data;
luo_file->fh->ops->unpreserve(&args);
luo_flb_file_unpreserve(luo_file->fh);
+ module_put(luo_file->fh->ops->owner);
list_del(&luo_file->list);
file_set->count--;
@@ -649,6 +656,7 @@ static void luo_file_finish_one(struct luo_file_set *file_set,
luo_file->fh->ops->finish(&args);
luo_flb_file_finish(luo_file->fh);
+ module_put(luo_file->fh->ops->owner);
}
/**
@@ -783,7 +791,8 @@ int luo_file_deserialize(struct luo_file_set *file_set,
scoped_guard(rwsem_read, &luo_file_handler_lock) {
list_private_for_each_entry(fh, &luo_file_handler_list, list) {
if (!strcmp(fh->compatible, file_ser[i].compatible)) {
- handler_found = true;
+ if (try_module_get(fh->ops->owner))
+ handler_found = true;
break;
}
}
@@ -796,8 +805,10 @@ int luo_file_deserialize(struct luo_file_set *file_set,
}
luo_file = kzalloc_obj(*luo_file);
- if (!luo_file)
+ if (!luo_file) {
+ module_put(fh->ops->owner);
return -ENOMEM;
+ }
luo_file->fh = fh;
luo_file->file = NULL;
@@ -873,6 +884,7 @@ int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
}
INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, flb_list));
+ init_rwsem(&ACCESS_PRIVATE(fh, flb_lock));
INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, list));
list_add_tail(&ACCESS_PRIVATE(fh, list), &luo_file_handler_list);
}
@@ -922,7 +934,6 @@ int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
list_del(&ACCESS_PRIVATE(fh, list));
}
- module_put(fh->ops->owner);
luo_session_resume();
return 0;
--
2.53.0.851.ga537e3e6e9-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/6] liveupdate: Defer FLB module refcounting to active sessions
2026-03-17 2:50 [PATCH 0/6] liveupdate: Fix module unloading and unregister API Pasha Tatashin
` (2 preceding siblings ...)
2026-03-17 2:50 ` [PATCH 3/6] liveupdate: Defer file handler module refcounting to active sessions Pasha Tatashin
@ 2026-03-17 2:50 ` Pasha Tatashin
2026-03-17 2:50 ` [PATCH 5/6] liveupdate: Make unregister functions return void Pasha Tatashin
2026-03-17 2:50 ` [PATCH 6/6] liveupdate: Remove luo_session_quiesce() Pasha Tatashin
5 siblings, 0 replies; 12+ messages in thread
From: Pasha Tatashin @ 2026-03-17 2:50 UTC (permalink / raw)
To: pasha.tatashin, rppt, pratyush, linux-kernel, dmatlack, akpm,
linux-mm
Stop pinning modules indefinitely upon FLB registration.
Instead, dynamically take a module reference when the FLB is actively
used in a session (e.g., during preserve and retrieve) and release it
when the session concludes.
This allows modules providing FLB operations to be cleanly unloaded
when not in active use by the live update orchestrator.
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
kernel/liveupdate/luo_flb.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c
index 91910d806d1d..daa852abdedd 100644
--- a/kernel/liveupdate/luo_flb.c
+++ b/kernel/liveupdate/luo_flb.c
@@ -112,10 +112,15 @@ static int luo_flb_file_preserve_one(struct liveupdate_flb *flb)
struct liveupdate_flb_op_args args = {0};
int err;
+ if (!try_module_get(flb->ops->owner))
+ return -ENODEV;
+
args.flb = flb;
err = flb->ops->preserve(&args);
- if (err)
+ if (err) {
+ module_put(flb->ops->owner);
return err;
+ }
private->outgoing.data = args.data;
private->outgoing.obj = args.obj;
}
@@ -143,6 +148,7 @@ static void luo_flb_file_unpreserve_one(struct liveupdate_flb *flb)
private->outgoing.data = 0;
private->outgoing.obj = NULL;
+ module_put(flb->ops->owner);
}
}
}
@@ -178,12 +184,17 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
if (!found)
return -ENOENT;
+ if (!try_module_get(flb->ops->owner))
+ return -ENODEV;
+
args.flb = flb;
args.data = private->incoming.data;
err = flb->ops->retrieve(&args);
- if (err)
+ if (err) {
+ module_put(flb->ops->owner);
return err;
+ }
private->incoming.obj = args.obj;
private->incoming.retrieved = true;
@@ -217,6 +228,7 @@ static void luo_flb_file_finish_one(struct liveupdate_flb *flb)
private->incoming.data = 0;
private->incoming.obj = NULL;
private->incoming.finished = true;
+ module_put(flb->ops->owner);
}
}
}
@@ -394,11 +406,6 @@ int liveupdate_register_flb(struct liveupdate_file_handler *fh,
goto err_resume;
}
- if (!try_module_get(flb->ops->owner)) {
- err = -EAGAIN;
- goto err_resume;
- }
-
list_add_tail(&private->list, &luo_flb_global.list);
luo_flb_global.count++;
}
@@ -479,7 +486,6 @@ int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
if (!private->users) {
list_del_init(&private->list);
luo_flb_global.count--;
- module_put(flb->ops->owner);
}
luo_session_resume();
@@ -506,7 +512,8 @@ int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
*
* Return: 0 on success, or a negative errno on failure. -ENODATA means no
* incoming FLB data, -ENOENT means specific flb not found in the incoming
- * data, and -EOPNOTSUPP when live update is disabled or not configured.
+ * data, -ENODEV if the FLB's module is unloading, and -EOPNOTSUPP when
+ * live update is disabled or not configured.
*/
int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp)
{
--
2.53.0.851.ga537e3e6e9-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/6] liveupdate: Make unregister functions return void
2026-03-17 2:50 [PATCH 0/6] liveupdate: Fix module unloading and unregister API Pasha Tatashin
` (3 preceding siblings ...)
2026-03-17 2:50 ` [PATCH 4/6] liveupdate: Defer FLB " Pasha Tatashin
@ 2026-03-17 2:50 ` Pasha Tatashin
2026-03-17 8:58 ` kernel test robot
2026-03-17 10:10 ` kernel test robot
2026-03-17 2:50 ` [PATCH 6/6] liveupdate: Remove luo_session_quiesce() Pasha Tatashin
5 siblings, 2 replies; 12+ messages in thread
From: Pasha Tatashin @ 2026-03-17 2:50 UTC (permalink / raw)
To: pasha.tatashin, rppt, pratyush, linux-kernel, dmatlack, akpm,
linux-mm
Change liveupdate_unregister_file_handler and liveupdate_unregister_flb
to return void instead of an error code. If they fail to unregister
due to dangling references, print a warning instead of aborting.
As pointed out by Jason Gunthorpe and Alex Williamson, returning an error
from a "destroy" or unregister function during a module unload is a poor
API choice since the unload cannot be stopped at that point.
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
include/linux/liveupdate.h | 13 ++++++------
kernel/liveupdate/luo_file.c | 27 +++++++++++-------------
kernel/liveupdate/luo_flb.c | 40 ++++++++++--------------------------
lib/tests/liveupdate.c | 8 ++------
4 files changed, 31 insertions(+), 57 deletions(-)
diff --git a/include/linux/liveupdate.h b/include/linux/liveupdate.h
index 8394fb2d8774..293df26b9e7f 100644
--- a/include/linux/liveupdate.h
+++ b/include/linux/liveupdate.h
@@ -231,12 +231,12 @@ bool liveupdate_enabled(void);
int liveupdate_reboot(void);
int liveupdate_register_file_handler(struct liveupdate_file_handler *fh);
-int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh);
+void liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh);
int liveupdate_register_flb(struct liveupdate_file_handler *fh,
struct liveupdate_flb *flb);
-int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
- struct liveupdate_flb *flb);
+void liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
+ struct liveupdate_flb *flb);
int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp);
int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp);
@@ -258,9 +258,8 @@ static inline int liveupdate_register_file_handler(struct liveupdate_file_handle
return -EOPNOTSUPP;
}
-static inline int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
+static inline void liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
{
- return -EOPNOTSUPP;
}
static inline int liveupdate_register_flb(struct liveupdate_file_handler *fh,
@@ -269,8 +268,8 @@ static inline int liveupdate_register_flb(struct liveupdate_file_handler *fh,
return -EOPNOTSUPP;
}
-static inline int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
- struct liveupdate_flb *flb)
+static inline void liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
+ struct liveupdate_flb *flb)
{
return -EOPNOTSUPP;
}
diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index 6b2b49cb375e..0fe2f8be8bd1 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -907,21 +907,17 @@ int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
* reverses the operations of liveupdate_register_file_handler().
*
* It ensures safe removal by checking that:
- * No live update session is currently in progress.
* No FLB registered with this file handler.
*
* If the unregistration fails, the internal test state is reverted.
*
- * Return: 0 Success. -EOPNOTSUPP when live update is not enabled. -EBUSY A live
- * update is in progress, can't quiesce live update or FLB is registred with
- * this file handler.
*/
-int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
+void liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
{
- int err = -EBUSY;
+ bool is_empty;
if (!liveupdate_enabled())
- return -EOPNOTSUPP;
+ return;
liveupdate_test_unregister(fh);
@@ -929,18 +925,19 @@ int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
goto err_register;
scoped_guard(rwsem_write, &luo_file_handler_lock) {
- if (!list_empty(&ACCESS_PRIVATE(fh, flb_list)))
- goto err_resume;
-
- list_del(&ACCESS_PRIVATE(fh, list));
+ is_empty = list_empty(&ACCESS_PRIVATE(fh, flb_list));
+ if (is_empty)
+ list_del(&ACCESS_PRIVATE(fh, list));
}
luo_session_resume();
- return 0;
+ if (!is_empty) {
+ pr_warn("Failed to unregister file handler '%s': FLB list not empty\n",
+ fh->compatible);
+ liveupdate_test_register(fh);
+ }
+ return;
-err_resume:
- luo_session_resume();
err_register:
liveupdate_test_register(fh);
- return err;
}
diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c
index daa852abdedd..23fa6e0c6083 100644
--- a/kernel/liveupdate/luo_flb.c
+++ b/kernel/liveupdate/luo_flb.c
@@ -436,31 +436,17 @@ int liveupdate_register_flb(struct liveupdate_file_handler *fh,
* the FLB is removed from the global registry and the reference to its
* owner module (acquired during registration) is released.
*
- * Context: This function ensures the session is quiesced (no active FDs
- * being created) during the update. It is typically called from a
- * subsystem's module exit function.
- * Return: 0 on success.
- * -EOPNOTSUPP if live update is disabled.
- * -EBUSY if the live update session is active and cannot be quiesced.
- * -ENOENT if the FLB was not found in the file handler's list.
*/
-int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
- struct liveupdate_flb *flb)
+void liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
+ struct liveupdate_flb *flb)
{
struct luo_flb_private *private = luo_flb_get_private(flb);
struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
struct luo_flb_link *iter;
- int err = -ENOENT;
+ bool found = false;
if (!liveupdate_enabled())
- return -EOPNOTSUPP;
-
- /*
- * Ensure the system is quiescent (no active sessions).
- * This acts as a global lock for unregistration.
- */
- if (!luo_session_quiesce())
- return -EBUSY;
+ return;
guard(rwsem_write)(&luo_flb_lock);
guard(rwsem_write)(&ACCESS_PRIVATE(fh, flb_lock));
@@ -470,15 +456,19 @@ int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
if (iter->flb == flb) {
list_del(&iter->list);
kfree(iter);
- err = 0;
+ found = true;
break;
}
}
- if (err)
- goto err_resume;
+ if (!found) {
+ pr_warn("Failed to unregister FLB '%s': not found in file handler '%s'\n",
+ flb->compatible, fh->compatible);
+ return;
+ }
private->users--;
+
/*
* If this is the last file-handler with which we are registred, remove
* from the global list, and relese module reference.
@@ -487,14 +477,6 @@ int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
list_del_init(&private->list);
luo_flb_global.count--;
}
-
- luo_session_resume();
-
- return 0;
-
-err_resume:
- luo_session_resume();
- return err;
}
/**
diff --git a/lib/tests/liveupdate.c b/lib/tests/liveupdate.c
index 496d6ef91a30..5b6abf779f87 100644
--- a/lib/tests/liveupdate.c
+++ b/lib/tests/liveupdate.c
@@ -137,16 +137,12 @@ void liveupdate_test_register(struct liveupdate_file_handler *fh)
void liveupdate_test_unregister(struct liveupdate_file_handler *fh)
{
- int err, i;
+ int i;
for (i = 0; i < TEST_NFLBS; i++) {
struct liveupdate_flb *flb = &test_flbs[i];
- err = liveupdate_unregister_flb(fh, flb);
- if (err) {
- pr_err("Failed to unregister %s %pe\n",
- flb->compatible, ERR_PTR(err));
- }
+ liveupdate_unregister_flb(fh, flb);
}
pr_info("Unregistered %d FLBs from file handler: [%s]\n",
--
2.53.0.851.ga537e3e6e9-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 6/6] liveupdate: Remove luo_session_quiesce()
2026-03-17 2:50 [PATCH 0/6] liveupdate: Fix module unloading and unregister API Pasha Tatashin
` (4 preceding siblings ...)
2026-03-17 2:50 ` [PATCH 5/6] liveupdate: Make unregister functions return void Pasha Tatashin
@ 2026-03-17 2:50 ` Pasha Tatashin
5 siblings, 0 replies; 12+ messages in thread
From: Pasha Tatashin @ 2026-03-17 2:50 UTC (permalink / raw)
To: pasha.tatashin, rppt, pratyush, linux-kernel, dmatlack, akpm,
linux-mm
Now that module references properly handle the usage of file handlers
and FLBs during active sessions, we can safely remove the
luo_session_quiesce() and luo_session_resume() mechanism.
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
kernel/liveupdate/luo_file.c | 31 +++-------------------
kernel/liveupdate/luo_flb.c | 31 +++++-----------------
kernel/liveupdate/luo_internal.h | 2 --
kernel/liveupdate/luo_session.c | 44 --------------------------------
4 files changed, 9 insertions(+), 99 deletions(-)
diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index 0fe2f8be8bd1..bfa0b4868746 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -847,7 +847,6 @@ void luo_file_set_destroy(struct luo_file_set *file_set)
int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
{
struct liveupdate_file_handler *fh_iter;
- int err;
if (!liveupdate_enabled())
return -EOPNOTSUPP;
@@ -858,45 +857,29 @@ int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
return -EINVAL;
}
- /*
- * Ensure the system is quiescent (no active sessions).
- * This prevents registering new handlers while sessions are active or
- * while deserialization is in progress.
- */
- if (!luo_session_quiesce())
- return -EBUSY;
-
scoped_guard(rwsem_write, &luo_file_handler_lock) {
/* Check for duplicate compatible strings */
list_private_for_each_entry(fh_iter, &luo_file_handler_list, list) {
if (!strcmp(fh_iter->compatible, fh->compatible)) {
pr_err("File handler registration failed: Compatible string '%s' already registered.\n",
fh->compatible);
- err = -EEXIST;
- goto err_resume;
+ return -EEXIST;
}
}
/* Pin the module implementing the handler */
- if (!try_module_get(fh->ops->owner)) {
- err = -EAGAIN;
- goto err_resume;
- }
+ if (!try_module_get(fh->ops->owner))
+ return -EAGAIN;
INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, flb_list));
init_rwsem(&ACCESS_PRIVATE(fh, flb_lock));
INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, list));
list_add_tail(&ACCESS_PRIVATE(fh, list), &luo_file_handler_list);
}
- luo_session_resume();
liveupdate_test_register(fh);
return 0;
-
-err_resume:
- luo_session_resume();
- return err;
}
/**
@@ -921,23 +904,15 @@ void liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
liveupdate_test_unregister(fh);
- if (!luo_session_quiesce())
- goto err_register;
-
scoped_guard(rwsem_write, &luo_file_handler_lock) {
is_empty = list_empty(&ACCESS_PRIVATE(fh, flb_list));
if (is_empty)
list_del(&ACCESS_PRIVATE(fh, list));
}
- luo_session_resume();
if (!is_empty) {
pr_warn("Failed to unregister file handler '%s': FLB list not empty\n",
fh->compatible);
liveupdate_test_register(fh);
}
- return;
-
-err_register:
- liveupdate_test_register(fh);
}
diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c
index 23fa6e0c6083..8810595c672d 100644
--- a/kernel/liveupdate/luo_flb.c
+++ b/kernel/liveupdate/luo_flb.c
@@ -346,7 +346,6 @@ int liveupdate_register_flb(struct liveupdate_file_handler *fh,
struct luo_flb_link *link __free(kfree) = NULL;
struct liveupdate_flb *gflb;
struct luo_flb_link *iter;
- int err;
if (!liveupdate_enabled())
return -EOPNOTSUPP;
@@ -367,22 +366,13 @@ int liveupdate_register_flb(struct liveupdate_file_handler *fh,
if (!link)
return -ENOMEM;
- /*
- * Ensure the system is quiescent (no active sessions).
- * This acts as a global lock for registration: no other thread can
- * be in this section, and no sessions can be creating/using FDs.
- */
- if (!luo_session_quiesce())
- return -EBUSY;
-
guard(rwsem_write)(&luo_flb_lock);
guard(rwsem_write)(&ACCESS_PRIVATE(fh, flb_lock));
/* Check that this FLB is not already linked to this file handler */
- err = -EEXIST;
list_for_each_entry(iter, flb_list, list) {
if (iter->flb == flb)
- goto err_resume;
+ return -EEXIST;
}
/*
@@ -390,20 +380,16 @@ int liveupdate_register_flb(struct liveupdate_file_handler *fh,
* is registered
*/
if (!private->users) {
- if (WARN_ON(!list_empty(&private->list))) {
- err = -EINVAL;
- goto err_resume;
- }
+ if (WARN_ON(!list_empty(&private->list)))
+ return -EINVAL;
- if (luo_flb_global.count == LUO_FLB_MAX) {
- err = -ENOSPC;
- goto err_resume;
- }
+ if (luo_flb_global.count == LUO_FLB_MAX)
+ return -ENOSPC;
/* Check that compatible string is unique in global list */
list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) {
if (!strcmp(gflb->compatible, flb->compatible))
- goto err_resume;
+ return -EEXIST;
}
list_add_tail(&private->list, &luo_flb_global.list);
@@ -414,13 +400,8 @@ int liveupdate_register_flb(struct liveupdate_file_handler *fh,
private->users++;
link->flb = flb;
list_add_tail(&no_free_ptr(link)->list, flb_list);
- luo_session_resume();
return 0;
-
-err_resume:
- luo_session_resume();
- return err;
}
/**
diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h
index 8083d8739b09..ec949f91c8c1 100644
--- a/kernel/liveupdate/luo_internal.h
+++ b/kernel/liveupdate/luo_internal.h
@@ -83,8 +83,6 @@ 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);
-bool luo_session_quiesce(void);
-void luo_session_resume(void);
int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd);
void luo_file_unpreserve_files(struct luo_file_set *file_set);
diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
index 783677295640..067ffb54c36a 100644
--- a/kernel/liveupdate/luo_session.c
+++ b/kernel/liveupdate/luo_session.c
@@ -600,47 +600,3 @@ int luo_session_serialize(void)
return err;
}
-
-/**
- * luo_session_quiesce - Ensure no active sessions exist and lock session lists.
- *
- * Acquires exclusive write locks on both incoming and outgoing session lists.
- * It then validates no sessions exist in either list.
- *
- * This mechanism is used during file handler un/registration to ensure that no
- * sessions are currently using the handler, and no new sessions can be created
- * while un/registration is in progress.
- *
- * This prevents registering new handlers while sessions are active or
- * while deserialization is in progress.
- *
- * Return:
- * true - System is quiescent (0 sessions) and locked.
- * false - Active sessions exist. The locks are released internally.
- */
-bool luo_session_quiesce(void)
-{
- down_write(&luo_session_global.incoming.rwsem);
- down_write(&luo_session_global.outgoing.rwsem);
-
- if (luo_session_global.incoming.count ||
- luo_session_global.outgoing.count) {
- up_write(&luo_session_global.outgoing.rwsem);
- up_write(&luo_session_global.incoming.rwsem);
- return false;
- }
-
- return true;
-}
-
-/**
- * luo_session_resume - Unlock session lists and resume normal activity.
- *
- * Releases the exclusive locks acquired by a successful call to
- * luo_session_quiesce().
- */
-void luo_session_resume(void)
-{
- up_write(&luo_session_global.outgoing.rwsem);
- up_write(&luo_session_global.incoming.rwsem);
-}
--
2.53.0.851.ga537e3e6e9-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 5/6] liveupdate: Make unregister functions return void
2026-03-17 2:50 ` [PATCH 5/6] liveupdate: Make unregister functions return void Pasha Tatashin
@ 2026-03-17 8:58 ` kernel test robot
2026-03-17 10:10 ` kernel test robot
1 sibling, 0 replies; 12+ messages in thread
From: kernel test robot @ 2026-03-17 8:58 UTC (permalink / raw)
To: Pasha Tatashin, rppt, pratyush, linux-kernel, dmatlack, akpm,
linux-mm
Cc: oe-kbuild-all
Hi Pasha,
kernel test robot noticed the following build errors:
[auto build test ERROR on akpm-mm/mm-nonmm-unstable]
[also build test ERROR on akpm-mm/mm-everything linus/master v7.0-rc4 next-20260316]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Pasha-Tatashin/liveupdate-Protect-file-handler-list-with-rwsem/20260317-105522
base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-nonmm-unstable
patch link: https://lore.kernel.org/r/20260317025049.494931-6-pasha.tatashin%40soleen.com
patch subject: [PATCH 5/6] liveupdate: Make unregister functions return void
config: x86_64-rhel-9.4-ltp (https://download.01.org/0day-ci/archive/20260317/202603170941.c2zUXqhx-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260317/202603170941.c2zUXqhx-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603170941.c2zUXqhx-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from kernel/kexec_core.c:18:
include/linux/liveupdate.h: In function 'liveupdate_unregister_flb':
>> include/linux/liveupdate.h:274:16: error: 'return' with a value, in function returning void [-Wreturn-mismatch]
274 | return -EOPNOTSUPP;
| ^
include/linux/liveupdate.h:271:20: note: declared here
271 | static inline void liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
vim +/return +274 include/linux/liveupdate.h
cab056f2aae725 Pasha Tatashin 2025-12-18 270
e62bd1ab0687a1 Pasha Tatashin 2026-03-16 271 static inline void liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
cab056f2aae725 Pasha Tatashin 2025-12-18 272 struct liveupdate_flb *flb)
cab056f2aae725 Pasha Tatashin 2025-12-18 273 {
cab056f2aae725 Pasha Tatashin 2025-12-18 @274 return -EOPNOTSUPP;
cab056f2aae725 Pasha Tatashin 2025-12-18 275 }
cab056f2aae725 Pasha Tatashin 2025-12-18 276
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 5/6] liveupdate: Make unregister functions return void
2026-03-17 2:50 ` [PATCH 5/6] liveupdate: Make unregister functions return void Pasha Tatashin
2026-03-17 8:58 ` kernel test robot
@ 2026-03-17 10:10 ` kernel test robot
2026-03-17 13:03 ` Pasha Tatashin
1 sibling, 1 reply; 12+ messages in thread
From: kernel test robot @ 2026-03-17 10:10 UTC (permalink / raw)
To: Pasha Tatashin, rppt, pratyush, linux-kernel, dmatlack, akpm,
linux-mm
Cc: llvm, oe-kbuild-all
Hi Pasha,
kernel test robot noticed the following build warnings:
[auto build test WARNING on akpm-mm/mm-nonmm-unstable]
[also build test WARNING on akpm-mm/mm-everything linus/master v7.0-rc4 next-20260316]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Pasha-Tatashin/liveupdate-Protect-file-handler-list-with-rwsem/20260317-105522
base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-nonmm-unstable
patch link: https://lore.kernel.org/r/20260317025049.494931-6-pasha.tatashin%40soleen.com
patch subject: [PATCH 5/6] liveupdate: Make unregister functions return void
config: x86_64-kexec (https://download.01.org/0day-ci/archive/20260317/202603171111.YBKWkKnp-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260317/202603171111.YBKWkKnp-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603171111.YBKWkKnp-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from kernel/kexec_core.c:18:
>> include/linux/liveupdate.h:274:2: warning: void function 'liveupdate_unregister_flb' should not return a value [-Wreturn-mismatch]
274 | return -EOPNOTSUPP;
| ^ ~~~~~~~~~~~
1 warning generated.
vim +/liveupdate_unregister_flb +274 include/linux/liveupdate.h
cab056f2aae725 Pasha Tatashin 2025-12-18 270
e62bd1ab0687a1 Pasha Tatashin 2026-03-16 271 static inline void liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
cab056f2aae725 Pasha Tatashin 2025-12-18 272 struct liveupdate_flb *flb)
cab056f2aae725 Pasha Tatashin 2025-12-18 273 {
cab056f2aae725 Pasha Tatashin 2025-12-18 @274 return -EOPNOTSUPP;
cab056f2aae725 Pasha Tatashin 2025-12-18 275 }
cab056f2aae725 Pasha Tatashin 2025-12-18 276
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 5/6] liveupdate: Make unregister functions return void
2026-03-17 10:10 ` kernel test robot
@ 2026-03-17 13:03 ` Pasha Tatashin
0 siblings, 0 replies; 12+ messages in thread
From: Pasha Tatashin @ 2026-03-17 13:03 UTC (permalink / raw)
To: kernel test robot
Cc: rppt, pratyush, linux-kernel, dmatlack, akpm, linux-mm, llvm,
oe-kbuild-all
On Tue, Mar 17, 2026 at 6:11 AM kernel test robot <lkp@intel.com> wrote:
>
> Hi Pasha,
>
> kernel test robot noticed the following build warnings:
>
> [auto build test WARNING on akpm-mm/mm-nonmm-unstable]
> [also build test WARNING on akpm-mm/mm-everything linus/master v7.0-rc4 next-20260316]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url: https://github.com/intel-lab-lkp/linux/commits/Pasha-Tatashin/liveupdate-Protect-file-handler-list-with-rwsem/20260317-105522
> base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-nonmm-unstable
> patch link: https://lore.kernel.org/r/20260317025049.494931-6-pasha.tatashin%40soleen.com
> patch subject: [PATCH 5/6] liveupdate: Make unregister functions return void
> config: x86_64-kexec (https://download.01.org/0day-ci/archive/20260317/202603171111.YBKWkKnp-lkp@intel.com/config)
> compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260317/202603171111.YBKWkKnp-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202603171111.YBKWkKnp-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> In file included from kernel/kexec_core.c:18:
> >> include/linux/liveupdate.h:274:2: warning: void function 'liveupdate_unregister_flb' should not return a value [-Wreturn-mismatch]
> 274 | return -EOPNOTSUPP;
> | ^ ~~~~~~~~~~~
> 1 warning generated.
Ah, forgot to update these. Will send v2 soon.
Pasha
>
>
> vim +/liveupdate_unregister_flb +274 include/linux/liveupdate.h
>
> cab056f2aae725 Pasha Tatashin 2025-12-18 270
> e62bd1ab0687a1 Pasha Tatashin 2026-03-16 271 static inline void liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
> cab056f2aae725 Pasha Tatashin 2025-12-18 272 struct liveupdate_flb *flb)
> cab056f2aae725 Pasha Tatashin 2025-12-18 273 {
> cab056f2aae725 Pasha Tatashin 2025-12-18 @274 return -EOPNOTSUPP;
> cab056f2aae725 Pasha Tatashin 2025-12-18 275 }
> cab056f2aae725 Pasha Tatashin 2025-12-18 276
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/6] liveupdate: Defer file handler module refcounting to active sessions
2026-03-17 2:50 ` [PATCH 3/6] liveupdate: Defer file handler module refcounting to active sessions Pasha Tatashin
@ 2026-03-17 16:38 ` David Matlack
2026-03-17 18:32 ` Pasha Tatashin
0 siblings, 1 reply; 12+ messages in thread
From: David Matlack @ 2026-03-17 16:38 UTC (permalink / raw)
To: Pasha Tatashin; +Cc: rppt, pratyush, linux-kernel, akpm, linux-mm
On Mon, Mar 16, 2026 at 7:50 PM Pasha Tatashin
<pasha.tatashin@soleen.com> wrote:
> @@ -281,7 +282,10 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
> scoped_guard(rwsem_read, &luo_file_handler_lock) {
> list_private_for_each_entry(fh, &luo_file_handler_list, list) {
> if (fh->ops->can_preserve(fh, file)) {
> - err = 0;
> + if (try_module_get(fh->ops->owner))
> + err = 0;
> + else
> + err = -ENODEV;
> break;
> }
> }
Does LUO even need to take a reference to the file handler owner?
LUO already takes a reference to the file, and the file should already
be holding a reference to the file's owner, which should (must?) be
the same as the file handler's owner.
For FLB it makes more sense since the FLB's owner is likely not the
same as the file's owner.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/6] liveupdate: Defer file handler module refcounting to active sessions
2026-03-17 16:38 ` David Matlack
@ 2026-03-17 18:32 ` Pasha Tatashin
0 siblings, 0 replies; 12+ messages in thread
From: Pasha Tatashin @ 2026-03-17 18:32 UTC (permalink / raw)
To: David Matlack; +Cc: rppt, pratyush, linux-kernel, akpm, linux-mm
On Tue, Mar 17, 2026 at 12:39 PM David Matlack <dmatlack@google.com> wrote:
>
> On Mon, Mar 16, 2026 at 7:50 PM Pasha Tatashin
> <pasha.tatashin@soleen.com> wrote:
>
> > @@ -281,7 +282,10 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
> > scoped_guard(rwsem_read, &luo_file_handler_lock) {
> > list_private_for_each_entry(fh, &luo_file_handler_list, list) {
> > if (fh->ops->can_preserve(fh, file)) {
> > - err = 0;
> > + if (try_module_get(fh->ops->owner))
> > + err = 0;
> > + else
> > + err = -ENODEV;
> > break;
> > }
> > }
>
> Does LUO even need to take a reference to the file handler owner?
>
> LUO already takes a reference to the file, and the file should already
> be holding a reference to the file's owner, which should (must?) be
> the same as the file handler's owner.
Hi David,
Thanks for review. This is a very good point. I will remove taking
file handler reference entirely.
>
> For FLB it makes more sense since the FLB's owner is likely not the
> same as the file's owner.
+1.
Pasha
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-03-17 18:33 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-17 2:50 [PATCH 0/6] liveupdate: Fix module unloading and unregister API Pasha Tatashin
2026-03-17 2:50 ` [PATCH 1/6] liveupdate: Protect file handler list with rwsem Pasha Tatashin
2026-03-17 2:50 ` [PATCH 2/6] liveupdate: Protect FLB lists " Pasha Tatashin
2026-03-17 2:50 ` [PATCH 3/6] liveupdate: Defer file handler module refcounting to active sessions Pasha Tatashin
2026-03-17 16:38 ` David Matlack
2026-03-17 18:32 ` Pasha Tatashin
2026-03-17 2:50 ` [PATCH 4/6] liveupdate: Defer FLB " Pasha Tatashin
2026-03-17 2:50 ` [PATCH 5/6] liveupdate: Make unregister functions return void Pasha Tatashin
2026-03-17 8:58 ` kernel test robot
2026-03-17 10:10 ` kernel test robot
2026-03-17 13:03 ` Pasha Tatashin
2026-03-17 2:50 ` [PATCH 6/6] liveupdate: Remove luo_session_quiesce() Pasha Tatashin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox