-
Notifications
You must be signed in to change notification settings - Fork 331
docs: Add boot-transaction #3499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This fleshes out a bit more details of the boot links.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request adds comprehensive documentation for the ostree boot deployment transaction. The new document, docs/boot-transaction.md
, provides a detailed explanation of the boot process, especially in environments with separate root and boot filesystems. My review focuses on ensuring the accuracy and clarity of this new documentation. I've identified a few areas where the explanation could be more precise to avoid confusion, particularly regarding the structure of boot links and the terminology used to describe the update scenarios. Overall, this is a valuable addition to the project's documentation.
| +-- <hash1>/ | +-- entries/ | ||
| +-- <hash2>/ | +-- ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vertical bars |
in the diagram appear to be remnants of an attempt to visually separate the two filesystem trees, but they are misaligned and make the diagram harder to read. Removing them would improve clarity.
| +-- <hash1>/ | +-- entries/ | |
| +-- <hash2>/ | +-- ... | |
| +-- <hash1>/ +-- entries/ | |
| +-- <hash2>/ +-- ... |
symlinks (`/ostree/boot.{0,1}`) will also include the `bootcsum` in their | ||
target path, as can be seen in the diagram above. The function | ||
`_ostree_sysroot_parse_bootlink()` is used to parse this information from the | ||
symlink. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This paragraph is slightly inaccurate. The bootcsum
is not part of the boot symlink's target path. Instead, it's part of the path to the boot symlink itself, which is what the ostree=
kernel argument points to. The _ostree_sysroot_parse_bootlink()
function then parses this path (not the symlink target) to extract the bootcsum
.
I suggest rephrasing this for clarity and accuracy.
symlinks (`/ostree/boot.{0,1}`) will also include the `bootcsum` in their | |
target path, as can be seen in the diagram above. The function | |
`_ostree_sysroot_parse_bootlink()` is used to parse this information from the | |
symlink. | |
symlinks are referenced by a path that includes the `bootcsum`. This path is | |
passed to the kernel via the `ostree=` argument. The function | |
`_ostree_sysroot_parse_bootlink()` is then used by the initramfs to parse this | |
path and find the correct deployment. |
1. **Create New Bootlinks**: A new temporary directory of symlinks is created (e.g., `/ostree/boot.0.1`) pointing to the new deployment content. | ||
2. **System Sync**: `full_system_sync()` is called to ensure all filesystem changes are persisted to disk. | ||
3. **Atomic Swap**: The primary boot symlink (e.g., `/ostree/boot.0`) is atomically updated to point to the new temporary directory. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The term "temporary directory" here could be misleading. The directory /ostree/boot.0.1
is not temporary; it's one of the two rotating sub-bootversion directories. The "temporary" aspect is an implementation detail of the atomic symlink swap. Clarifying this would improve understanding.
1. **Create New Bootlinks**: A new temporary directory of symlinks is created (e.g., `/ostree/boot.0.1`) pointing to the new deployment content. | |
2. **System Sync**: `full_system_sync()` is called to ensure all filesystem changes are persisted to disk. | |
3. **Atomic Swap**: The primary boot symlink (e.g., `/ostree/boot.0`) is atomically updated to point to the new temporary directory. | |
1. **Create New Bootlinks**: A new directory for boot symlinks is created for the next sub-bootversion (e.g., `/ostree/boot.0.1`), pointing to the new deployment content. | |
2. **System Sync**: `full_system_sync()` is called to ensure all filesystem changes are persisted to disk. | |
3. **Atomic Swap**: The primary boot symlink (e.g., `/ostree/boot.0`) is atomically updated to point to the new directory of boot symlinks. |
|
||
2. **Prepare for Final Swap**: A temporary symbolic link, `/boot/loader.tmp`, is created. It points to the new bootloader directory from the previous step. | ||
|
||
3. **The Critical Sync (`full_system_sync`)**: This is a crucial step for ensuring robustness against crashes. The goal is to ensure all changes from steps 1 & 2 are durably persisted to the physical disk *before* performing the final, non-reversible bootloader switch. To do this, we call `syncfs()` on the root filesystem, and issue an `ioctl(FIFREEZE)` on the `/boot` filesystem. This is a strong synchronization primitive that forces the filesystem to flush all of its data and metadata, including its journal. This is important for filesystems like XFS, as bootloaders often cannot read a "dirty" journal. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3. **The Critical Sync (`full_system_sync`)**: This is a crucial step for ensuring robustness against crashes. The goal is to ensure all changes from steps 1 & 2 are durably persisted to the physical disk *before* performing the final, non-reversible bootloader switch. To do this, we call `syncfs()` on the root filesystem, and issue an `ioctl(FIFREEZE)` on the `/boot` filesystem. This is a strong synchronization primitive that forces the filesystem to flush all of its data and metadata, including its journal. This is important for filesystems like XFS, as bootloaders often cannot read a "dirty" journal. | |
3. **The Critical Sync (`full_system_sync`)**: This is a crucial step for ensuring robustness against crashes. The goal is to ensure all changes from steps 1 & 2 are durably persisted to the physical disk *before* performing the final, non-reversible bootloader switch. To do this, we call `syncfs(/ostree)`, and issue an `ioctl(FIFREEZE)` on the `/boot` filesystem. This is a strong synchronization primitive that forces the filesystem to flush all of its data and metadata, including its journal. This is important for filesystems like XFS, as bootloaders often cannot read a "dirty" journal. |
|
||
4. **The Atomic Switch (`swap_bootloader`)**: With all of the data safely on disk, we can now perform the "point of no return". An atomic `renameat()` is performed to rename `/boot/loader.tmp` to `/boot/loader`. After this point, the bootloader will use the new configuration on the next boot. | ||
|
||
5. **Final Sync**: To be fully robust, another `fsfreeze`/`thaw` cycle is performed on `/boot` to ensure the `renameat()` operation from step 4 is also durably persisted to disk. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- cleanup
This fleshes out a bit more details of the boot links.