repart: Support volatile-root for finding the root partition

The automatic logic can't always find the original root partition (ex:
if the rootfs is copied to a ext4 fs backed by zram in the initramfs),
so we want to support "/run/systemd/volatile-root" which is a symlink to
the original root partition.

Fix #20610
This commit is contained in:
Kristian Klausen
2021-09-01 21:51:39 +02:00
committed by Lennart Poettering
parent ce380c2f09
commit 54632d2ea4
+29 -12
View File
@@ -4529,6 +4529,7 @@ static int acquire_root_devno(
static int find_root(char **ret, int *ret_fd) {
const char *p;
int r;
_cleanup_free_ char *device = NULL;
assert(ret);
assert(ret_fd);
@@ -4564,20 +4565,36 @@ static int find_root(char **ret, int *ret_fd) {
assert(IN_SET(arg_empty, EMPTY_REFUSE, EMPTY_ALLOW));
/* Let's search for the root device. We look for two cases here: first in /, and then in /usr. The
* latter we check for cases where / is a tmpfs and only /usr is an actual persistent block device
* (think: volatile setups) */
/* If the root mount has been replaced by some form of volatile file system (overlayfs), the
* original root block device node is symlinked in /run/systemd/volatile-root. Let's read that
* here. */
r = readlink_malloc("/run/systemd/volatile-root", &device);
if (r == -ENOENT) { /* volatile-root not found */
/* Let's search for the root device. We look for two cases here: first in /, and then in /usr. The
* latter we check for cases where / is a tmpfs and only /usr is an actual persistent block device
* (think: volatile setups) */
FOREACH_STRING(p, "/", "/usr") {
FOREACH_STRING(p, "/", "/usr") {
r = acquire_root_devno(p, arg_root, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd);
if (r < 0) {
if (r == -EUCLEAN)
return btrfs_log_dev_root(LOG_ERR, r, p);
if (r != -ENODEV)
return log_error_errno(r, "Failed to determine backing device of %s: %m", p);
} else
return 0;
r = acquire_root_devno(p, arg_root, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd);
if (r < 0) {
if (r == -EUCLEAN)
return btrfs_log_dev_root(LOG_ERR, r, p);
if (r != -ENODEV)
return log_error_errno(r, "Failed to determine backing device of %s: %m", p);
} else
return 0;
}
} else if (r < 0)
return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
else {
r = acquire_root_devno(device, NULL, O_RDONLY|O_CLOEXEC, ret, ret_fd);
if (r == -EUCLEAN)
return btrfs_log_dev_root(LOG_ERR, r, device);
if (r < 0)
return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", device);
return 0;
}
return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "Failed to discover root block device.");