soft-reboot: Also handle /boot#3487
Conversation
So it can be shared with soft reboots. Signed-off-by: Colin Walters <walters@verbum.org>
Closes: ostreedev#3486 Signed-off-by: Colin Walters <walters@verbum.org>
There was a problem hiding this comment.
Code Review
This pull request refactors the /boot mounting logic into a new shared function otcore_mount_boot and uses it in both ostree-prepare-root and the soft-reboot logic. This is a good improvement for code reuse. My review focuses on the new function, suggesting improvements to its error handling and consistency to make it more robust and maintainable.
| gboolean | ||
| otcore_mount_boot (const char *physical_root, const char *deployment, GError **error) | ||
| { | ||
| g_autofree char *boot_loader = g_build_filename (physical_root, "boot/loader", NULL); | ||
| struct stat stbuf; | ||
|
|
||
| /* If /boot is on the same partition, use a bind mount to make it visible | ||
| * at /boot inside the deployment. | ||
| */ | ||
| if (!(lstat (boot_loader, &stbuf) == 0 && S_ISLNK (stbuf.st_mode))) | ||
| return TRUE; | ||
|
|
||
| g_autofree char *target_boot = g_build_filename (deployment, "boot", NULL); | ||
| if (!(lstat (target_boot, &stbuf) == 0 && S_ISDIR (stbuf.st_mode))) | ||
| return TRUE; | ||
|
|
||
| g_autofree char *src_boot = g_build_filename (physical_root, "boot", NULL); | ||
| if (mount (src_boot, target_boot, NULL, MS_BIND | MS_SILENT, NULL) < 0) | ||
| return glnx_throw (error, "failed to bind mount /boot"); | ||
|
|
||
| return TRUE; | ||
| } |
There was a problem hiding this comment.
This new function can be improved in a few ways for robustness and clarity:
- Error Handling: The
lstatcalls don't handle errors correctly. They will silently succeed iflstatfails for reasons other thanENOENT(e.g., permission denied), which could mask underlying issues. It's better to explicitly check forENOENTand treat other errors as fatal. - Error Reporting: The error message for
mountfailure could be more informative by including theerrnostring. Usingglnx_throw_errno_prefixwould achieve this, which is a common pattern in this file. - Naming Consistency: The parameter name
deploymentis inconsistent with the declaration inotcore.h(deploy_path). Renaming it todeploy_pathwould improve consistency with the header and other functions in this module. - Readability: The
if (!(...))expressions are a bit difficult to parse. Breaking them down into separate checks improves readability.
Here is a suggested implementation that addresses these points:
gboolean
otcore_mount_boot (const char *physical_root, const char *deploy_path, GError **error)
{
g_autofree char *boot_loader = g_build_filename (physical_root, "boot/loader", NULL);
struct stat stbuf;
int r;
/* If /boot is on the same partition, use a bind mount to make it visible
* at /boot inside the deployment.
*/
r = lstat (boot_loader, &stbuf);
if (r < 0)
{
if (errno == ENOENT)
return TRUE;
return glnx_throw_errno_prefix (error, "lstat(%s)", boot_loader);
}
if (!S_ISLNK (stbuf.st_mode))
return TRUE;
g_autofree char *target_boot = g_build_filename (deploy_path, "boot", NULL);
r = lstat (target_boot, &stbuf);
if (r < 0)
{
if (errno == ENOENT)
return TRUE;
return glnx_throw_errno_prefix (error, "lstat(%s)", target_boot);
}
if (!S_ISDIR (stbuf.st_mode))
return TRUE;
g_autofree char *src_boot = g_build_filename (physical_root, "boot", NULL);
if (mount (src_boot, target_boot, NULL, MS_BIND | MS_SILENT, NULL) < 0)
return glnx_throw_errno_prefix (error, "failed to bind mount /boot");
return TRUE;
}There was a problem hiding this comment.
The lstat calls don't handle errors correctly. They will silently succeed if lstat fails for reasons other than ENOENT (e.g., permission denied),
Yes, this was true in the original code. Not fatal right now.
Closes: #3486