prepare-sysroot: Bind var under /run instead of inplace

This commit is contained in:
Misaki Kasumi 2024-12-18 15:57:37 +08:00
parent 8aaea0c65d
commit 1db98c0c18
2 changed files with 15 additions and 62 deletions

View File

@ -126,34 +126,6 @@ require_internal_units (const char *normal_dir, const char *early_dir, const cha
#endif
}
// Resolve symlink to return osname
static gboolean
_ostree_sysroot_parse_bootlink_aboot (const char *bootlink, char **out_osname, GError **error)
{
static gsize regex_initialized;
static GRegex *regex;
g_autofree char *symlink_val = glnx_readlinkat_malloc (-1, bootlink, NULL, error);
if (!symlink_val)
return glnx_prefix_error (error, "Failed to read '%s' symlink", bootlink);
if (g_once_init_enter (&regex_initialized))
{
regex = g_regex_new ("^deploy/([^/]+)/", 0, 0, NULL);
g_assert (regex);
g_once_init_leave (&regex_initialized, 1);
}
g_autoptr (GMatchInfo) match = NULL;
if (!g_regex_match (regex, symlink_val, 0, &match))
return glnx_throw (error,
"Invalid aboot symlink in /ostree, expected symlink to resolve to "
"deploy/OSNAME/... instead it resolves to '%s'",
symlink_val);
*out_osname = g_match_info_fetch (match, 1);
return TRUE;
}
/* Generate var.mount */
static gboolean
fstab_generator (const char *ostree_target, const bool is_aboot, const char *normal_dir,
@ -166,20 +138,6 @@ fstab_generator (const char *ostree_target, const bool is_aboot, const char *nor
static const char fstab_path[] = "/etc/fstab";
static const char var_path[] = "/var";
/* Written by ostree-sysroot-deploy.c. We parse out the stateroot here since we
* need to know it to mount /var. Unfortunately we can't easily use the
* libostree API to find the booted deployment since /boot might not have been
* mounted yet.
*/
g_autofree char *stateroot = NULL;
if (is_aboot)
{
if (!_ostree_sysroot_parse_bootlink_aboot (ostree_target, &stateroot, error))
return glnx_prefix_error (error, "Parsing aboot stateroot");
}
else if (!_ostree_sysroot_parse_bootlink (ostree_target, NULL, &stateroot, NULL, NULL, error))
return glnx_prefix_error (error, "Parsing stateroot");
/* Load /etc/fstab if it exists, and look for a /var mount */
g_autoptr (OtLibMountFile) fstab = setmntent (fstab_path, "re");
gboolean found_var_mnt = FALSE;
@ -219,7 +177,7 @@ fstab_generator (const char *ostree_target, const bool is_aboot, const char *nor
return FALSE;
/* Generate our bind mount unit */
const char *stateroot_var_path = glnx_strjoina ("/sysroot/ostree/deploy/", stateroot, "/var");
const char *var_dir = OTCORE_RUN_OSTREE_PRIVATE "/var";
g_auto (GLnxTmpfile) tmpf = {
0,
@ -253,7 +211,7 @@ fstab_generator (const char *ostree_target, const bool is_aboot, const char *nor
"Where=%s\n"
"What=%s\n"
"Options=bind,slave,shared\n",
var_path, stateroot_var_path))
var_path, var_dir))
return FALSE;
if (!g_output_stream_flush (outstream, cancellable, error))
return FALSE;

View File

@ -393,11 +393,8 @@ main (int argc, char *argv[])
// however, see
// https://github.com/systemd/systemd/blob/604b2001081adcbd64ee1fbe7de7a6d77c5209fe/src/basic/mountpoint-util.h#L36
// which bumps up these defaults for the rootfs a bit.
g_autofree char *root_upperdir
= root_transient ? g_build_filename (OTCORE_RUN_OSTREE_PRIVATE, "root/upper", NULL)
: NULL;
g_autofree char *root_workdir
= root_transient ? g_build_filename (OTCORE_RUN_OSTREE_PRIVATE, "root/work", NULL) : NULL;
const char *root_upperdir = OTCORE_RUN_OSTREE_PRIVATE "/root/upper";
const char *root_workdir = OTCORE_RUN_OSTREE_PRIVATE "/root/work";
// Propagate these options for transient root, if provided
if (root_transient)
@ -611,17 +608,15 @@ main (int argc, char *argv[])
err (EXIT_FAILURE, "failed to bind mount (class:readonly) /usr");
}
/* Prepare /var.
* When a read-only sysroot is configured, this adds a dedicated bind-mount (to itself)
* so that the stateroot location stays writable. */
if (sysroot_readonly)
{
/* Bind-mount /var (at stateroot path), and remount as writable. */
if (mount ("../../var", "../../var", NULL, MS_BIND | MS_SILENT, NULL) < 0)
err (EXIT_FAILURE, "failed to prepare /var bind-mount at %s", srcpath);
if (mount ("../../var", "../../var", NULL, MS_BIND | MS_REMOUNT | MS_SILENT, NULL) < 0)
err (EXIT_FAILURE, "failed to make writable /var bind-mount at %s", srcpath);
}
const char *var_dir = OTCORE_RUN_OSTREE_PRIVATE "/var";
/* Bind-mount /var, and remount as writable. */
if (mkdirat (AT_FDCWD, var_dir, 0) < 0)
err (EXIT_FAILURE, "failed to mkdir %s", var_dir);
if (mount ("../../var", var_dir, NULL, MS_BIND | MS_SILENT, NULL) < 0)
err (EXIT_FAILURE, "failed to prepare /var bind-mount at %s", var_dir);
if (mount (var_dir, var_dir, NULL, MS_BIND | MS_REMOUNT | MS_SILENT, NULL) < 0)
err (EXIT_FAILURE, "failed to make writable /var bind-mount at %s", var_dir);
/* When running under systemd, /var will be handled by a 'var.mount' unit outside
* of initramfs.
@ -640,8 +635,8 @@ main (int argc, char *argv[])
*/
if (mount_var)
{
if (mount ("../../var", TMP_SYSROOT "/var", NULL, MS_BIND | MS_SILENT, NULL) < 0)
err (EXIT_FAILURE, "failed to bind mount ../../var to var");
if (mount (var_dir, TMP_SYSROOT "/var", NULL, MS_BIND | MS_SILENT, NULL) < 0)
err (EXIT_FAILURE, "failed to bind mount /var");
/* To avoid having submounts of /var propagate into $stateroot/var, the
* mount is made with slave+shared propagation. See the comment in