summaryrefslogtreecommitdiff
path: root/src/partition
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-03-26 16:26:32 +0100
committerLennart Poettering <lennart@poettering.net>2021-04-20 18:53:15 +0200
commita73b2ad041469bf20e3771725dcf70069451e116 (patch)
tree080e81e014dfdc50d244d291b7d5664d73cf3779 /src/partition
parentee7561d014d073944779e155271d7042d7ea5572 (diff)
downloadsystemd-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.c45
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();