Skip to content

vmspawn: let SetMemory() report progress with 'more' - #44403

Open
katexochen wants to merge 2 commits into
systemd:mainfrom
katexochen:vmspawn-balloon-1-1
Open

katexochen wants to merge 2 commits into
systemd:mainfrom
katexochen:vmspawn-balloon-1-1

Conversation

@katexochen

Copy link
Copy Markdown
Member

Follow-up to #44318, as suggested in its review: instead of polling
Describe() to see whether the guest followed a SetMemory() request,
callers can now pass 'more' and get a notification whenever the
guest's balloon moves, then a final reply once it reached the target.

Partial convergence is normal (unmovable pages, deflate-on-oom), so a
call also ends with a final reply once the size did not change for
five seconds; the caller compares targetBytes and actualBytes. A newer
request ends a still pending call with the new Superseded error.
Without 'more' the call behaves as before, but its reply now carries
the effective target and the current size, since vmspawn rounds the
requested size up to 64 KiB.

TEST-97 now waits through 'more' and covers the Superseded path, using
a paused VM so the pending call cannot complete first.

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Reviewed 6797b73 (architecture, correctness, lifetimes, security, style, tests).

Suggestions

  • src/vmspawn/vmspawn-memory.c:133 Every balloon change re-arms the 5s stall timer. A guest that keeps moving its balloon (deflate-on-oom, then reinflating, or on purpose) holds a 'more' call open forever, and callers without their own timeout hang. Add an overall deadline that doesn't get extended here.
  • src/vmspawn/vmspawn-memory.h:13 When the backend goes away, on_qmp_disconnect() closes the event subscribers but leaves a pending progress_link alone. If the process outlives the 5s stall timer, the call then gets a success reply with stale sizes. End it with NotConnected from the disconnect path.
  • test/units/TEST-97-VMSPAWN-MEMORY.balloon.sh:110 Pausing doesn't actually guarantee this. The 5s stall timer starts when QEMU accepts the first call and keeps running while the vCPUs are paused. If the Describe poll (allowed 10s) plus the second call take longer than 5s, the first call returns success and assert_neq fails. Fix the comment and keep the window under 5s.
  • src/vmspawn/vmspawn-memory.c:126 previous is from before the new target. If a 'more' call reverses direction while the guest is still moving toward the old target, the next BALLOON_CHANGE can still be a step away from the new one: an in-flight balloon batch, or an event QEMU throttled up to 1s. The call then ends at once, short of the target. Only run the moved-away check after a first step toward the new target.

Nits

  • src/vmspawn/vmspawn-memory.c:125 If notify or rearm fails, the call still ends with a normal success reply, so the caller can't tell it was aborted. on_balloon_complete() uses sd_varlink_error_errno() for the same rearm failure; do that here too.
  • man/systemd-vmspawn.xml:229 The paragraph wasn't reflowed, so "it is permitted to deflate the" is left as a short dangling line before "balloon on its own". Reflow the rest of the paragraph.
  • src/shared/varlink-io.systemd.MachineInstance.c:105 The continuation strings are indented 5 columns too far. Elsewhere (e.g. varlink-io.systemd.Resolve.Hook.c) they line up with the opening quote after SD_VARLINK_SYMBOL_COMMENT(.
  • test/units/TEST-97-VMSPAWN-MEMORY.balloon.sh:64 Both callers pass the same value for BYTES and WANT, so WANT is redundant. Drop it, compare against $bytes, and call it as set_memory_and_wait "$RAM" and set_memory_and_wait "$SMALL".

Workflow run

@github-actions github-actions Bot added documentation tests util-lib vmspawn please-review PR is ready for (re-)review by a maintainer labels Oct 23, 2026
Comment thread src/vmspawn/vmspawn-memory.c
Comment thread src/vmspawn/vmspawn-memory.h
Comment thread test/units/TEST-97-VMSPAWN-MEMORY.balloon.sh Outdated
Comment thread src/vmspawn/vmspawn-memory.c Outdated
Comment thread man/systemd-vmspawn.xml Outdated
Comment thread src/shared/varlink-io.systemd.MachineInstance.c Outdated
Comment thread test/units/TEST-97-VMSPAWN-MEMORY.balloon.sh Outdated
With the 'more' flag, SetMemory() notifies the caller whenever the
guest's balloon moves and replies once the guest reached the target,
or once the size did not change for five seconds, since partial
convergence is normal. A newer request ends a pending call with the
new Superseded error. The reply now also carries the effective target
and the current size.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
Wait for convergence through SetMemory() with 'more' instead of
polling Describe(), except for the first shrink, where the guest may
not have loaded its balloon driver yet. Also check that a newer
request ends a pending call with Superseded.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
Comment on lines +123 to +126
/* Also end the call once the guest moves away from the target, e.g. on deflate-on-oom, so that
* a guest moving its balloon back and forth cannot hold it open forever. */
if (actual == m->target ||
(previous > 0 && ABS_DIFF(actual, m->target) >= ABS_DIFF(previous, m->target))) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude: suggestion: previous is from before the new target. If a 'more' call reverses direction while the guest is still moving toward the old target, the next BALLOON_CHANGE can still be a step away from the new one: an in-flight balloon batch, or an event QEMU throttled up to 1s. The call then ends at once, short of the target. Only run the moved-away check after a first step toward the new target.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

valid, but let's rather try to keep the mechanism simple for now. I think there are a lot of corner cases here, but I want to postpone handling every single one to the point where the code is a bit more stable. Ending the more call early isn't that bad of a failure mode for something experimental.

This branch has not been deployed

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

Development

Successfully merging this pull request may close these issues.

1 participant