Skip to content

post: fstrim the sticky disk before unmount at commit - #82

Open
magma-beef wants to merge 7 commits into
mainfrom
devin/1792435014-post-fstrim-before-unmount
Open

magma-beef wants to merge 7 commits into
mainfrom
devin/1792435014-post-fstrim-before-unmount

Conversation

@magma-beef

@magma-beef magma-beef commented Oct 19, 2026 •

Copy link
Copy Markdown

In the post step, run fstrim on the sticky disk before it is unmounted and committed, so freed blocks are discarded from the backing image.

  • The agent sends a trim budget in GetStickyDiskResponse.fstrim_timeout_secs (field 8). main reads it (from the typed field, or from unknown field 8 when the bundled proto package predates it) and stores it in action state; 0/absent disables the trim.
  • post evaluates the full commit decision (mode, early deny, if-missing, on-change verdict, previous-step failures) before unmount and trims only when the budget is positive and a commit will be requested. Order: sync → df sample → trim → drop_caches → umount → flushbufs.
  • Best-effort: timeout <budget> sudo fstrim -v; a missing binary, unsupported discard, or timeout only logs and never fails the step.

Start here: src/post.ts (commit decision, trim ordering), then src/mount.ts (trimFilesystem, fstrimTimeoutSecsFrom). dist/ is regenerated.

Checks: npm run lint, npx tsc --noEmit -p ., npm test, npm run build.

Link to Devin session: https://app.devin.ai/sessions/2e17815c306b4c3cb7af4f6bce008a66
Open in Devin Desktop: https://app.devin.ai/desktop/session/2e17815c306b4c3cb7af4f6bce008a66?variant=devin
Requested by: @magma-beef


Devin Review


View with [code]smith View full Proof
Need help on this PR? Tag @codesmith-bot with what you need. (Staging)


View with [code]smith Prove this works
Need help on this PR? Tag @codesmith-bot with what you need.

Sticky disks are RBD images; blocks a job frees are only reclaimed by the backing store once the guest discards them, so without a trim deleted files keep their 4 MiB RBD objects allocated and the disk's real usage ratchets up to its high-water mark. Run a best-effort `timeout 60 sudo fstrim -v` on the mount right before unmount, only when the commit will actually be requested, mirroring the docker-cache disk's trim in job_completed.sh. The trim never fails the post step and is a no-op until the hypervisor negotiates discard for the device.

The commit decision (commit mode, early denial, on-change verdict, prior step failures) is now evaluated before unmount so the trim can be skipped for disks whose snapshot will be discarded.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@devin-ai-integration devin-ai-integration 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.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review October 19, 2026 19:53
@blacksmith-staging

blacksmith-staging Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Matches Post step trims freed blocks before unmount

After, main saved the budget and post ran fstrim between the df sample and drop_caches/umount, shrinking the backing image from 1026 MiB to 2 MiB; before, no trim ran and the image stayed at 1026 MiB.

Merge-base

Post step before

This PR 0afafedb

Post step after

Also checked · 4 match

Matches No trim when no commit will be requested
Matches Budget 0 or absent disables the trim
Matches Unsupported discard only logs
Matches Host min extent passed as fstrim -m

Proof on 0afafedb (from b19c797c)

View full Proof report

@piob-io

piob-io commented Oct 19, 2026

Copy link
Copy Markdown

Waiting 60s is too long. How short can it be while staying useful. 5s? Also... since this code gets rolled out by customers, I feel like we should make it so we can inject this delay from the fa agent side, so we can do a slow rollout, and tune this in the future.

@devin-ai-integration

Copy link
Copy Markdown

Agreed on both. Plan:

  • fa: add fstrim_timeout_secs to GetStickyDiskResponse, sourced from a new live-config key (guest_fstrim_timeout_secs, built-in default 0 = guest does not trim). That gives a slow rollout + per-host/global tuning from the agent side without a new action release.
  • this PR: drop the hard-coded 60 s; the post step only trims when the agent sent a positive timeout and uses that value. Until the fa change is rolled out the action is a no-op here. I'll start with 5 s as the value we set via live config; a timed-out trim is still useful since ext4 FITRIM keeps the extents it already discarded.

The action can't compile against the new field until the proto lands on buf.build, so I'll link the fa PR here and update this one once it merges.

The VM agent now returns GetStickyDiskResponse.fstrim_timeout_secs (fa
live config guest_fstrim_timeout_secs). The main step saves it in action
state and the post step trims only when it is positive, bounded by that
many seconds, so the trim is off until a host enables it and its budget
can be tuned without a new action release. Read through a cast so the
action keeps compiling against the current generated proto package.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
cursor[bot]

This comment was marked as resolved.

…ckage predates it

The bundled GetStickyDiskResponse has no fstrim_timeout_secs yet, and protobuf-es keeps fields it does not know in the message's unknown-field list (the gRPC transport is binary), so decode field 8 from there when the typed field is absent. Releases built before the field existed therefore honour the host budget once the agent sends it, which is what makes an agent-side rollout possible.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown

Re @piob-io's comment (#82 (comment)) — implemented as of c4a2f7b:

  • No fixed timeout in the action any more. The VM agent sends the budget in GetStickyDiskResponse.fstrim_timeout_secs (FastActions/fa#6600: live-config key guest_fstrim_timeout_secs, default 0 = no trim), main saves it in action state, post trims only when it is positive and the commit will be requested, bounded by timeout <secs>.
  • Works on this action version even before its proto package is bumped: when the typed field is absent the value is read from unknown field 8 (protobuf-es keeps unknown binary fields over gRPC), so a slow per-host rollout and later tuning need no new action release.
  • On "how short": a trim of an already-trimmed disk is sub-second; the first trim of a large dirty disk is what costs time, and with a budget it just stops early and the rest is picked up next run. Proposed start is 5 s per host; the post step logs fstrim <mount>: trimmed|timed_out|failed in <ms> so we can see the distribution before raising it.

Same shape for the docker (useblacksmith/setup-docker-builder) and git-mirror (useblacksmith/checkout) actions, branches pending PRs; the web schema PR adds the key to AgentConfigSchema.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
magma-beef and others added 3 commits October 23, 2026 00:08
Bump @buf/blacksmith_vm-agent.bufbuild_es to a build that includes
GetStickyDiskResponse.fstrim_timeout_secs (fa #6600) and drop the
unknown-field-8 decoding.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
GetStickyDiskResponse.fstrim_min_extent_bytes (fa #6823) is saved as
action state alongside the timeout budget and, when positive, becomes
`fstrim -m <bytes>` so free extents smaller than the host's threshold are
not discarded. Zero or absent leaves fstrim at its default. Bumps the
@buf vm-agent packages to the fa main build that carries field 9.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants