LUO FILE DESCRIPTORS(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… LUO FILE DESCRIPTORS πŸ’…

bestie, this is section 9 of the Kernel API Manual, and honestly? it's giving architecture. periodt.

LUO ships the whole infra situation for keeping specific, stateful file descriptors alive across a kexec-based live update 🫢. The main character goal here is letting workloads β€” think virtual machines rocking vfio, memfd, or iommufd β€” hold onto their essential resources with zero interruption. no cap, that's the whole vibe ✨

The framework is built around a callback-based handler model plus a very well-defined lifecycle for every single preserved file πŸ’–


πŸŽ€ Handler Registration πŸŽ€

Kernel modules that own a specific file type (like memfd, like vfio) register a struct liveupdate_file_handler. That handler hands over a set of callbacks that LUO invokes at different stages of the update process, and the most iconic ones are:

  • can_preserve β€” a lil lightweight vibe check to see if this handler is even compatible with a given struct file πŸ‘€
  • preserve β€” the heavyweight one, queen. saves the file's state and returns an opaque u64 handle. this typically runs while the workload is still active so we can minimize downtime during the actual reboot transition πŸ”₯
  • unpreserve β€” cleans up anything .preserve allocated. gets called if the preservation process gets aborted before the reboot (i.e. session is closed) 🧹
  • freeze β€” the final pre-reboot moment to get the state ready for kexec. we are already in the reboot syscall here, so userspace literally cannot mutate the file anymore πŸ™ˆ
  • unfreeze β€” undoes whatever .freeze did. called if the live update gets aborted after the freeze phase πŸ’€
  • retrieve β€” reconstructs the file in the new kernel from the preserved handle ✨
  • finish β€” final check + cleanup in the new kernel. after a successful finish call, LUO gives up ownership of this file 🫑

🌸 File Preservation Lifecycle β€” the happy path 🌸

  1. Preserve (Normal Operation) β€” a userspace agent preserves files one by one via an ioctl. for each file, luo_preserve_file finds a compatible handler, calls its .preserve operation, and creates an internal struct luo_file to track the live state πŸ’–
  2. Freeze (Pre-Reboot) β€” right before the kexec, luo_file_freeze gets called. it iterates through all preserved files, calls their respective .freeze operation, and serializes their final metadata (compatible string, token, and data handle) into a contiguous memory block for KHO 🧊
  3. Deserialize β€” after kexec, luo_file_deserialize runs when the session gets deserialized (which is when /dev/liveupdate is first opened). it reads the serialized data from the KHO memory region and reconstructs the in-memory list of struct luo_file instances for the new kernel, linking them to their corresponding handlers πŸ¦‹
  4. Retrieve (New Kernel β€” Userspace Ready) β€” the userspace agent can now restore file descriptors by providing a token. luo_retrieve_file searches for the matching token, calls the handler's .retrieve op to re-create the struct file, and returns a new FD. and the best part? files can be retrieved in ANY order πŸ‘‘
  5. Finish (New Kernel β€” Cleanup) β€” once a session retrieval is complete, luo_file_finish is called. it iterates through all the files, invokes their .finish operations for final cleanup, and releases all associated kernel resources 🌈

😭 File Preservation Lifecycle β€” the unhappy paths 😭

  1. Abort Before Reboot β€” if the userspace agent aborts the live update process before calling reboot (like, say, by closing the session file descriptor), the session's release handler calls luo_file_unpreserve_files. this invokes the .unpreserve callback on all preserved files, making sure all allocated resources get cleaned up and the system goes back to a clean state 🧚
  2. Freeze Failure β€” during the reboot syscall, if any handler's .freeze op fails, the .unfreeze op is invoked on all previously successful freezes to roll back their state. the reboot syscall then returns an error to userspace, canceling the live update πŸ’€
  3. Finish Failure β€” in the new kernel, if a handler's .finish op fails, the luo_file_finish operation is aborted. LUO retains ownership of all files within that session, including the ones that weren't even processed yet. the userspace agent can try calling the finish operation again later. and if the issue just cannot be resolved? those resources will be held by LUO until the next live update cycle, at which point they will be discarded πŸ™ˆ
fr fr bestie, read that last one again β€” LUO keeps holding those files, they do not just vanish. lowkey important.

✨ SEE ALSO ✨

Kernel file ./kernel/liveupdate/luo_file.c struct luo_file(9), luo_preserve_file(9), luo_file_unpreserve_files(9), luo_file_freeze(9), luo_file_unfreeze(9), luo_retrieve_file(9), luo_file_finish(9), luo_file_deserialize(9), liveupdate_register_file_handler(9), liveupdate_unregister_file_handler(9)


okay that's the whole page, you ate that πŸ’… this one lives in ./kernel/liveupdate and it's dated October 2026 β€” go forth and preserve some file descriptors, icon πŸŽ€βœ¨

πŸ“¦ where this page comes from