-
Notifications
You must be signed in to change notification settings - Fork 296
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
sysroot: Support boot counting for boot entries #3310
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1776,13 +1776,13 @@ parse_os_release (const char *contents, const char *split) | |
return ret; | ||
} | ||
|
||
/* Generate the filename we will use in /boot/loader/entries for this deployment. | ||
/* Generate the entry name we will use in /boot/loader/entries for this deployment. | ||
* The provided n_deployments should be the total number of target deployments (which | ||
* might be different from the cached value in the sysroot). | ||
*/ | ||
static char * | ||
bootloader_entry_filename (OstreeSysroot *sysroot, guint n_deployments, | ||
OstreeDeployment *deployment) | ||
bootloader_entry_name (OstreeSysroot *sysroot, guint n_deployments, | ||
OstreeDeployment *deployment) | ||
{ | ||
guint index = n_deployments - ostree_deployment_get_index (deployment); | ||
// Allow opt-out to dropping the stateroot in case of compatibility issues. | ||
|
@@ -1792,14 +1792,78 @@ bootloader_entry_filename (OstreeSysroot *sysroot, guint n_deployments, | |
if (use_old_naming) | ||
{ | ||
const char *stateroot = ostree_deployment_get_osname (deployment); | ||
return g_strdup_printf ("ostree-%d-%s.conf", index, stateroot); | ||
return g_strdup_printf ("ostree-%d-%s", index, stateroot); | ||
} | ||
else | ||
{ | ||
return g_strdup_printf ("ostree-%d.conf", index); | ||
return g_strdup_printf ("ostree-%d", index); | ||
} | ||
} | ||
|
||
#ifdef ENABLE_BOOT_COUNT | ||
|
||
#define BOOT_COUNT_MAX_RETRIES 3 | ||
|
||
static gint | ||
bootloader_get_max_boot_tries (OstreeSysroot *self, OstreeDeployment *deployment, | ||
GCancellable *cancellable, GError **error) | ||
{ | ||
g_autofree char *tries_file_path = ostree_deployment_get_boot_tries_relpath (deployment); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmm...one super messy thing here is that at this point we may not have actually written out the deployment's AFAICS, the uapi standard doesn't specify To combine with "make this configurable via sysroot" we could have e.g.:
But OTOH I've been trying to get away from the sysroot configuration for other reasons...so we may need to invent |
||
|
||
glnx_autofd int fd = -1; | ||
if (!ot_openat_ignore_enoent (self->sysroot_fd, tries_file_path, &fd, error)) | ||
return BOOT_COUNT_MAX_RETRIES; | ||
if (fd >= 0) | ||
{ | ||
g_autofree char *origin_contents = glnx_fd_readall_utf8 (fd, NULL, cancellable, error); | ||
if (!origin_contents) | ||
return BOOT_COUNT_MAX_RETRIES; | ||
|
||
return atoi(origin_contents); | ||
} | ||
|
||
return BOOT_COUNT_MAX_RETRIES; | ||
} | ||
|
||
/* Drop all temporary entries in /boot/loader/entries for this deployment, | ||
* which were created during automatic boot assesment | ||
* https://uapi-group.org/specifications/specs/boot_loader_specification/#boot-counting | ||
*/ | ||
static gboolean | ||
bootloader_remove_tmp_entries (int dfd, const char *entry_name, gint max_tries, GCancellable *cancellable, | ||
GError **error) | ||
{ | ||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; | ||
g_autofree char *entry_name_init = g_strdup_printf ("%s+%d", entry_name, max_tries); | ||
|
||
if (!glnx_dirfd_iterator_init_at (dfd, ".", FALSE, &dfd_iter, error)) | ||
return FALSE; | ||
|
||
while (TRUE) | ||
{ | ||
struct dirent *dent = NULL; | ||
|
||
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) | ||
return FALSE; | ||
if (dent == NULL) | ||
break; | ||
|
||
/* Don't remove default boot entry (with +3 suffix) */ | ||
if (g_str_has_prefix (dent->d_name, entry_name_init)) | ||
continue; | ||
|
||
if (g_str_has_prefix (dent->d_name, entry_name)) | ||
{ | ||
if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error)) | ||
return FALSE; | ||
} | ||
|
||
} | ||
|
||
return TRUE; | ||
} | ||
#endif | ||
|
||
/* Given @deployment, prepare it to be booted; basically copying its | ||
* kernel/initramfs into /boot/ostree (if needed) and writing out an entry in | ||
* /boot/loader/entries. | ||
|
@@ -1834,7 +1898,7 @@ install_deployment_kernel (OstreeSysroot *sysroot, int new_bootversion, | |
const char *bootcsum = ostree_deployment_get_bootcsum (deployment); | ||
g_autofree char *bootcsumdir = g_strdup_printf ("ostree/%s-%s", osname, bootcsum); | ||
g_autofree char *bootconfdir = g_strdup_printf ("loader.%d/entries", new_bootversion); | ||
g_autofree char *bootconf_name = bootloader_entry_filename (sysroot, n_deployments, deployment); | ||
g_autofree char *bootconf_name = bootloader_entry_name (sysroot, n_deployments, deployment); | ||
|
||
if (!glnx_shutil_mkdir_p_at (sysroot->boot_fd, bootcsumdir, 0775, cancellable, error)) | ||
return FALSE; | ||
|
@@ -2145,9 +2209,18 @@ install_deployment_kernel (OstreeSysroot *sysroot, int new_bootversion, | |
glnx_autofd int bootconf_dfd = -1; | ||
if (!glnx_opendirat (sysroot->boot_fd, bootconfdir, TRUE, &bootconf_dfd, error)) | ||
return FALSE; | ||
#ifdef ENABLE_BOOT_COUNT | ||
gint max_tries = bootloader_get_max_boot_tries (sysroot, deployment, cancellable, error); | ||
g_autofree char *bootconf_filename = g_strdup_printf ("%s+%d.conf", bootconf_name, max_tries); | ||
|
||
if (!bootloader_remove_tmp_entries(bootconf_dfd, bootconf_name, max_tries, cancellable, error)) | ||
return FALSE; | ||
#else | ||
g_autofree char *bootconf_filename = g_strdup_printf ("%s.conf", bootconf_name); | ||
#endif | ||
|
||
if (!ostree_bootconfig_parser_write_at (ostree_deployment_get_bootconfig (deployment), | ||
bootconf_dfd, bootconf_name, cancellable, error)) | ||
bootconf_dfd, bootconf_filename, cancellable, error)) | ||
return FALSE; | ||
|
||
return TRUE; | ||
|
@@ -4176,14 +4249,22 @@ ostree_sysroot_deployment_set_kargs_in_place (OstreeSysroot *self, OstreeDeploym | |
ostree_bootconfig_parser_set (new_bootconfig, "options", kargs_str); | ||
|
||
g_autofree char *bootconf_name | ||
= bootloader_entry_filename (self, self->deployments->len, deployment); | ||
= bootloader_entry_name (self, self->deployments->len, deployment); | ||
|
||
g_autofree char *bootconfdir = g_strdup_printf ("loader.%d/entries", self->bootversion); | ||
glnx_autofd int bootconf_dfd = -1; | ||
if (!glnx_opendirat (self->boot_fd, bootconfdir, TRUE, &bootconf_dfd, error)) | ||
return FALSE; | ||
#ifdef ENABLE_BOOT_COUNT | ||
gint max_tries = bootloader_get_max_boot_tries (self, deployment, cancellable, error); | ||
g_autofree char *bootconf_filename = g_strdup_printf ("%s+%d.conf", bootconf_name, max_tries); | ||
|
||
if (!ostree_bootconfig_parser_write_at (new_bootconfig, bootconf_dfd, bootconf_name, | ||
if (!bootloader_remove_tmp_entries(bootconf_dfd, bootconf_name, max_tries, cancellable, error)) | ||
return FALSE; | ||
#else | ||
g_autofree char *bootconf_filename = g_strdup_printf ("%s.conf", bootconf_name); | ||
#endif | ||
if (!ostree_bootconfig_parser_write_at (new_bootconfig, bootconf_dfd, bootconf_filename, | ||
cancellable, error)) | ||
return FALSE; | ||
} | ||
|
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.
I think instead of a build-time option this should be a runtime option in the sysroot; something like
or so?
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.
yes, makes sense, will fix. thanks!