struct luo_session_ser currently embeds struct luo_file_set_ser directly by value. Embedding struct luo_file_set_ser couples the session layout's size and field offsets to struct luo_file_set_ser, preventing either structure from appending fields independently across kexec. Convert struct luo_session_ser to hold a DECLARE_KHOSER_PTR pointer to struct luo_file_set_ser instead of embedding it by value. Reserve space for both structures in each session block-set entry, placing struct luo_file_set_ser immediately after struct luo_session_ser, and bump LUO_ABI_COMPATIBLE from luo-v5 to luo-v6. Signed-off-by: Tarun Sahu --- include/linux/kho/abi/luo.h | 9 +++++---- kernel/liveupdate/luo_session.c | 27 ++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/include/linux/kho/abi/luo.h b/include/linux/kho/abi/luo.h index 721949374fa1..f1152470f71a 100644 --- a/include/linux/kho/abi/luo.h +++ b/include/linux/kho/abi/luo.h @@ -61,13 +61,14 @@ #include #include #include +#include #include /* * The LUO state is registered under this KHO entry name. */ #define LUO_KHO_ENTRY_NAME "LUO" -#define LUO_ABI_COMPATIBLE "luo-v5" +#define LUO_ABI_COMPATIBLE "luo-v6" #define LUO_ABI_COMPAT_LEN ALIGN(sizeof(LUO_ABI_COMPATIBLE), 8) /** @@ -133,7 +134,7 @@ static_assert(!IS_ENABLED(CONFIG_64BIT) || * struct luo_session_ser - Represents the serialized metadata for a LUO session. * @name: The unique name of the session, provided by the userspace at * the time of session creation. - * @file_set_ser: Serialized files belonging to this session, + * @file_set_ser: Serialized pointer to the files belonging to this session. * * This structure is used to package session-specific metadata for transfer * between kernels via Kexec Handover. An array of these structures (one per @@ -144,10 +145,10 @@ static_assert(!IS_ENABLED(CONFIG_64BIT) || */ struct luo_session_ser { char name[LIVEUPDATE_SESSION_NAME_LENGTH]; - struct luo_file_set_ser file_set_ser; + DECLARE_KHOSER_PTR(file_set_ser, struct luo_file_set_ser *); }; -static_assert(sizeof(struct luo_session_ser) == 80); +static_assert(sizeof(struct luo_session_ser) == 72); static_assert(!IS_ENABLED(CONFIG_64BIT) || __alignof__(struct luo_session_ser) == 8); diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c index 74bc66929f4b..df667fe15fb2 100644 --- a/kernel/liveupdate/luo_session.c +++ b/kernel/liveupdate/luo_session.c @@ -131,18 +131,21 @@ struct luo_session_global { struct luo_session_header outgoing; }; +#define LUO_SESSION_SER_SIZE (sizeof(struct luo_session_ser) + \ + sizeof(struct luo_file_set_ser)) + static struct luo_session_global luo_session_global = { .incoming = { .list = LIST_HEAD_INIT(luo_session_global.incoming.list), .rwsem = __RWSEM_INITIALIZER(luo_session_global.incoming.rwsem), .block_set = KHO_BLOCK_SET_INIT(luo_session_global.incoming.block_set, - sizeof(struct luo_session_ser)), + LUO_SESSION_SER_SIZE), }, .outgoing = { .list = LIST_HEAD_INIT(luo_session_global.outgoing.list), .rwsem = __RWSEM_INITIALIZER(luo_session_global.outgoing.rwsem), .block_set = KHO_BLOCK_SET_INIT(luo_session_global.outgoing.block_set, - sizeof(struct luo_session_ser)), + LUO_SESSION_SER_SIZE), }, }; @@ -223,14 +226,16 @@ static void luo_session_unfreeze_one(struct luo_session *session, struct luo_session_ser *ser) { guard(mutex)(&session->mutex); - luo_file_unfreeze(&session->file_set, &ser->file_set_ser); + luo_file_unfreeze(&session->file_set, + KHOSER_LOAD_PTR(ser->file_set_ser)); } static int luo_session_freeze_one(struct luo_session *session, struct luo_session_ser *ser) { guard(mutex)(&session->mutex); - return luo_file_freeze(&session->file_set, &ser->file_set_ser); + return luo_file_freeze(&session->file_set, + KHOSER_LOAD_PTR(ser->file_set_ser)); } static int luo_session_release(struct inode *inodep, struct file *filep) @@ -552,6 +557,17 @@ int __init luo_session_setup_incoming(u64 sessions_pa) return 0; } +static struct luo_session_ser *luo_session_ser_init(void *mem) +{ + struct luo_file_set_ser *file_set_ser; + struct luo_session_ser *ser = mem; + + file_set_ser = mem + sizeof(struct luo_session_ser); + KHOSER_STORE_PTR(ser->file_set_ser, file_set_ser); + + return ser; +} + static int luo_session_deserialize_one(struct luo_session_header *sh, struct luo_session_ser *ser) { @@ -575,7 +591,7 @@ static int luo_session_deserialize_one(struct luo_session_header *sh, scoped_guard(mutex, &session->mutex) { err = luo_file_deserialize(&session->file_set, - &ser->file_set_ser); + KHOSER_LOAD_PTR(ser->file_set_ser)); } if (err) { pr_warn("Failed to deserialize files for session [%s] %pe\n", @@ -657,6 +673,7 @@ int luo_session_serialize(void) goto err_undo; } + ser = luo_session_ser_init(ser); err = luo_session_freeze_one(session, ser); if (err) { kho_block_set_it_prev(&it); -- 2.56.0.506.g506a7eabc5-goog