liveupdate: Reference count outgoing FLB data

Increment the outgoing FLB refcount in liveupdate_flb_get_outgoing() so
that the FLB structure cannot be freed while the caller is actively
using it. Add an additional liveupdate_flb_put_outgoing() function so
the caller can explicitly indicate when it is done using the outgoing
FLB.

During a Live Update, the kernel may need to fetch the outgoing FLB
outside of the scope of a file handler's preserve() and unpreserve()
callbacks. In that situation there is no way for the caller to protect
itself against the outgoing FLB from being freed while it is using it.
Incrementing the reference count in liveupdate_flb_get_outgoing()
ensures it cannot be freed.

This change also aligns the outgoing FLB lifecycle management with the
incoming FLB, since the latter uses the same get/put semantics.

Fixes: cab056f2aa ("liveupdate: luo_flb: introduce File-Lifecycle-Bound global state")
Assisted-by: Gemini:gemini-3-pro-preview
Signed-off-by: David Matlack <dmatlack@google.com>
Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Link: https://patch.msgid.link/20260528174140.1921129-2-dmatlack@google.com
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
This commit is contained in:
David Matlack 2026-05-28 17:41:39 +00:00 committed by Mike Rapoport (Microsoft)
parent 05cf3d87a0
commit 36882f3392
2 changed files with 12 additions and 3 deletions

View File

@ -243,6 +243,7 @@ int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp);
void liveupdate_flb_put_incoming(struct liveupdate_flb *flb);
int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp);
void liveupdate_flb_put_outgoing(struct liveupdate_flb *flb);
#else /* CONFIG_LIVEUPDATE */
@ -292,5 +293,9 @@ static inline int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb,
return -EOPNOTSUPP;
}
static inline void liveupdate_flb_put_outgoing(struct liveupdate_flb *flb)
{
}
#endif /* CONFIG_LIVEUPDATE */
#endif /* _LINUX_LIVEUPDATE_H */

View File

@ -133,7 +133,7 @@ static int luo_flb_file_preserve_one(struct liveupdate_flb *flb)
return 0;
}
static void luo_flb_file_unpreserve_one(struct liveupdate_flb *flb)
void liveupdate_flb_put_outgoing(struct liveupdate_flb *flb)
{
struct luo_flb_private *private = luo_flb_get_private(flb);
@ -264,7 +264,7 @@ int luo_flb_file_preserve(struct liveupdate_file_handler *fh)
exit_err:
list_for_each_entry_continue_reverse(iter, flb_list, list)
luo_flb_file_unpreserve_one(iter->flb);
liveupdate_flb_put_outgoing(iter->flb);
up_read(&luo_register_rwlock);
return err;
@ -289,7 +289,7 @@ void luo_flb_file_unpreserve(struct liveupdate_file_handler *fh)
guard(rwsem_read)(&luo_register_rwlock);
list_for_each_entry_reverse(iter, flb_list, list)
luo_flb_file_unpreserve_one(iter->flb);
liveupdate_flb_put_outgoing(iter->flb);
}
/**
@ -544,6 +544,10 @@ int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp)
return -EOPNOTSUPP;
guard(mutex)(&private->outgoing.lock);
if (!private->outgoing.obj)
return -ENOENT;
refcount_inc(&private->outgoing.count);
*objp = private->outgoing.obj;
return 0;