diff --git a/src/partition/repart.c b/src/partition/repart.c index af319d2e33c..976d1d538ba 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -4471,8 +4471,43 @@ static int acquire_root_devno( return 0; } +static int find_os_prefix(const char **ret) { + int r; + + assert(ret); + + /* Searches for the right place to look for the OS root. This is relevant in the initrd: in the + * initrd the host OS is typically mounted to /sysroot/ — except in setups where /usr/ is a separate + * partition, in which case it is mounted to /sysusr/usr/ before being moved to /sysroot/usr/. */ + + if (!in_initrd()) { + *ret = NULL; /* no prefix */ + return 0; + } + + r = path_is_mount_point("/sysroot", NULL, 0); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to determine whether /sysroot/ is a mount point, assuming it is not: %m"); + else if (r > 0) { + log_debug("/sysroot/ is a mount point, assuming it's the prefix."); + *ret = "/sysroot"; + return 0; + } + + r = path_is_mount_point("/sysusr/usr", NULL, 0); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to determine whether /sysusr/usr is a mount point, assuming it is not: %m"); + else if (r > 0) { + log_debug("/sysusr/usr/ is a mount point, assuming /sysusr/ is the prefix."); + *ret = "/sysusr"; + return 0; + } + + return -ENOENT; +} + static int find_root(char **ret, int *ret_fd) { - const char *t; + const char *t, *prefix; int r; assert(ret); @@ -4513,12 +4548,16 @@ static int find_root(char **ret, int *ret_fd) { * latter we check for cases where / is a tmpfs and only /usr is an actual persistent block device * (think: volatile setups) */ + r = find_os_prefix(&prefix); + if (r < 0) + return log_error_errno(r, "Failed to determine OS prefix: %m"); + FOREACH_STRING(t, "/", "/usr") { _cleanup_free_ char *j = NULL; const char *p; - if (in_initrd()) { - j = path_join("/sysroot", t); + if (prefix) { + j = path_join(prefix, t); if (!j) return log_oom();