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

generator: Fixes for Android Boot environment #3192

Merged

Conversation

ericcurtin
Copy link
Collaborator

@ericcurtin ericcurtin commented Feb 21, 2024

In Android Boot environment we do not parse ostree= karg to determine
what directory to boot into, alternatively we do this based on the
androidboot.slot_suffix= karg. But we do set ostree=true karg to denote
that we are indeed booting an ostree environment (required for some
systemd unit files). This change accounts for this approach in the
systemd generator. In this case androidboot.slot_suffix= points you to
/ostree/root.[a|b] and then that points you to the directory to boot
into in /ostree/deploy... Here is what a cmdline may look like in this
type of environment:

androidboot.slot_suffix=_a androidboot.bootdevice=*.ufshc root=PARTLABEL=system_a root=UUID=76a22bf4-f153-4541-b6c7-0332c0dfaeac rw ostree=true loglevel=4 acpi=off console=ttyAMA0 systemd.show_status=auto libahci.ignore_sss=1 slub_debug=FPZ fsck.mode=skip rcupdate.rcu_normal_after_boot=0 rcupdate.rcu_expedited=1

@ericcurtin
Copy link
Collaborator Author

Will "undraft" this PR pending testing...

@ericcurtin
Copy link
Collaborator Author

Re-pushing something shortly hold tight.

@ericcurtin ericcurtin force-pushed the ostree-impl-system-generator-aboot branch from fadec22 to 81b94ab Compare February 21, 2024 18:55
@github-actions github-actions bot added the area/prepare-root Issue relates to ostree-prepare-root label Feb 21, 2024
@ericcurtin ericcurtin force-pushed the ostree-impl-system-generator-aboot branch 2 times, most recently from c3813e3 to a8f8ca8 Compare February 21, 2024 19:59
In Android Boot environment we do not parse ostree= karg to determine
what directory to boot into, alternatively we do this based on the
androidboot.slot_suffix= karg. But we do set ostree=true karg to denote
that we are indeed booting an ostree environment (required for some
systemd unit files). This change accounts for this approach in the
systemd generator. In this case androidboot.slot_suffix= points you to
/ostree/root.[a|b] and then that points you to the directory to boot
into in /ostree/deploy... Here is what a cmdline may look like in this
type of environment:

androidboot.slot_suffix=_a androidboot.bootdevice=*.ufshc root=PARTLABEL=system_a root=UUID=76a22bf4-f153-4541-b6c7-0332c0dfaeac rw ostree=true loglevel=4 acpi=off console=ttyAMA0 systemd.show_status=auto libahci.ignore_sss=1 slub_debug=FPZ fsck.mode=skip rcupdate.rcu_normal_after_boot=0 rcupdate.rcu_expedited=1

Signed-off-by: Eric Curtin <[email protected]>
@ericcurtin ericcurtin force-pushed the ostree-impl-system-generator-aboot branch from a8f8ca8 to 4a71845 Compare February 21, 2024 20:55
@ericcurtin ericcurtin marked this pull request as ready for review February 21, 2024 20:56
@ericcurtin
Copy link
Collaborator Author

/ok-to-test

"ostree=/ostree/boot.BOOTVERSION/OSNAME/BOOTCSUM/TREESERIAL or aboot method",
to_parse);

if (is_aboot)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main difference of this PR, the systemd generator needs to parse the OSNAME from the directory structure which is a little different in the aboot case.

Copy link
Member

