Skip to content

Report free space in on-disk order and stop GEOM label shadowing - #29

Merged
ericbsd merged 1 commit into
masterfrom
freespace-rework
Aug 28, 2026
Merged

ericbsd merged 1 commit into
masterfrom
freespace-rework

Conversation

@ericbsd

@ericbsd ericbsd commented Aug 28, 2026 •

Copy link
Copy Markdown

disk-part.sh and part-label.sh built their output from get_disk_partitions and get_partitions_lables, which return only the occupied entries, then appended a single freemb value for the largest gap. A front-end had no way to tell where a gap sat, so it could not merge free space with the neighbours it touches after a delete.

Both scripts now walk gpart show directly. gpart sorts entries by start block, so emitting each line as it is read puts every gap in its true position between the entries it separates, reported as freespaceN-blockstart, -blocksize and -sizemb. blocksize is exact and sizemb rounds down, reading 0 for a gap under 2048 blocks.

disk-info.sh derived the controller type by scraping dmesg, which returns nothing once the boot messages have rolled out of the ring buffer. The device name prefix is the CAM peripheral that attached, so map that to the protocol family instead.

None of that helps if gpart cannot read the disk at all. kern.geom.label.disk_ident and kern.geom.label.gptid default to enabled, so GEOM tastes a raw disk twice and adaX coexists with diskid/DISK-. Once the installed system imports its pool, the pool binds to the diskid provider and GEOM withdraws the raw partition geom for the whole disk. gpart(8) then fails on that disk and its /dev/adaXpY nodes stop resolving. run_final_cleanup now disables both labels on the installed system.

setup_fstab writes raw ${PARTDEV} paths for every non-ZFS entry, so a ZFS install still has swap and the EFI mount pointing at those nodes. Write both lines unconditionally rather than gating them on ZFS, since the entries that break sit beside the pool on the same disk. sysrc cannot set these; it rejects dotted names, hence the appends.

Summary by Sourcery

Preserve disk layout ordering and raw-device availability so front-ends can manage free space and installed systems can reliably access their partitions.

New Features:

  • Report every free-space gap in on-disk order, including its starting block, exact block size, and rounded megabyte size.
  • Identify disk protocol families from device-name prefixes instead of transient dmesg output.

Bug Fixes:

  • Prevent GEOM disk-identification labels from shadowing raw disks and breaking gpart access and installed swap or EFI devices.
  • Ensure fstab entries for non-ZFS filesystems are written for ZFS installations as well.

Enhancements:

  • Read partition and label metadata directly from gpart output while preserving the physical ordering of entries and gaps.

disk-part.sh and part-label.sh built their output from
get_disk_partitions and get_partitions_lables, which return only the
occupied entries, then appended a single freemb value for the largest
gap. A front-end had no way to tell where a gap sat, so it could not
merge free space with the neighbours it touches after a delete.

Both scripts now walk gpart show directly. gpart sorts entries by start
block, so emitting each line as it is read puts every gap in its true
position between the entries it separates, reported as
freespaceN-blockstart, -blocksize and -sizemb. blocksize is exact and
sizemb rounds down, reading 0 for a gap under 2048 blocks.

disk-info.sh derived the controller type by scraping dmesg, which
returns nothing once the boot messages have rolled out of the ring
buffer. The device name prefix is the CAM peripheral that attached, so
map that to the protocol family instead.

None of that helps if gpart cannot read the disk at all.
kern.geom.label.disk_ident and kern.geom.label.gptid default to enabled,
so GEOM tastes a raw disk twice and adaX coexists with
diskid/DISK-<serial>. Once the installed system imports its pool, the
pool binds to the diskid provider and GEOM withdraws the raw partition
geom for the whole disk. gpart(8) then fails on that disk and its
/dev/adaXpY nodes stop resolving. run_final_cleanup now disables both
labels on the installed system.

setup_fstab writes raw ${PARTDEV} paths for every non-ZFS entry, so a
ZFS install still has swap and the EFI mount pointing at those nodes.
Write both lines unconditionally rather than gating them on ZFS, since
the entries that break sit beside the pool on the same disk. sysrc
cannot set these; it rejects dotted names, hence the appends.
@ericbsd
ericbsd requested review from a team as code owners August 28, 2026 21:30
@sourcery-ai

sourcery-ai Bot commented Aug 28, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

The PR changes disk and partition reporting to stream gpart’s on-disk layout, including each free-space gap, replaces fragile dmesg-based protocol detection with device-prefix mapping, and prevents GEOM label providers from hiding raw devices needed by installed fstab entries.

Sequence diagram for on-disk partition and free-space reporting

sequenceDiagram
    participant Frontend
    participant DiskPart as disk-part.sh
    participant Gpart as gpart
    Frontend->>DiskPart: request disk layout
    DiskPart->>Gpart: gpart show DISK
    Gpart-->>DiskPart: entries sorted by start block
    loop each layout entry
        alt partition entry
            DiskPart-->>Frontend: partition blockstart, blocksize, sizemb
        else free-space entry
            DiskPart-->>Frontend: freespaceN blockstart, blocksize, sizemb
        end
    end
Loading

Sequence diagram for persistent disk protocol detection

sequenceDiagram
    participant DiskInfo as disk-info.sh
    participant Device as device name
    DiskInfo->>Device: inspect DISK prefix
    alt ada or ad
        Device-->>DiskInfo: ATA
    else da
        Device-->>DiskInfo: SCSI
    else nvd or nda
        Device-->>DiskInfo: NVMe
    else vtbd
        Device-->>DiskInfo: VirtIO
    else mmcsd, md, or unknown
        Device-->>DiskInfo: mapped protocol or Unknown
    end
Loading

File-Level Changes

Change Details Files
Emit partition and free-space entries directly from gpart in on-disk order.
  • Replace occupied-partition helper output with gpart parsing.
  • Report every gap with exact block start/size and rounded-down MiB size.
  • Preserve MBR/GPT device naming and derive partition labels from gpart fields.
  • Retain the legacy largest-free-space summary in label output.
backend-query/disk-part.sh
backend-query/part-label.sh
Make controller protocol detection independent of the dmesg ring buffer.
  • Map device-name prefixes to ATA, SCSI, NVMe, MMC, VirtIO, Memory, or Unknown.
backend-query/disk-info.sh
Disable GEOM disk-identification labels in the installed system to prevent raw-device shadowing.
  • Append disk_ident and gptid label-disable settings to the target loader configuration during final cleanup.
backend/functions-cleanup.sh
Ensure installed fstab entries continue to reference raw partition devices alongside ZFS.
  • Write swap and EFI/raw-device entries unconditionally rather than gating them on ZFS.
  • Use loader.conf appends because sysrc cannot handle dotted setting names.
backend/functions-cleanup.sh

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Needs a human reviewer. The installer permanently disables disk and GPT-ID GEOM labels, so an incorrect device-addressing assumption could leave installed systems unable to boot or access swap, EFI, or imported storage. Reverting the configuration can restore behavior, but if the system is already unbootable that recovery requires out-of-band access.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@ericbsd
ericbsd merged commit d522f71 into master Aug 28, 2026
2 checks passed
@ericbsd
ericbsd deleted the freespace-rework branch August 28, 2026 21:41
@github-project-automation github-project-automation Bot moved this from In Review to Done in Development Tracker Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants