Skip to content
Merged
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
2 changes: 1 addition & 1 deletion crates/lib/src/bootc_composefs/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ pub(crate) async fn delete_composefs_deployment(

delete_depl_boot_entries(&depl_to_del, &storage, deleting_staged)?;

composefs_gc(storage, booted_cfs, true).await?;
composefs_gc(storage, booted_cfs, false, true).await?;

Ok(())
}
6 changes: 5 additions & 1 deletion crates/lib/src/bootc_composefs/finalize.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::path::Path;

use crate::bootc_composefs::boot::BootType;
use crate::bootc_composefs::gc::composefs_gc;
use crate::bootc_composefs::rollback::{rename_exchange_bls_entries, rename_exchange_user_cfg};
use crate::bootc_composefs::status::get_composefs_status;
use crate::composefs_consts::STATE_DIR_ABS;
Expand Down Expand Up @@ -123,7 +124,6 @@ pub(crate) async fn composefs_backend_finalize(

let boot_dir = storage.require_boot_dir()?;

// NOTE: Assuming here we won't have two bootloaders at the same time
match booted_composefs.bootloader {
Bootloader::Grub => match staged_composefs.boot_type {
BootType::Bls => {
Expand All @@ -141,6 +141,10 @@ pub(crate) async fn composefs_backend_finalize(
Bootloader::None => unreachable!("Checked at install time"),
};

// Now that we have successfully updated bootloader entires, we can GC the unreferenced ones
// We do not prune the composefs repository here though
composefs_gc(storage, booted_cfs, false, false).await?;

Ok(())
}

Expand Down
5 changes: 5 additions & 0 deletions crates/lib/src/bootc_composefs/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ pub(crate) async fn composefs_gc(
storage: &Storage,
booted_cfs: &BootedComposefs,
dry_run: bool,
prune_repo: bool,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Two boolean arguments is ugly and confusing. Let's have a single enum GcMode.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Or probably dry_run: bool with enum GcDepth or so.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Eh it's fine we can just do this type of style fixup after too!

) -> Result<GcResult> {
const COMPOSEFS_GC_JOURNAL_ID: &str = "3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7";

Expand Down Expand Up @@ -288,6 +289,10 @@ pub(crate) async fn composefs_gc(
}
}

if !prune_repo {
return Ok(GcResult::default());
}

// Identify orphaned deployments: state dirs or bootloader entries
// that don't correspond to a live deployment. EROFS images in
// composefs/images/ are NOT managed here — repo.gc() handles those
Expand Down
2 changes: 1 addition & 1 deletion crates/lib/src/bootc_composefs/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ pub(crate) async fn do_upgrade(

// We take into account the staged bootloader entries so this won't remove
// the currently staged entry
composefs_gc(storage, booted_cfs, false).await?;
composefs_gc(storage, booted_cfs, false, true).await?;

apply_upgrade(storage, booted_cfs, &id.to_hex(), opts).await
}
Expand Down
7 changes: 6 additions & 1 deletion crates/lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,9 @@ pub(crate) enum InternalsOpts {
/// Implies `--dry-run`. Intended for use in tests and health-checks.
#[clap(long)]
assert_no_op: bool,
/// Prune the composefs repository in addition to boot binaries
#[clap(long)]
prune_repo: bool,
},
/// Block device inspection tools.
#[clap(subcommand)]
Expand Down Expand Up @@ -2208,6 +2211,7 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
InternalsOpts::ComposefsGC {
dry_run,
assert_no_op,
prune_repo,
} => {
let storage = &get_storage().await?;

Expand All @@ -2219,7 +2223,8 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
BootedStorageKind::Composefs(booted_cfs) => {
let effective_dry_run = dry_run || assert_no_op;
let gc_result =
composefs_gc(storage, &booted_cfs, effective_dry_run).await?;
composefs_gc(storage, &booted_cfs, effective_dry_run, prune_repo)
.await?;

if effective_dry_run {
println!("Dry run (no files deleted)");
Expand Down
38 changes: 6 additions & 32 deletions tmt/tests/booted/test-composefs-gc-uki.nu
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,12 @@ def first_boot [] {

echo $containerfile | podman build -t localhost/bootc-first . -f -

let current_time = (date now)

bootc switch --transport containers-storage localhost/bootc-first

# Find the large file's verity and save it
# nu has its own built in find which sucks, so we use the other one
# TODO: Replace this with some concrete API
# See: https://github.com/composefs/composefs-rs/pull/236
let file_path = (
/usr/bin/find /sysroot/composefs/objects -type f -size 1337k -newermt ($current_time | format date "%Y-%m-%d %H:%M:%S")
| xargs grep -lx "large-file-marker"
)

echo $file_path | save /var/large-file-marker-objpath
cat /var/large-file-marker-objpath
let new_st = bootc status --json | from json
let path = bootc internals cfs dump-files $new_st.status.staged.composefs.verity /usr/share/large-test-file --backing-path-only | awk '{print $2}'
echo $"/sysroot/composefs/objects/($path)" | save /var/large-file-marker-objpath

echo $st.status.booted.composefs.verity | save /var/boot0-verity

Expand All @@ -68,7 +59,6 @@ def second_boot [] {
echo $st.status.booted.composefs.verity | save /var/boot1-verity

let path = cat /var/large-file-marker-objpath

assert ($path | path exists)

mut containerfile = echo "
Expand All @@ -90,7 +80,7 @@ def third_boot [] {
mount /dev/disk/by-partlabel/EFI-SYSTEM /var/tmp/efi

assert equal $booted.image.image "localhost/bootc-second"
assert ($"/var/tmp/efi/EFI/Linux/bootc/($uki_prefix)(cat /var/boot0-verity).efi" | path exists)
assert (not ($"/var/tmp/efi/EFI/Linux/bootc/($uki_prefix)(cat /var/boot0-verity).efi" | path exists))
assert ($"/var/tmp/efi/EFI/Linux/bootc/($uki_prefix)(cat /var/boot1-verity).efi" | path exists)

echo $st.status.booted.composefs.verity | save /var/boot2-verity
Expand Down Expand Up @@ -119,12 +109,9 @@ def fourth_boot [] {
mount /dev/disk/by-partlabel/EFI-SYSTEM /var/tmp/efi

assert equal $booted.image.image "localhost/bootc-third"
assert (not ($"/var/tmp/efi/EFI/Linux/bootc/($uki_prefix)(cat /var/boot0-verity).efi" | path exists))
assert ($"/var/tmp/efi/EFI/Linux/bootc/($uki_prefix)(cat /var/boot1-verity).efi" | path exists)
assert (not ($"/var/tmp/efi/EFI/Linux/bootc/($uki_prefix)(cat /var/boot1-verity).efi" | path exists))
assert ($"/var/tmp/efi/EFI/Linux/bootc/($uki_prefix)(cat /var/boot2-verity).efi" | path exists)

echo $st.status.booted.composefs.verity | save /var/boot3-verity

mut containerfile = "
FROM localhost/bootc as base
RUN echo 'another file' > /usr/share/another-one
Expand All @@ -135,22 +122,10 @@ def fourth_boot [] {
echo $containerfile | podman build -t localhost/bootc-final . -f -

bootc switch --transport containers-storage localhost/bootc-final
tap ok
}

def fifth_boot [] {
mkdir /var/tmp/efi
mount /dev/disk/by-partlabel/EFI-SYSTEM /var/tmp/efi

assert equal $booted.image.image "localhost/bootc-final"

assert (not ($"/var/tmp/efi/EFI/Linux/bootc/($uki_prefix)(cat /var/boot1-verity).efi" | path exists))
assert ($"/var/tmp/efi/EFI/Linux/bootc/($uki_prefix)(cat /var/boot2-verity).efi" | path exists)
assert ($"/var/tmp/efi/EFI/Linux/bootc/($uki_prefix)(cat /var/boot3-verity).efi" | path exists)

# We had this in boot1 (second boot)
let path = cat /var/large-file-marker-objpath
assert (not ($path | path exists))

tap ok
}

Expand All @@ -160,7 +135,6 @@ def main [] {
"1" => second_boot,
"2" => third_boot,
"3" => fourth_boot,
"4" => fifth_boot,
$o => { error make { msg: $"Invalid TMT_REBOOT_COUNT ($o)" } },
}
}
Expand Down
50 changes: 12 additions & 38 deletions tmt/tests/booted/test-composefs-gc.nu
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,12 @@ def first_boot [] {
RUN echo 'large-file-marker' | dd of=/usr/share/large-test-file conv=notrunc
" | podman build -t localhost/bootc-derived . -f -

let current_time = (date now)

bootc switch --transport containers-storage localhost/bootc-derived

# Find the large file's verity and save it
# nu has its own built in find which sucks, so we use the other one
# TODO: Replace this with some concrete API
# See: https://github.com/composefs/composefs-rs/pull/236
let file_path = (
/usr/bin/find /sysroot/composefs/objects -type f -size 1337k -newermt ($current_time | format date "%Y-%m-%d %H:%M:%S")
| xargs grep -lx "large-file-marker"
)

echo $file_path | save /var/large-file-marker-objpath
cat /var/large-file-marker-objpath
let new_st = bootc status --json | from json
let path = bootc internals cfs dump-files $new_st.status.staged.composefs.verity /usr/share/large-test-file --backing-path-only | awk '{print $2}'
echo $"/sysroot/composefs/objects/($path)" | save /var/large-file-marker-objpath

echo $st.status.booted.composefs.verity | save /var/first-verity

Expand Down Expand Up @@ -123,22 +114,6 @@ def third_boot [] {
echo "
FROM localhost/bootc-derived-initrd
RUN echo 'another file' > /usr/share/another-one
" | podman build -t localhost/bootc-prefinal . -f -


bootc switch --transport containers-storage localhost/bootc-prefinal

tmt-reboot
}

def fourth_boot [] {
assert equal $booted.image.image "localhost/bootc-prefinal"

# Now we create a new image derived from the current kernel + initrd
# Switching to this and rebooting should remove the old kernel + initrd
echo "
FROM localhost/bootc-derived-initrd
RUN echo 'another file 1' > /usr/share/another-one-1
" | podman build -t localhost/bootc-final . -f -


Expand All @@ -147,7 +122,7 @@ def fourth_boot [] {
tmt-reboot
}

def fifth_boot [] {
def fourth_boot [] {
let bootloader = (bootc status --json | from json).status.booted.composefs.bootloader

if ($bootloader | str downcase) == "systemd" {
Expand All @@ -156,10 +131,6 @@ def fifth_boot [] {
mount /dev/disk/by-partlabel/EFI-SYSTEM /var/tmp/efi
}

# The large file should be GC'd in the previous switch
let path = cat /var/large-file-marker-objpath
assert (not ($path | path exists))

assert equal $booted.image.image "localhost/bootc-final"
assert (not ((cat /var/to-be-deleted-kernel | path exists)))

Expand All @@ -174,10 +145,14 @@ def fifth_boot [] {

bootc switch --transport containers-storage localhost/bootc-shared-1

# The large file should be GC'd in the previous switch
let path = cat /var/large-file-marker-objpath
assert (not ($path | path exists))

tmt-reboot
}

def sixth_boot [i: int] {
def fifth_boot [i: int] {
assert equal $booted.image.image $"localhost/bootc-shared-($i)"

# Just this being booted counts as success
Expand All @@ -201,10 +176,9 @@ def main [] {
"1" => second_boot,
"2" => third_boot,
"3" => fourth_boot,
"4" => fifth_boot,
"5" => { sixth_boot 1 },
"6" => { sixth_boot 2 },
"7" => { sixth_boot 3 },
"4" => { fifth_boot 1 },
"5" => { fifth_boot 2 },
"6" => { fifth_boot 3 },
$o => { error make { msg: $"Invalid TMT_REBOOT_COUNT ($o)" } },
}
}
Expand Down