ostree-prepare-root: Refactor: Create /sysroot.tmp much later

Typically we have our ready made-up up root at
`/sysroot/ostree/deploy/.../` (`deploy_path`) and the real rootfs at
`/sysroot` (`root_mountpoint`).  We want to end up with our made-up root
at `/sysroot/` and the real rootfs under `/sysroot/sysroot` as systemd
will be responsible for 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`

This is a refactoring to group all these operations together so I can
implement an alternative in terms of `pivot_root`.

Closes: #403
Approved by: cgwalters
This commit is contained in:
William Manley 2016-07-18 18:02:12 +01:00 committed by Atomic Bot
parent a0a4052365
commit 47e7afab27
1 changed files with 35 additions and 26 deletions

View File

@ -191,7 +191,6 @@ main(int argc, char *argv[])
char *deploy_path = NULL;
char srcpath[PATH_MAX];
char destpath[PATH_MAX];
char newroot[PATH_MAX];
struct stat stbuf;
int orig_cwd_dfd;
@ -202,16 +201,6 @@ main(int argc, char *argv[])
deploy_path = resolve_deploy_path (root_mountpoint);
/* Create a temporary target for our mounts in the initramfs; this will
* be moved to the new system root below.
*/
snprintf (newroot, sizeof(newroot), "%s.tmp", root_mountpoint);
if (mkdir (newroot, 0755) < 0)
{
perrorv ("Couldn't create temporary sysroot '%s': ", newroot);
exit (EXIT_FAILURE);
}
/* Work-around for a kernel bug: for some reason the kernel
* refuses switching root if any file systems are mounted
* MS_SHARED. Hence remount them MS_PRIVATE here as a
@ -225,7 +214,7 @@ main(int argc, char *argv[])
}
/* Make deploy_path a bind mount, so we can move it later */
if (mount (deploy_path, newroot, NULL, MS_BIND, NULL) < 0)
if (mount (deploy_path, deploy_path, NULL, MS_BIND, NULL) < 0)
{
perrorv ("failed to initial bind mount %s", deploy_path);
exit (EXIT_FAILURE);
@ -233,7 +222,7 @@ main(int argc, char *argv[])
/* Link to the deployment's /var */
snprintf (srcpath, sizeof(srcpath), "%s/../../var", deploy_path);
snprintf (destpath, sizeof(destpath), "%s/var", newroot);
snprintf (destpath, sizeof(destpath), "%s/var", deploy_path);
if (mount (srcpath, destpath, NULL, MS_MGC_VAL|MS_BIND, NULL) < 0)
{
perrorv ("failed to bind mount %s to %s", srcpath, destpath);
@ -245,7 +234,7 @@ main(int argc, char *argv[])
snprintf (srcpath, sizeof(srcpath), "%s/boot/loader", root_mountpoint);
if (lstat (srcpath, &stbuf) == 0 && S_ISLNK (stbuf.st_mode))
{
snprintf (destpath, sizeof(destpath), "%s/boot", newroot);
snprintf (destpath, sizeof(destpath), "%s/boot", deploy_path);
if (lstat (destpath, &stbuf) == 0 && S_ISDIR (stbuf.st_mode))
{
snprintf (srcpath, sizeof(srcpath), "%s/boot", root_mountpoint);
@ -257,7 +246,7 @@ main(int argc, char *argv[])
}
}
/* Here we do a dance to chdir to the newroot so that we can have
/* Here we do a dance to chdir to the deploy_path so that we can have
* the potential overlayfs mount points not look ugly. However...I
* think we could do this a lot earlier and make all of the mounts
* here just be relative.
@ -269,9 +258,9 @@ main(int argc, char *argv[])
exit (EXIT_FAILURE);
}
if (chdir (newroot) < 0)
if (chdir (deploy_path) < 0)
{
perrorv ("failed to chdir to newroot");
perrorv ("failed to chdir to deploy_path");
exit (EXIT_FAILURE);
}
@ -324,19 +313,39 @@ main(int argc, char *argv[])
touch_run_ostree ();
/* Move physical root to $deployment/sysroot */
snprintf (destpath, sizeof(destpath), "%s/sysroot", newroot);
if (mount (root_mountpoint, destpath, NULL, MS_MOVE, NULL) < 0)
/* In this instance typically we have our ready made-up up root at
* /sysroot/ostree/deploy/.../ (deploy_path) and the real rootfs at
* /sysroot (root_mountpoint). We want to end up with our made-up root at
* /sysroot/ and the real rootfs under /sysroot/sysroot as systemd will be
* responsible for 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)
{
perrorv ("Failed to MS_MOVE %s to '%s'", root_mountpoint, destpath);
perrorv ("couldn't create temporary sysroot /sysroot.tmp: ");
exit (EXIT_FAILURE);
}
/* Now that we've set up all the bind mounts in /sysroot.tmp which
* points to the deployment, move it /sysroot. From there,
* systemd's initrd-switch-root.target will take over.
*/
if (mount (newroot, root_mountpoint, NULL, MS_MOVE, NULL) < 0)
if (mount (deploy_path, "/sysroot.tmp", NULL, MS_MOVE, NULL) < 0)
{
perrorv ("failed to MS_MOVE '%s' to '/sysroot.tmp'", deploy_path);
exit (EXIT_FAILURE);
}
if (mount (root_mountpoint, "/sysroot.tmp/sysroot", NULL, MS_MOVE, NULL) < 0)
{
perrorv ("failed to MS_MOVE '%s' to '/sysroot.tmp/sysroot'",
root_mountpoint);
exit (EXIT_FAILURE);
}
if (mount ("/sysroot.tmp", root_mountpoint, NULL, MS_MOVE, NULL) < 0)
{
perrorv ("failed to MS_MOVE %s to %s", deploy_path, root_mountpoint);
exit (EXIT_FAILURE);