diff options
-rw-r--r-- | src/fstab-generator/fstab-generator.c | 5 | ||||
-rw-r--r-- | src/volatile-root/volatile-root.c | 84 |
2 files changed, 71 insertions, 18 deletions
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 30a6d356d0..d1bfa775e4 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -722,10 +722,11 @@ static int add_sysroot_usr_mount(void) { } static int add_volatile_root(void) { + /* Let's add in systemd-remount-volatile.service which will remount the root device to tmpfs if this is - * requested, leaving only /usr from the root mount inside. */ + * requested (or as an overlayfs), leaving only /usr from the root mount inside. */ - if (arg_volatile_mode != VOLATILE_YES) + if (!IN_SET(arg_volatile_mode, VOLATILE_YES, VOLATILE_OVERLAY)) return 0; return generator_add_symlink(arg_dest, SPECIAL_INITRD_ROOT_FS_TARGET, "requires", diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c index d7f52e4a62..02f6d31b05 100644 --- a/src/volatile-root/volatile-root.c +++ b/src/volatile-root/volatile-root.c @@ -3,6 +3,7 @@ #include <sys/mount.h> #include "alloc-util.h" +#include "escape.h" #include "fs-util.h" #include "main-func.h" #include "mkdir.h" @@ -17,20 +18,7 @@ static int make_volatile(const char *path) { _cleanup_free_ char *old_usr = NULL; int r; - r = path_is_mount_point(path, NULL, AT_SYMLINK_FOLLOW); - if (r < 0) - return log_error_errno(r, "Couldn't determine whether %s is a mount point: %m", path); - if (r == 0) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "%s is not a mount point.", path); - - r = path_is_temporary_fs(path); - if (r < 0) - return log_error_errno(r, "Couldn't determine whether %s is a temporary file system: %m", path); - if (r > 0) { - log_info("%s already is a temporary file system.", path); - return 0; - } + assert(path); r = chase_symlinks("/usr", path, CHASE_PREFIX_ROOT, &old_usr); if (r < 0) @@ -79,6 +67,51 @@ finish_rmdir: return r; } +static int make_overlay(const char *path) { + _cleanup_free_ char *escaped_path = NULL; + bool tmpfs_mounted = false; + const char *options = NULL; + int r; + + assert(path); + + r = mkdir_p("/run/systemd/overlay-sysroot", 0700); + if (r < 0) + return log_error_errno(r, "Couldn't create overlay sysroot directory: %m"); + + r = mount_verbose(LOG_ERR, "tmpfs", "/run/systemd/overlay-sysroot", "tmpfs", MS_STRICTATIME, "mode=755"); + if (r < 0) + goto finish; + + tmpfs_mounted = true; + + if (mkdir("/run/systemd/overlay-sysroot/upper", 0755) < 0) { + r = log_error_errno(errno, "Failed to create /run/systemd/overlay-sysroot/upper: %m"); + goto finish; + } + + if (mkdir("/run/systemd/overlay-sysroot/work", 0755) < 0) { + r = log_error_errno(errno, "Failed to create /run/systemd/overlay-sysroot/work: %m"); + goto finish; + } + + escaped_path = shell_escape(path, ",:"); + if (!escaped_path) { + r = log_oom(); + goto finish; + } + + options = strjoina("lowerdir=", escaped_path, ",upperdir=/run/systemd/overlay-sysroot/upper,workdir=/run/systemd/overlay-sysroot/work"); + r = mount_verbose(LOG_ERR, "overlay", path, "overlay", 0, options); + +finish: + if (tmpfs_mounted) + (void) umount_verbose("/run/systemd/overlay-sysroot"); + + (void) rmdir("/run/systemd/overlay-sysroot"); + return r; +} + static int run(int argc, char *argv[]) { VolatileMode m = _VOLATILE_MODE_INVALID; const char *path; @@ -116,10 +149,29 @@ static int run(int argc, char *argv[]) { "Directory cannot be the root directory."); } - if (m != VOLATILE_YES) + if (!IN_SET(m, VOLATILE_YES, VOLATILE_OVERLAY)) return 0; - return make_volatile(path); + r = path_is_mount_point(path, NULL, AT_SYMLINK_FOLLOW); + if (r < 0) + return log_error_errno(r, "Couldn't determine whether %s is a mount point: %m", path); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "%s is not a mount point.", path); + + r = path_is_temporary_fs(path); + if (r < 0) + return log_error_errno(r, "Couldn't determine whether %s is a temporary file system: %m", path); + if (r > 0) { + log_info("%s already is a temporary file system.", path); + return 0; + } + + if (m == VOLATILE_YES) + return make_volatile(path); + else { + assert(m == VOLATILE_OVERLAY); + return make_overlay(path); + } } DEFINE_MAIN_FUNCTION(run); |