mirror of
https://github.com/ostreedev/ostree.git
synced 2024-12-23 21:35:26 +03:00
Merge pull request #2864 from cgwalters/prepare-root-prepare-composefs
prepare-root: Move sysroot.tmp creation earlier
This commit is contained in:
commit
0dd2788410
@ -36,11 +36,16 @@
|
|||||||
* hardlinked chroot() targets are maintained, this one does the equivalent
|
* hardlinked chroot() targets are maintained, this one does the equivalent
|
||||||
* of chroot().
|
* of chroot().
|
||||||
*
|
*
|
||||||
|
* # ostree-prepare-root.service
|
||||||
|
*
|
||||||
* If using systemd, an excellent reference is `man bootup`. This
|
* If using systemd, an excellent reference is `man bootup`. This
|
||||||
* service runs Before=initrd-root-fs.target. At this point it's
|
* service runs Before=initrd-root-fs.target. At this point it's
|
||||||
* assumed that the block storage and root filesystem are mounted at
|
* assumed that the block storage and root filesystem are mounted at
|
||||||
* /sysroot - i.e. /sysroot points to the *physical* root before
|
* /sysroot - i.e. /sysroot points to the *physical* root before
|
||||||
* this service runs. After, `/` is the deployment root.
|
* this service runs. After, `/` is the deployment root, and /sysroot is
|
||||||
|
* the physical root.
|
||||||
|
*
|
||||||
|
* # Running as pid 1
|
||||||
*
|
*
|
||||||
* There is also a secondary mode for this service when an initrd isn't
|
* There is also a secondary mode for this service when an initrd isn't
|
||||||
* used - instead the binary must be statically linked (and the kernel
|
* used - instead the binary must be statically linked (and the kernel
|
||||||
@ -78,6 +83,9 @@
|
|||||||
SD_ID128_MAKE (71, 70, 33, 6a, 73, ba, 46, 01, ba, d3, 1a, f8, 88, aa, 0d, f7)
|
SD_ID128_MAKE (71, 70, 33, 6a, 73, ba, 46, 01, ba, d3, 1a, f8, 88, aa, 0d, f7)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// A temporary mount point
|
||||||
|
#define TMP_SYSROOT "/sysroot.tmp"
|
||||||
|
|
||||||
#include "ostree-mount-util.h"
|
#include "ostree-mount-util.h"
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
@ -202,6 +210,11 @@ main (int argc, char *argv[])
|
|||||||
we_mounted_proc = 1;
|
we_mounted_proc = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is the final target where we should prepare the rootfs. The usual
|
||||||
|
* case with systemd in the initramfs is that root_mountpoint = "/sysroot".
|
||||||
|
* In the fastboot embedded case we're pid1 and will setup / ourself, and
|
||||||
|
* then root_mountpoint = "/".
|
||||||
|
* */
|
||||||
const char *root_mountpoint = realpath (root_arg, NULL);
|
const char *root_mountpoint = realpath (root_arg, NULL);
|
||||||
if (root_mountpoint == NULL)
|
if (root_mountpoint == NULL)
|
||||||
err (EXIT_FAILURE, "realpath(\"%s\")", root_arg);
|
err (EXIT_FAILURE, "realpath(\"%s\")", root_arg);
|
||||||
@ -234,16 +247,23 @@ main (int argc, char *argv[])
|
|||||||
if (mount (NULL, "/", NULL, MS_REC | MS_PRIVATE | MS_SILENT, NULL) < 0)
|
if (mount (NULL, "/", NULL, MS_REC | MS_PRIVATE | MS_SILENT, NULL) < 0)
|
||||||
err (EXIT_FAILURE, "failed to make \"/\" private mount");
|
err (EXIT_FAILURE, "failed to make \"/\" private mount");
|
||||||
|
|
||||||
/* Make deploy_path a bind mount, so we can move it later */
|
if (mkdir (TMP_SYSROOT, 0755) < 0)
|
||||||
if (mount (deploy_path, deploy_path, NULL, MS_BIND | MS_SILENT, NULL) < 0)
|
err (EXIT_FAILURE, "couldn't create temporary sysroot %s", TMP_SYSROOT);
|
||||||
err (EXIT_FAILURE, "failed to make initial bind mount %s", deploy_path);
|
|
||||||
|
|
||||||
/* chdir to our new root. We need to do this after bind-mounting it over
|
/* Run in the deploy_path dir so we can use relative paths below */
|
||||||
* itself otherwise our cwd is still on the non-bind-mounted filesystem
|
|
||||||
* below. */
|
|
||||||
if (chdir (deploy_path) < 0)
|
if (chdir (deploy_path) < 0)
|
||||||
err (EXIT_FAILURE, "failed to chdir to deploy_path");
|
err (EXIT_FAILURE, "failed to chdir to deploy_path");
|
||||||
|
|
||||||
|
/* Currently always false */
|
||||||
|
bool using_composefs = false;
|
||||||
|
|
||||||
|
if (!using_composefs)
|
||||||
|
{
|
||||||
|
/* The deploy root starts out bind mounted to sysroot.tmp */
|
||||||
|
if (mount (deploy_path, TMP_SYSROOT, NULL, MS_BIND | MS_SILENT, NULL) < 0)
|
||||||
|
err (EXIT_FAILURE, "failed to make initial bind mount %s", deploy_path);
|
||||||
|
}
|
||||||
|
|
||||||
/* This will result in a system with /sysroot read-only. Thus, two additional
|
/* This will result in a system with /sysroot read-only. Thus, two additional
|
||||||
* writable bind-mounts (for /etc and /var) are required later on. */
|
* writable bind-mounts (for /etc and /var) are required later on. */
|
||||||
if (sysroot_readonly)
|
if (sysroot_readonly)
|
||||||
@ -269,7 +289,7 @@ main (int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
if (snprintf (srcpath, sizeof (srcpath), "%s/boot", root_mountpoint) < 0)
|
if (snprintf (srcpath, sizeof (srcpath), "%s/boot", root_mountpoint) < 0)
|
||||||
err (EXIT_FAILURE, "failed to assemble /boot path");
|
err (EXIT_FAILURE, "failed to assemble /boot path");
|
||||||
if (mount (srcpath, "boot", NULL, MS_BIND | MS_SILENT, NULL) < 0)
|
if (mount (srcpath, TMP_SYSROOT "/boot", NULL, MS_BIND | MS_SILENT, NULL) < 0)
|
||||||
err (EXIT_FAILURE, "failed to bind mount %s to boot", srcpath);
|
err (EXIT_FAILURE, "failed to bind mount %s to boot", srcpath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,13 +297,15 @@ main (int argc, char *argv[])
|
|||||||
/* Prepare /etc.
|
/* Prepare /etc.
|
||||||
* No action required if sysroot is writable. Otherwise, a bind-mount for
|
* No action required if sysroot is writable. Otherwise, a bind-mount for
|
||||||
* the deployment needs to be created and remounted as read/write. */
|
* the deployment needs to be created and remounted as read/write. */
|
||||||
if (sysroot_readonly)
|
if (sysroot_readonly || using_composefs)
|
||||||
{
|
{
|
||||||
/* Bind-mount /etc (at deploy path), and remount as writable. */
|
/* Bind-mount /etc (at deploy path), and remount as writable. */
|
||||||
if (mount ("etc", "etc", NULL, MS_BIND | MS_SILENT, NULL) < 0)
|
if (mount ("etc", TMP_SYSROOT "/etc", NULL, MS_BIND | MS_SILENT, NULL) < 0)
|
||||||
err (EXIT_FAILURE, "failed to prepare /etc bind-mount at %s", srcpath);
|
err (EXIT_FAILURE, "failed to prepare /etc bind-mount at /sysroot.tmp/etc");
|
||||||
if (mount ("etc", "etc", NULL, MS_BIND | MS_REMOUNT | MS_SILENT, NULL) < 0)
|
if (mount (TMP_SYSROOT "/etc", TMP_SYSROOT "/etc", NULL, MS_BIND | MS_REMOUNT | MS_SILENT,
|
||||||
err (EXIT_FAILURE, "failed to make writable /etc bind-mount at %s", srcpath);
|
NULL)
|
||||||
|
< 0)
|
||||||
|
err (EXIT_FAILURE, "failed to make writable /etc bind-mount at /sysroot.tmp/etc");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare /usr.
|
/* Prepare /usr.
|
||||||
@ -291,28 +313,31 @@ main (int argc, char *argv[])
|
|||||||
if (lstat (".usr-ovl-work", &stbuf) == 0)
|
if (lstat (".usr-ovl-work", &stbuf) == 0)
|
||||||
{
|
{
|
||||||
/* Do we have a persistent overlayfs for /usr? If so, mount it now. */
|
/* Do we have a persistent overlayfs for /usr? If so, mount it now. */
|
||||||
const char usr_ovl_options[] = "lowerdir=usr,upperdir=.usr-ovl-upper,workdir=.usr-ovl-work";
|
const char usr_ovl_options[]
|
||||||
|
= "lowerdir=" TMP_SYSROOT "/usr,upperdir=.usr-ovl-upper,workdir=.usr-ovl-work";
|
||||||
|
|
||||||
/* Except overlayfs barfs if we try to mount it on a read-only
|
/* Except overlayfs barfs if we try to mount it on a read-only
|
||||||
* filesystem. For this use case I think admins are going to be
|
* filesystem. For this use case I think admins are going to be
|
||||||
* okay if we remount the rootfs here, rather than waiting until
|
* okay if we remount the rootfs here, rather than waiting until
|
||||||
* later boot and `systemd-remount-fs.service`.
|
* later boot and `systemd-remount-fs.service`.
|
||||||
*/
|
*/
|
||||||
if (path_is_on_readonly_fs ("."))
|
if (path_is_on_readonly_fs (TMP_SYSROOT))
|
||||||
{
|
{
|
||||||
if (mount (".", ".", NULL, MS_REMOUNT | MS_SILENT, NULL) < 0)
|
if (mount (TMP_SYSROOT, TMP_SYSROOT, NULL, MS_REMOUNT | MS_SILENT, NULL) < 0)
|
||||||
err (EXIT_FAILURE, "failed to remount rootfs writable (for overlayfs)");
|
err (EXIT_FAILURE, "failed to remount rootfs writable (for overlayfs)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mount ("overlay", "usr", "overlay", MS_SILENT, usr_ovl_options) < 0)
|
if (mount ("overlay", TMP_SYSROOT "/usr", "overlay", MS_SILENT, usr_ovl_options) < 0)
|
||||||
err (EXIT_FAILURE, "failed to mount /usr overlayfs");
|
err (EXIT_FAILURE, "failed to mount /usr overlayfs");
|
||||||
}
|
}
|
||||||
else
|
else if (!using_composefs)
|
||||||
{
|
{
|
||||||
/* Otherwise, a read-only bind mount for /usr */
|
/* Otherwise, a read-only bind mount for /usr. (Not needed for composefs) */
|
||||||
if (mount ("usr", "usr", NULL, MS_BIND | MS_SILENT, NULL) < 0)
|
if (mount (TMP_SYSROOT "/usr", TMP_SYSROOT "/usr", NULL, MS_BIND | MS_SILENT, NULL) < 0)
|
||||||
err (EXIT_FAILURE, "failed to bind mount (class:readonly) /usr");
|
err (EXIT_FAILURE, "failed to bind mount (class:readonly) /usr");
|
||||||
if (mount ("usr", "usr", NULL, MS_BIND | MS_REMOUNT | MS_RDONLY | MS_SILENT, NULL) < 0)
|
if (mount (TMP_SYSROOT "/usr", TMP_SYSROOT "/usr", NULL,
|
||||||
|
MS_BIND | MS_REMOUNT | MS_RDONLY | MS_SILENT, NULL)
|
||||||
|
< 0)
|
||||||
err (EXIT_FAILURE, "failed to bind mount (class:readonly) /usr");
|
err (EXIT_FAILURE, "failed to bind mount (class:readonly) /usr");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,7 +370,7 @@ main (int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
if (mount_var)
|
if (mount_var)
|
||||||
{
|
{
|
||||||
if (mount ("../../var", "var", NULL, MS_BIND | MS_SILENT, NULL) < 0)
|
if (mount ("../../var", TMP_SYSROOT "/var", NULL, MS_BIND | MS_SILENT, NULL) < 0)
|
||||||
err (EXIT_FAILURE, "failed to bind mount ../../var to var");
|
err (EXIT_FAILURE, "failed to bind mount ../../var to var");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +382,9 @@ main (int argc, char *argv[])
|
|||||||
if (!running_as_pid1)
|
if (!running_as_pid1)
|
||||||
touch_run_ostree ();
|
touch_run_ostree ();
|
||||||
|
|
||||||
|
if (chdir (TMP_SYSROOT) < 0)
|
||||||
|
err (EXIT_FAILURE, "failed to chdir to " TMP_SYSROOT);
|
||||||
|
|
||||||
if (strcmp (root_mountpoint, "/") == 0)
|
if (strcmp (root_mountpoint, "/") == 0)
|
||||||
{
|
{
|
||||||
/* pivot_root rotates two mount points around. In this instance . (the
|
/* pivot_root rotates two mount points around. In this instance . (the
|
||||||
@ -371,32 +399,22 @@ main (int argc, char *argv[])
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* In this instance typically we have our ready made-up up root at
|
/* In this instance typically we have our ready made-up up root at
|
||||||
* /sysroot/ostree/deploy/.../ (deploy_path) and the real rootfs at
|
* /sysroot.tmp and the physical root at /sysroot (root_mountpoint).
|
||||||
* /sysroot (root_mountpoint). We want to end up with our made-up root at
|
* We want to end up with our deploy root at /sysroot/ and the physical
|
||||||
* /sysroot/ and the real rootfs under /sysroot/sysroot as systemd will be
|
* root under /sysroot/sysroot as systemd will be responsible for
|
||||||
* responsible for moving /sysroot to /.
|
* moving /sysroot to /.
|
||||||
*
|
|
||||||
* We need to do this in 3 moves to avoid trying to move /sysroot under
|
|
||||||
* itself:
|
|
||||||
*
|
|
||||||
* 1. /sysroot/ostree/deploy/... -> /sysroot.tmp
|
|
||||||
* 2. /sysroot -> /sysroot.tmp/sysroot
|
|
||||||
* 3. /sysroot.tmp -> /sysroot
|
|
||||||
*/
|
*/
|
||||||
if (mkdir ("/sysroot.tmp", 0755) < 0)
|
|
||||||
err (EXIT_FAILURE, "couldn't create temporary sysroot /sysroot.tmp");
|
|
||||||
|
|
||||||
if (mount (deploy_path, "/sysroot.tmp", NULL, MS_MOVE | MS_SILENT, NULL) < 0)
|
|
||||||
err (EXIT_FAILURE, "failed to MS_MOVE '%s' to '/sysroot.tmp'", deploy_path);
|
|
||||||
|
|
||||||
if (mount (root_mountpoint, "sysroot", NULL, MS_MOVE | MS_SILENT, NULL) < 0)
|
if (mount (root_mountpoint, "sysroot", NULL, MS_MOVE | MS_SILENT, NULL) < 0)
|
||||||
err (EXIT_FAILURE, "failed to MS_MOVE '%s' to 'sysroot'", root_mountpoint);
|
err (EXIT_FAILURE, "failed to MS_MOVE '%s' to 'sysroot'", root_mountpoint);
|
||||||
|
|
||||||
if (mount (".", root_mountpoint, NULL, MS_MOVE | MS_SILENT, NULL) < 0)
|
if (mount (".", root_mountpoint, NULL, MS_MOVE | MS_SILENT, NULL) < 0)
|
||||||
err (EXIT_FAILURE, "failed to MS_MOVE %s to %s", deploy_path, root_mountpoint);
|
err (EXIT_FAILURE, "failed to MS_MOVE %s to %s", ".", root_mountpoint);
|
||||||
|
|
||||||
if (rmdir ("/sysroot.tmp") < 0)
|
if (chdir (root_mountpoint) < 0)
|
||||||
err (EXIT_FAILURE, "couldn't remove temporary sysroot /sysroot.tmp");
|
err (EXIT_FAILURE, "failed to chdir to %s", root_mountpoint);
|
||||||
|
|
||||||
|
if (rmdir (TMP_SYSROOT) < 0)
|
||||||
|
err (EXIT_FAILURE, "couldn't remove temporary sysroot %s", TMP_SYSROOT);
|
||||||
|
|
||||||
if (sysroot_readonly)
|
if (sysroot_readonly)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user