On Tue, Oct 20 2026, Pasha Tatashin wrote: > Currently, LUO sessions are frozen automatically only inside the > reboot(LINUX_REBOOT_CMD_KEXEC) pathway, where luo_session_serialize() > iterates through all outgoing sessions under global write locks and > freezes them serially during shutdown. Allowing userspace to decide when > to freeze a session once it is done with it (and to freeze multiple > sessions in parallel, since luo_session_freeze() only acquires the > per-session mutex) avoids postponing this work to kexec shutdown and > reduces blackout time. > > Introduce LIVEUPDATE_SESSION_FREEZE on session file descriptors to freeze > a session early. The ioctl runs .freeze() across all preserved files in the > session and serializes their metadata. Once frozen, no additional files can > be added to the session, and subsequent freeze calls return -EBUSY. Freeze > is only valid on outgoing sessions and returns -EINVAL on incoming ones. > > During kexec, sessions that were already frozen early are skipped, while > sessions that did not invoke this ioctl auto-freeze as before. If an > early-frozen session is released before kexec, its files are rolled back > via .unfreeze() before being unpreserved. > > Signed-off-by: Pasha Tatashin <[email protected]> [...] > @@ -218,18 +219,33 @@ static int luo_session_finish_one(struct luo_session > *session) > return luo_file_finish(&session->file_set); > } > > -static void luo_session_unfreeze_one(struct luo_session *session, > - struct luo_session_ser *ser) > +static void luo_session_unserialize_one(struct luo_session *session, > + struct luo_session_ser *ser) > { > guard(mutex)(&session->mutex); > - luo_file_unfreeze(&session->file_set, &ser->file_set_ser); > + if (!session->frozen) > + luo_file_unfreeze(&session->file_set);
"Wait, this looks wrong. If session is not frozen then unfreeze it? Should be the other way round, right?" This was my first reaction until I realized that you only unfreeze _automatically_ frozen sessions. User-frozen sessions stay frozen. Which makes sense, but is not obvious at all. Perhaps rename this to session->user_frozen and add a comment here? With that fixed, feel free to add Reviewed-by: Pratyush Yadav <[email protected]> > + memset(ser, 0, sizeof(*ser)); > } > > -static int luo_session_freeze_one(struct luo_session *session, > - struct luo_session_ser *ser) > +static int luo_session_serialize_one(struct luo_session *session, > + struct luo_session_ser *ser) > { > + int err; > + > guard(mutex)(&session->mutex); > - return luo_file_freeze(&session->file_set, &ser->file_set_ser); > + if (!session->frozen) { > + err = luo_file_freeze(&session->file_set); > + if (err) > + return err; > + } > + > + strscpy(ser->name, session->name, sizeof(ser->name)); > + ser->file_set_ser.count = session->file_set.count; > + ser->file_set_ser.files = > + kho_block_set_head_pa(&session->file_set.block_set); > + > + return 0; > } > > static int luo_session_release(struct inode *inodep, struct file *filep) [...] > @@ -267,6 +286,9 @@ static int luo_session_preserve_fd(struct luo_session > *session, > int err; > > guard(mutex)(&session->mutex); > + if (session->frozen) > + return -EBUSY; > + > err = luo_preserve_file(&session->file_set, argp->token, argp->fd); > if (err) > return err; > @@ -340,11 +362,40 @@ static int luo_session_get_name(struct luo_session > *session, > return luo_ucmd_respond(ucmd, sizeof(*argp)); > } > > +static int luo_session_freeze(struct luo_session *session, > + struct luo_ucmd *ucmd) > +{ > + struct liveupdate_session_freeze *argp = ucmd->cmd; > + int err; > + > + if (argp->reserved) > + return -EINVAL; > + > + guard(mutex)(&session->mutex); > + if (session->frozen) > + return -EBUSY; > + > + err = luo_file_freeze(&session->file_set); > + if (err) > + return err; > + > + err = luo_ucmd_respond(ucmd, sizeof(*argp)); > + if (err) { > + luo_file_unfreeze(&session->file_set); > + return err; > + } > + > + session->frozen = true; > + > + return 0; > +} > + > union ucmd_buffer { > struct liveupdate_session_finish finish; > struct liveupdate_session_preserve_fd preserve; > struct liveupdate_session_retrieve_fd retrieve; > struct liveupdate_session_get_name get_name; > + struct liveupdate_session_freeze freeze; > }; > > /* Type of sessions the ioctl applies to. */ [...] -- Regards, Pratyush Yadav