@jmarrero jmarrero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ericcurtin ericcurtin merged commit e790e79 into ostreedev:main Feb 22, 2024
24 checks passed
@ericcurtin ericcurtin deleted the ostree-impl-system-generator-aboot branch February 22, 2024 17:06
@@ -261,17 +262,19 @@ _ostree_impl_system_generator (const char *normal_dir, const char *early_dir, co
if (!cmdline)
return glnx_throw (error, "Failed to read /proc/cmdline");

g_autofree char *ostree_cmdline = otcore_find_proc_cmdline_key (cmdline, "ostree");

g_autoptr (GError) otcore_get_ostree_target_error = NULL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't being checked. But anyway, why not pass error to the function? Looking at the code, not finding an ostree= karg isn't fatal.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't actually care so much if otcore_get_ostree_target fails but if there is no karg found for ostree selection we should return true for the CoreOS live environments.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the androidboot karg doesn't exist all behavior is identical to what this code was like previous to this commit...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a "error" passed to this function, I deliberately didn't use it and used this one instead otcore_get_ostree_target_error, because we don't care so much about the otcore_get_ostree_target_error errors. But we do care about the "error" errors.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or are we saying:

  if (!otcore_get_ostree_target (cmdline, &is_aboot, &ostree_target,
                                 NULL)

should work? Didn't do this just in case of NULL ptr dereference or something, but if you are confident this works ok I trust you 😄

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's totally OK to pass NULL for the GError**. But I guess the question is, do we want to ignore the "androidboot.slot_suffix invalid: %s" error? I don't see why we would special-case that one. We're strict everywhere else in this function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But actually, I think the issue is that the logic here is not correct. It should be e.g.

  if (!otcore_get_ostree_target (cmdline, &is_aboot, &ostree_target, error))
    return FALSE;
  /* This could happen ... */
  if (!ostree_target)
	return TRUE;

@@ -84,8 +84,10 @@ otcore_get_ostree_target (const char *cmdline, char **out_target, GError **error

// First, handle the Android boot case
g_autofree char *slot_suffix = otcore_find_proc_cmdline_key (cmdline, "androidboot.slot_suffix");
*is_aboot = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the callers, might as well make this argument optional so they can just pass NULL if they're not interested.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there examples of optional arguments in this codebase? I know we can't do that in C generally but maybe there's some extension to C etc. that does this we are using that I'm not aware of.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this context, optional means that the caller is allowed to pass NULL. So then in this function we'd do e.g.

if (is_aboot)
  *is_aboot = ...

Comment on lines 268 to 270
/* This could happen in CoreOS live environments, where we hackily mock
* the `ostree=` karg for `ostree-prepare-root.service` specifically, but
* otherwise that karg doesn't exist on the real command-line. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think now that the conditional is more complex, let's tweak the comment slightly to make it clearer that we're referring to the "no ostree= karg exists". E.g.

Suggested change
/* This could happen in CoreOS live environments, where we hackily mock
* the `ostree=` karg for `ostree-prepare-root.service` specifically, but
* otherwise that karg doesn't exist on the real command-line. */
/* If no `ostree=` karg exists, gracefully no-op.
* This could happen in CoreOS live environments, where we hackily mock
* the `ostree=` karg for `ostree-prepare-root.service` specifically, but
* otherwise that karg doesn't exist on the real command-line. */

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you've identified generally this comment no longer makes a lot of sense, the only place the function fails is in the case where slot_suffix isn't right

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

@ericcurtin ericcurtin Feb 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll rewrite the comment in this area, it's gonna be tomorrow morning, been online waaay too many hours this week

@@ -19,6 +19,8 @@

#pragma once

#include <stdbool.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: we do use bool in a few places already but not really in function signatures. Let's just keep using gboolean for consistency?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM

Comment on lines +746 to +748
regex = g_regex_new (is_aboot ? "^deploy/([^/]+)/"
: "^/ostree/boot.([01])/([^/]+)/([^/]+)/([0-9]+)$",
0, 0, NULL);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a conditional selector for the regex in a g_once looks highly suspect here. I think in practice it doesn't matter too much because you probably only have all aboot deployments or none. But the way the API for this function is structured leaves the door open. ISTM we probably want two static GRegexs instead.

Copy link
Collaborator Author

@ericcurtin ericcurtin Feb 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is I'd end up doing:

if (!g_regex_match (is_aboot ? aboot_regex : non_aboot_regex, to_parse, 0, &match))

so it wouldn't make a whole pile of difference.

/proc/cmdline is an immutable file. Each process re-runs g_once_init_enter.

We can do code like above (technically they are different regex strings), but it's not really gonna change much in reality. It's also gonna be more lines of duplicate code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll just write a _ostree_sysroot_parse_bootlink_aboot function altogether

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that much duplicate code. Basically I'm saying something like:

static GRegex *regex_aboot;
static GRegex *regex_ostree;

if (g_once_init_enter (...))
  {
    regex_aboot = ...
    regex_ostree = ...
  }

and move the ternary down to g_regex_match.

The difference is that the function correctly handles is_aboot actually being different on multiple calls in the same invocation. If we're saying that's never gonna happen, then I would refactor things to lift is_aboot to e.g. the OstreeSysroot level or so to say "this is an aboot-managed machine". Short-term, just handling this here correctly makes the code more obviously right when reading the function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote a _ostree_sysroot_parse_bootlink_aboot function instead in #3195, the only thing the aboot version had in common was that it was using a regex, it was starting to get messey.

@jmarrero
Copy link
Member

@ericcurtin can you address the @jlebon comments before I do the release?

@ericcurtin
Copy link
Collaborator Author

I'll open another PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/prepare-root Issue relates to ostree-prepare-root ok-to-test
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants