diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-03-26 16:26:32 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-04-20 18:53:15 +0200 |
commit | a73b2ad041469bf20e3771725dcf70069451e116 (patch) | |
tree | 080e81e014dfdc50d244d291b7d5664d73cf3779 /src/partition | |
parent | ee7561d014d073944779e155271d7042d7ea5572 (diff) | |
download | systemd-a73b2ad041469bf20e3771725dcf70069451e116.tar.gz |
repart: try harder to find OS prefix
This teaches repart to look for the root block device both as the
backing for /sysroot and for /sysusr/usr.
The latter is a new addition, and starts making more sense with the next
commit. It's about supporting systems that are shipped with only a /usr/
fs, but where a root fs is allocated and formatted on first boot via
systemd-repart (or a similar tool). In this case it's useful to be able
to mount the ultimate /usr/ early on without mounting the root fs
right-away (simple because the rootfs might not exist yet, and we need
the repart data encoded in /usr/ to actually format it). Hence, instead
of requiring that we mount /sysroot/ first and /sysroot/usr/ second as
we did so far, let's rearrange things slightly:
1. We mount the /usr/ file system we discover to /sysusr/usr/
2. We mount the root file system we discover to /sysroot/
3. Once both are established we bind mount /sysusr/usr/ to /sysroot/usr/
And that' it. The first two steps can happen in either order, and we can
access /usr/ with or without a rootfs being around.
This commit implements nothing of the above. Instead, it teaches
systemd-repart to check both /sysroot/ and /sysusr/ for repart drop-ins,
and use the first of these hierarchies it finds populated. This way
systemd-repart can be spawned once /usr is mounted and it will work
correctly without root fs having to exist, or we can invoke it when the
root fs is already mounted, where it also will work correctly.
Diffstat (limited to 'src/partition')
-rw-r--r-- | src/partition/repart.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/src/partition/repart.c b/src/partition/repart.c index af319d2e33..976d1d538b 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(); |