Skip to content

Kargs source#2114

Draft
jmarrero wants to merge 2 commits intobootc-dev:mainfrom
jmarrero:kargs-source
Draft

Kargs source#2114
jmarrero wants to merge 2 commits intobootc-dev:mainfrom
jmarrero:kargs-source

Conversation

@jmarrero
Copy link
Copy Markdown
Contributor

@jmarrero jmarrero commented Apr 1, 2026

Add a new bootc loader-entries set-options-for-source command that
manages kernel arguments from independent sources (e.g. TuneD, admin)
by tracking ownership via x-options-source-<name> extension keys in
BLS config files. This solves the problem of karg accumulation on bootc
systems with transient /etc, where tools like TuneD lose their state
files on reboot and can't track which kargs they previously set.

The command stages a new deployment with the updated kargs and source
keys. The kargs diff is computed by removing the old source's args and
adding the new ones, preserving all untracked options. Source keys
survive the staging roundtrip via ostree's bootconfig-extra
serialization (ostree >= 2026.1, version check present but commented
out until release).

Staged deployment handling:

  • No staged deployment: stages based on the booted commit
  • Staged deployment exists (e.g. from bootc upgrade): replaces it
    using the staged commit and origin, preserving pending upgrades while
    layering the source kargs change on top

Example usage:
bootc loader-entries set-options-for-source --source tuned
--options "isolcpus=1-3 nohz_full=1-3"

See: ostreedev/ostree#3570

jmarrero added 2 commits April 1, 2026 16:52
…kargs

Add a new `bootc loader-entries set-options-for-source` command that
manages kernel arguments from independent sources (e.g. TuneD, admin)
by tracking ownership via `x-options-source-<name>` extension keys in
BLS config files. This solves the problem of karg accumulation on bootc
systems with transient /etc, where tools like TuneD lose their state
files on reboot and can't track which kargs they previously set.

The command stages a new deployment with the updated kargs and source
keys. The kargs diff is computed by removing the old source's args and
adding the new ones, preserving all untracked options. Source keys
survive the staging roundtrip via ostree's `bootconfig-extra`
serialization (ostree >= 2026.1, version check present but commented
out until release).

Staged deployment handling:
- No staged deployment: stages based on the booted commit
- Staged deployment exists (e.g. from `bootc upgrade`): replaces it
  using the staged commit and origin, preserving pending upgrades while
  layering the source kargs change on top

Example usage:
  bootc loader-entries set-options-for-source --source tuned \
    --options "isolcpus=1-3 nohz_full=1-3"

See: ostreedev/ostree#3570
See: bootc-dev#899

Assisted-by: OpenCode (Claude claude-opus-4-6)
…urce

Add a multi-reboot integration test covering the full lifecycle of
source-tracked kernel arguments:

- Input validation (invalid/empty source names, special characters)
- Adding source-tracked kargs and verifying /proc/cmdline after reboot
- x-options-source-* BLS keys surviving the staging roundtrip
- Source replacement semantics (old kargs removed, new ones added)
- Multiple sources coexisting independently
- Source removal (--source without --options clears owned kargs)
- Idempotent operation (no deployment staged when kargs unchanged)

The test uses 4 reboots across 5 phases, matching the same scenarios
as the rpm-ostree kolainst test but adapted for the bootc CLI and
TMT test framework.

Also includes auto-generated man pages for the new loader-entries
subcommand.

Assisted-by: OpenCode (Claude claude-opus-4-6)
@github-actions github-actions bot added the area/documentation Updates to the documentation label Apr 1, 2026
@bootc-bot bootc-bot bot requested a review from ckyrouac April 1, 2026 21:13
@jmarrero
Copy link
Copy Markdown
Contributor Author

jmarrero commented Apr 1, 2026

Draft while I continue testing.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the loader-entries subcommand to manage kernel arguments from multiple independent sources by tracking them via extension keys in BLS configuration files. The implementation includes logic for merging source-specific options and staging new deployments. Review feedback identifies a logic gap in source discovery for staged deployments that could lead to incorrect merging or duplicate arguments, and also recommends replacing blocking synchronous I/O with asynchronous alternatives to prevent performance issues within the async executor.

Comment on lines +198 to +204
for (name, _) in &booted_sources {
let key = format!("{OPTIONS_SOURCE_KEY_PREFIX}{name}");
if let Some(val) = bootconfig.get(&key) {
sources.insert(name.clone(), CmdlineOwned::from(val.to_string()));
}
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The discovery logic for source keys in staged deployments is incomplete. It only iterates over source names found in the booted BLS entry. If a new source was added in a previous staged deployment (but not yet booted), it won't be discovered here, even if it exists in the staged bootconfig. This can lead to incorrect merging or duplicate kernel arguments. You should explicitly check for the target_source in the bootconfig even if it's not in booted_sources.

        if let Ok(bls_content) = read_bls_entry_for_deployment(sysroot, &booted) {
            let booted_sources = extract_source_options_from_bls(&bls_content);
            for (name, _) in &booted_sources {
                let key = format!("{OPTIONS_SOURCE_KEY_PREFIX}{name}");
                if let Some(val) = bootconfig.get(&key) {
                    sources.insert(name.clone(), CmdlineOwned::from(val.to_string()));
                }
            }
        }
        // Ensure the target source is also discovered if it exists in the staged bootconfig
        let target_key = format!("{OPTIONS_SOURCE_SOURCE_KEY_PREFIX}{source}");
        if let Some(val) = bootconfig.get(&target_key) {
            sources.insert(source.to_string(), CmdlineOwned::from(val.to_string()));
        }

Comment on lines +112 to +114
for entry in std::fs::read_dir(&entries_dir)
.with_context(|| format!("Reading {}", entries_dir.display()))?
{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This function performs blocking synchronous I/O (std::fs::read_dir) within an asynchronous context (it is called by run_from_opt which is async). In a tokio environment, blocking the executor can lead to performance issues. Consider using tokio::fs or wrapping the blocking calls in tokio::task::spawn_blocking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/documentation Updates to the documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant