Currently, luo_session_setup_outgoing() allocates the session block and sets its physical address in the header immediately. With upcoming dynamic block-based session management, this makes the first block different from the rest. Move the allocation to where it is first needed.
Signed-off-by: Pasha Tatashin <[email protected]> --- kernel/liveupdate/luo_core.c | 4 +- kernel/liveupdate/luo_internal.h | 2 +- kernel/liveupdate/luo_session.c | 68 ++++++++++++++++++++------------ 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c index 9bd649b22029..5dd7f1e7dddb 100644 --- a/kernel/liveupdate/luo_core.c +++ b/kernel/liveupdate/luo_core.c @@ -189,9 +189,7 @@ static int __init luo_fdt_setup(void) if (err) goto exit_free_luo_ser; - err = luo_session_setup_outgoing(&luo_ser->sessions_pa); - if (err) - goto exit_free_luo_ser; + luo_session_setup_outgoing(&luo_ser->sessions_pa); err = luo_flb_setup_outgoing(&luo_ser->flbs_pa); if (err) diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h index 04f31319ccdf..090078ad771c 100644 --- a/kernel/liveupdate/luo_internal.h +++ b/kernel/liveupdate/luo_internal.h @@ -126,7 +126,7 @@ extern struct rw_semaphore luo_register_rwlock; int luo_session_create(const char *name, struct file **filep); int luo_session_retrieve(const char *name, struct file **filep); -int __init luo_session_setup_outgoing(u64 *sessions_pa); +void __init luo_session_setup_outgoing(u64 *sessions_pa); int __init luo_session_setup_incoming(u64 sessions_pa); int luo_session_serialize(void); int luo_session_deserialize(void); diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c index c08733a328bc..339514e8122c 100644 --- a/kernel/liveupdate/luo_session.c +++ b/kernel/liveupdate/luo_session.c @@ -77,15 +77,16 @@ /** * struct luo_session_header - Header struct for managing LUO sessions. - * @count: The number of sessions currently tracked in the @list. - * @list: The head of the linked list of `struct luo_session` instances. - * @rwsem: A read-write semaphore providing synchronized access to the - * session list and other fields in this structure. - * @header_ser: The header data of serialization array. - * @ser: The serialized session data (an array of - * `struct luo_session_ser`). - * @active: Set to true when first initialized. If previous kernel did not - * send session data, active stays false for incoming. + * @count: The number of sessions currently tracked in the @list. + * @list: The head of the linked list of `struct luo_session` instances. + * @rwsem: A read-write semaphore providing synchronized access to the + * session list and other fields in this structure. + * @header_ser: The header data of serialization array. + * @ser: The serialized session data (an array of + * `struct luo_session_ser`). + * @sessions_pa: Points to the location of sessions_pa within struct luo_ser. + * @active: Set to true when first initialized. If previous kernel did not + * send session data, active stays false for incoming. */ struct luo_session_header { long count; @@ -93,6 +94,7 @@ struct luo_session_header { struct rw_semaphore rwsem; struct luo_session_header_ser *header_ser; struct luo_session_ser *ser; + u64 *sessions_pa; bool active; }; @@ -140,10 +142,30 @@ static void luo_session_free(struct luo_session *session) kfree(session); } +static int luo_session_grow_ser(struct luo_session_header *sh) +{ + struct luo_session_header_ser *header_ser; + + if (sh->count == LUO_SESSION_MAX) + return -ENOMEM; + + if (sh->header_ser) + return 0; + + header_ser = kho_alloc_preserve(LUO_SESSION_PGCNT << PAGE_SHIFT); + if (IS_ERR(header_ser)) + return PTR_ERR(header_ser); + + sh->header_ser = header_ser; + sh->ser = (void *)(header_ser + 1); + return 0; +} + static int luo_session_insert(struct luo_session_header *sh, struct luo_session *session) { struct luo_session *it; + int err; guard(rwsem_write)(&sh->rwsem); @@ -152,8 +174,9 @@ static int luo_session_insert(struct luo_session_header *sh, * for new session. */ if (sh == &luo_session_global.outgoing) { - if (sh->count == LUO_SESSION_MAX) - return -ENOMEM; + err = luo_session_grow_ser(sh); + if (err) + return err; } /* @@ -458,21 +481,10 @@ int luo_session_retrieve(const char *name, struct file **filep) return err; } -int __init luo_session_setup_outgoing(u64 *sessions_pa) +void __init luo_session_setup_outgoing(u64 *sessions_pa) { - struct luo_session_header_ser *header_ser; - - header_ser = kho_alloc_preserve(LUO_SESSION_PGCNT << PAGE_SHIFT); - if (IS_ERR(header_ser)) - return PTR_ERR(header_ser); - - *sessions_pa = virt_to_phys(header_ser); - - luo_session_global.outgoing.header_ser = header_ser; - luo_session_global.outgoing.ser = (void *)(header_ser + 1); + luo_session_global.outgoing.sessions_pa = sessions_pa; luo_session_global.outgoing.active = true; - - return 0; } int __init luo_session_setup_incoming(u64 sessions_pa) @@ -573,6 +585,8 @@ int luo_session_serialize(void) int err; guard(rwsem_write)(&sh->rwsem); + *sh->sessions_pa = 0; + list_for_each_entry(session, &sh->list, list) { err = luo_session_freeze_one(session, &sh->ser[i]); if (err) @@ -582,7 +596,11 @@ int luo_session_serialize(void) sizeof(sh->ser[i].name)); i++; } - sh->header_ser->count = sh->count; + + if (sh->header_ser && sh->count > 0) { + sh->header_ser->count = sh->count; + *sh->sessions_pa = virt_to_phys(sh->header_ser); + } return 0; -- 2.53.0

