Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sysroot: Support /boot on / for syslinux and uboot #215

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile-tests.am
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ dist_test_scripts = \
tests/test-gpg-signed-commit.sh \
tests/test-admin-upgrade-unconfigured.sh \
tests/test-admin-deploy-syslinux.sh \
tests/test-admin-deploy-syslinux-bootonslash.sh \
tests/test-admin-deploy-2.sh \
tests/test-admin-deploy-karg.sh \
tests/test-admin-deploy-switch.sh \
Expand Down
1 change: 1 addition & 0 deletions src/libostree/ostree-bootloader-grub2.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ grub2_child_setup (gpointer user_data)
static gboolean
_ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
int bootversion,
gboolean have_boot_partition,
GCancellable *cancellable,
GError **error)
{
Expand Down
31 changes: 18 additions & 13 deletions src/libostree/ostree-bootloader-syslinux.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ _ostree_bootloader_syslinux_get_name (OstreeBootloader *bootloader)

static gboolean
append_config_from_boostree_loader_entries (OstreeBootloaderSyslinux *self,
gboolean regenerate_default,
int bootversion,
GPtrArray *new_lines,
GCancellable *cancellable,
GError **error)
gboolean regenerate_default,
int bootversion,
gboolean have_boot_partition,
GPtrArray *new_lines,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GPtrArray) boostree_loader_configs = NULL;
Expand All @@ -78,6 +79,7 @@ append_config_from_boostree_loader_entries (OstreeBootloaderSyslinux *self,
{
OstreeBootconfigParser *config = boostree_loader_configs->pdata[i];
const char *val;
const char *filename_prefix = have_boot_partition ? "" : "/boot";

val = ostree_bootconfig_parser_get (config, "title");
if (!val)
Expand All @@ -97,11 +99,11 @@ append_config_from_boostree_loader_entries (OstreeBootloaderSyslinux *self,
"No \"linux\" key in bootloader config");
goto out;
}
g_ptr_array_add (new_lines, g_strdup_printf ("\tKERNEL %s", val));
g_ptr_array_add (new_lines, g_strdup_printf ("\tKERNEL %s%s", filename_prefix, val));

val = ostree_bootconfig_parser_get (config, "initrd");
if (val)
g_ptr_array_add (new_lines, g_strdup_printf ("\tINITRD %s", val));
g_ptr_array_add (new_lines, g_strdup_printf ("\tINITRD %s%s", filename_prefix, val));

val = ostree_bootconfig_parser_get (config, "options");
if (val)
Expand All @@ -115,9 +117,10 @@ append_config_from_boostree_loader_entries (OstreeBootloaderSyslinux *self,

static gboolean
_ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader,
int bootversion,
GCancellable *cancellable,
GError **error)
int bootversion,
gboolean have_boot_partition,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (bootloader);
Expand Down Expand Up @@ -156,6 +159,7 @@ _ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader,
{
char *line = *iter;
gboolean skip = FALSE;
const char *nonostree_prefix = have_boot_partition ? "/ostree/" : "/boot/ostree/";

if (parsing_label &&
(line == NULL || !g_str_has_prefix (line, "\t")))
Expand All @@ -171,7 +175,7 @@ _ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader,
/* If this is a non-ostree kernel, just emit the lines
* we saw.
*/
if (!g_str_has_prefix (kernel_arg, "/ostree/"))
if (!g_str_has_prefix (kernel_arg, nonostree_prefix))
{
for (i = 0; i < tmp_lines->len; i++)
{
Expand Down Expand Up @@ -241,8 +245,9 @@ _ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader,
regenerate_default = TRUE;

if (!append_config_from_boostree_loader_entries (self, regenerate_default,
bootversion, new_lines,
cancellable, error))
bootversion, have_boot_partition,
new_lines,
cancellable, error))
goto out;

new_config_contents = _ostree_sysroot_join_lines (new_lines);
Expand Down
25 changes: 15 additions & 10 deletions src/libostree/ostree-bootloader-uboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,16 @@ _ostree_bootloader_uboot_get_name (OstreeBootloader *bootloader)

static gboolean
create_config_from_boot_loader_entries (OstreeBootloaderUboot *self,
int bootversion,
GPtrArray *new_lines,
GCancellable *cancellable,
GError **error)
int bootversion,
gboolean have_boot_partition,
GPtrArray *new_lines,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GPtrArray) boot_loader_configs = NULL;
OstreeBootconfigParser *config;
const char *val;
const char *filename_prefix = have_boot_partition ? "" : "/boot";

if (!_ostree_sysroot_read_boot_loader_configs (self->sysroot, bootversion, &boot_loader_configs,
cancellable, error))
Expand All @@ -87,11 +89,11 @@ create_config_from_boot_loader_entries (OstreeBootloaderUboot *self,
"No \"linux\" key in bootloader config");
return FALSE;
}
g_ptr_array_add (new_lines, g_strdup_printf ("kernel_image=%s", val));
g_ptr_array_add (new_lines, g_strdup_printf ("kernel_image=%s%s", filename_prefix, val));

val = ostree_bootconfig_parser_get (config, "initrd");
if (val)
g_ptr_array_add (new_lines, g_strdup_printf ("ramdisk_image=%s", val));
g_ptr_array_add (new_lines, g_strdup_printf ("ramdisk_image=%s%s", filename_prefix, val));

val = ostree_bootconfig_parser_get (config, "options");
if (val)
Expand Down Expand Up @@ -140,9 +142,10 @@ create_config_from_boot_loader_entries (OstreeBootloaderUboot *self,

static gboolean
_ostree_bootloader_uboot_write_config (OstreeBootloader *bootloader,
int bootversion,
GCancellable *cancellable,
GError **error)
int bootversion,
gboolean have_boot_partition,
GCancellable *cancellable,
GError **error)
{
OstreeBootloaderUboot *self = OSTREE_BOOTLOADER_UBOOT (bootloader);
g_autoptr(GFile) new_config_path = NULL;
Expand All @@ -161,7 +164,9 @@ _ostree_bootloader_uboot_write_config (OstreeBootloader *bootloader,

new_lines = g_ptr_array_new_with_free_func (g_free);

if (!create_config_from_boot_loader_entries (self, bootversion, new_lines,
if (!create_config_from_boot_loader_entries (self, bootversion,
have_boot_partition,
new_lines,
cancellable, error))
return FALSE;

Expand Down
10 changes: 6 additions & 4 deletions src/libostree/ostree-bootloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,16 @@ _ostree_bootloader_get_name (OstreeBootloader *self)

gboolean
_ostree_bootloader_write_config (OstreeBootloader *self,
int bootversion,
GCancellable *cancellable,
GError **error)
int bootversion,
gboolean have_boot_partition,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE);

return OSTREE_BOOTLOADER_GET_IFACE (self)->write_config (self, bootversion,
cancellable, error);
have_boot_partition,
cancellable, error);
}

gboolean
Expand Down
2 changes: 2 additions & 0 deletions src/libostree/ostree-bootloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct _OstreeBootloaderInterface
const char * (* get_name) (OstreeBootloader *self);
gboolean (* write_config) (OstreeBootloader *self,
int bootversion,
gboolean have_boot_partition,
GCancellable *cancellable,
GError **error);
gboolean (* is_atomic) (OstreeBootloader *self);
Expand All @@ -60,6 +61,7 @@ const char *_ostree_bootloader_get_name (OstreeBootloader *self);

gboolean _ostree_bootloader_write_config (OstreeBootloader *self,
int bootversion,
gboolean have_boot_partition,
GCancellable *cancellable,
GError **error);

Expand Down
52 changes: 41 additions & 11 deletions src/libostree/ostree-sysroot-deploy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1668,7 +1668,7 @@ cleanup_legacy_current_symlinks (OstreeSysroot *self,
}

static gboolean
is_ro_mount (const char *path)
is_mount (const char *path)
{
#ifdef HAVE_LIBMOUNT
/* Dragging in all of this crud is apparently necessary just to determine
Expand All @@ -1681,7 +1681,6 @@ is_ro_mount (const char *path)
struct libmnt_fs *fs;
struct libmnt_cache *cache;
gboolean is_mount = FALSE;
struct statvfs stvfsbuf;

if (!tb)
return FALSE;
Expand All @@ -1695,17 +1694,29 @@ is_ro_mount (const char *path)
mnt_free_cache (cache);
mnt_free_table (tb);

if (!is_mount)
return FALSE;
return is_mount;
#else
return FALSE;
#endif
}

static gboolean
query_mount_is_ro (const char *path,
gboolean *out_is_ro,
GError **error)
{
struct statvfs stvfsbuf;

/* We *could* parse the options, but it seems more reliable to
* introspect the actual mount at runtime.
*/
if (statvfs (path, &stvfsbuf) == 0)
return (stvfsbuf.f_flag & ST_RDONLY) != 0;

#endif
return FALSE;
if (statvfs (path, &stvfsbuf) < 0)
{
glnx_set_error_from_errno (error);
return FALSE;
}
*out_is_ro = (stvfsbuf.f_flag & ST_RDONLY) != 0;
return TRUE;
}

/**
Expand Down Expand Up @@ -1828,11 +1839,29 @@ _ostree_sysroot_write_deployments_internal (OstreeSysroot *self,
g_autofree char* new_loader_entries_dir = NULL;
glnx_unref_object OstreeRepo *repo = NULL;
gboolean show_osname = FALSE;
gboolean boot_is_mount = FALSE;

if (self->booted_deployment)
boot_was_ro_mount = is_ro_mount ("/boot");
boot_is_mount = is_mount ("/boot");
else
{
/* For legacy reasons; see
* https://bugzilla.gnome.org/show_bug.cgi?id=751666 But the
* test suite can override this. Do NOT use this debug flag
* in production, instead we could consider a compile-time
* default if you don't want a dependency on libmount or
* something.
*/
boot_is_mount = (self->debug_flags & OSTREE_SYSROOT_DEBUG_BOOT_IS_NOT_MOUNT) == 0;
}

if (self->booted_deployment && boot_is_mount)
{
if (!query_mount_is_ro ("/boot", &boot_was_ro_mount, error))
goto out;
}

g_debug ("boot is ro: %s", boot_was_ro_mount ? "yes" : "no");
g_debug ("boot is mount: %d ro: %d", boot_is_mount, boot_was_ro_mount);

if (boot_was_ro_mount)
{
Expand Down Expand Up @@ -1911,6 +1940,7 @@ _ostree_sysroot_write_deployments_internal (OstreeSysroot *self,
if (bootloader)
{
if (!_ostree_bootloader_write_config (bootloader, new_bootversion,
boot_is_mount,
cancellable, error))
{
g_prefix_error (error, "Bootloader write config: ");
Expand Down
4 changes: 3 additions & 1 deletion src/libostree/ostree-sysroot-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ G_BEGIN_DECLS
typedef enum {

/* Don't flag deployments as immutable. */
OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS = 1 << 0
OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS = 1 << 0,
/* If set, assume /boot is on / */
OSTREE_SYSROOT_DEBUG_BOOT_IS_NOT_MOUNT = 1 << 1

} OstreeSysrootDebugFlags;

Expand Down
3 changes: 2 additions & 1 deletion src/libostree/ostree-sysroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,10 @@ ostree_sysroot_init (OstreeSysroot *self)
{
const GDebugKey keys[] = {
{ "mutable-deployments", OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS },
{ "boot-is-not-mount", OSTREE_SYSROOT_DEBUG_BOOT_IS_NOT_MOUNT }
};

self->debug_flags = g_parse_debug_string (g_getenv("OSTREE_SYSROOT_DEBUG"),
self->debug_flags = g_parse_debug_string (g_getenv ("OSTREE_SYSROOT_DEBUG"),
keys, G_N_ELEMENTS (keys));

self->sysroot_fd = -1;
Expand Down
46 changes: 46 additions & 0 deletions tests/test-admin-deploy-syslinux-bootonslash.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
#
# Copyright (C) 2016 Colin Walters <walters@verbum.org>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

set -euo pipefail

. $(dirname $0)/libtest.sh

# Exports OSTREE_SYSROOT so --sysroot not needed.
setup_os_repository "archive-z2" "syslinux"

echo "1..2"

${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime
# Override the default and say that /boot is not a partition
env OSTREE_SYSROOT_DEBUG=${OSTREE_SYSROOT_DEBUG},boot-is-not-mount \
${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime

assert_file_has_content sysroot/boot/syslinux/syslinux.cfg "KERNEL /boot/ostree/testos.*vmlinuz"
assert_file_has_content sysroot/boot/syslinux/syslinux.cfg "INITRD /boot/ostree/testos.*initramfs"

echo "ok bootonslash"

${CMD_PREFIX} ostree admin undeploy 0

# Legacy default of /boot is a partition
${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime
assert_file_has_content sysroot/boot/syslinux/syslinux.cfg "KERNEL /ostree/testos.*vmlinuz"
assert_file_has_content sysroot/boot/syslinux/syslinux.cfg "INITRD /ostree/testos.*initramfs"

echo "ok bootpartition"