Skip to content

Add support for freezing filesystems before taking snapshots - #1022

Merged
dmitry-lyfar merged 3 commits into
mainfrom
feature/fsfreeze
Sep 10, 2026
Merged

Add support for freezing filesystems before taking snapshots#1022
dmitry-lyfar merged 3 commits into
mainfrom
feature/fsfreeze

Conversation

@jonathan-conder

Copy link
Copy Markdown
Contributor

Description

This doesn't really do much at the moment, but is needed in order to take consistent snapshots of VM filesystems.

Also fixes a potential race when running findmnt on /project; WaitExecution only waits on DataDone when the exec succeeded (but potentially had a nonzero exit status). With any error other than ErrExec there might not be synchronization between LXD writing to errbuf and us reading from it.

Self-review quick check

  • Make decisions that cost a lot to reverse explicit in the PR description.
  • Avoid nested conditions.
  • Delete dead code and redundant comments.
  • Normalise symmetries by sticking to doing identical things identically.
// one way to handle errors
if err := f(); err != nil {
   ...
}

// one way to handle multiple returns
val, err := f()
if err != nil {
   ...
}
...
  • Check that coupled code elements, files, and directories are adjacent. For example, test data is stored as close as possible to a test.
  • Put variable declaration and initialisation together.
  • Divide large expressions into digestable and self-explanatory ones. Use multiple variables if required.
  • Put a blank line between two logically different chunks of code.
  • Follow the style guide for new error messages.

Docs

Procedure:

  • I have checked and added or updated relevant documentation.
  • I have checked and added or updated relevant release notes.
  • I have included the technical author in the review.

Content:

  • Headings and titles accurately describe the content.
  • New and updated pages include correct metadata.
  • Documentation tests are added or updated where applicable (for tutorial/ and how-to/ sections).
  • Documentation follows the style guide.
  • If needed, docs/.coverage.yaml updated, coverage tags added (.. artefact).

Or:

  • I confirm the PR has no implications for documentation.

Copilot AI left a comment

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.

🟡 Changes recommended

The fsfreeze executable path is not provisioned, cancellation handling is inconsistent, and thaw failures can leave filesystems frozen without diagnosis.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds VM filesystem quiescing around LXD snapshots, improves execution-output synchronization, and hardens readiness signaling.

Changes:

  • Adds filesystem freeze/thaw implementation and tests.
  • Integrates freezing into snapshot creation and workshopctl.
  • Safely handles execution output and D-Bus readiness signals.
File summaries
File Description
cmd/workshopctl/main.go Adds fsfreeze multicall entry point.
internal/dirs/dirs.go Defines the guest fsfreeze path.
internal/fsfreeze/export_test.go Exposes test hooks.
internal/fsfreeze/fsfreeze.go Implements mount discovery and freeze/thaw behavior.
internal/fsfreeze/fsfreeze_test.go Tests filesystem handling and lifecycle behavior.
internal/fsfreeze/sys/generate.sh Generates ioctl constants.
internal/fsfreeze/sys/syscall_linux.go Wraps freeze/thaw ioctls.
internal/fsfreeze/sys/sysnum_linux.go Defines cgo generation input.
internal/fsfreeze/sys/zsysnum_linux.go Provides generated architecture constants.
internal/waitready/waitready.go Filters D-Bus readiness signals safely.
internal/workshop/lxd/lxd_backend_project.go Avoids unsafe stderr reads.
internal/workshop/lxd/lxd_backend_snapshots.go Freezes running VMs during snapshot copying.
internal/workshop/lxd/tests/helper/helper.go Supports fsfreeze in integration helpers.
Review details

Files not reviewed (1)

  • internal/fsfreeze/sys/zsysnum_linux.go: Generated file

Suppressed comments (1)

internal/fsfreeze/fsfreeze.go:215

  • Rollback silently ignores FITHAW failures after a later filesystem fails to freeze. In that case an earlier filesystem can remain frozen indefinitely while the process reports only the later freeze error. Collect rollback thaw errors and return them together with the triggering error, as the normal thaw path does.
	rev.Add(func() {
		for _, f := range slices.Backward(frozen) {
			_ = fsThaw(f)
			f.Close()
		}
  • Files reviewed: 12/13 changed files
  • Comments generated: 3
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/fsfreeze/fsfreeze.go
Comment thread internal/workshop/lxd/lxd_backend_snapshots.go
Comment thread internal/workshop/lxd/lxd_backend_snapshots.go Outdated

Copilot AI left a comment

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.

🟡 Changes recommended

Deferred rollback can leave filesystems frozen, and four malformed reusable-workflow paths prevent CI workflows from loading.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Files not reviewed (1)

  • internal/fsfreeze/sys/zsysnum_linux.go: Generated file

Suppressed comments (1)

.github/workflows/automatic-tests.yaml:35

  • This local reusable-workflow reference must begin with ./; the $/.github/... path is invalid and prevents the automatic-tests workflow from loading the unit-test job.
    uses: $/.github/workflows/unit-tests.yaml
  • Files reviewed: 18/19 changed files
  • Comments generated: 4
  • Review effort level: Balanced

Comment thread .github/workflows/automatic-tests.yaml
Comment thread .github/workflows/lxd-candidate-check.yaml
Comment thread .github/workflows/spread.yaml
Comment thread internal/fsfreeze/fsfreeze.go Outdated
This looks like a longstanding oversight; if checkPartialSnapshot
returns an error it means GetInstance failed or the snapshot is
complete. In the first case, deleting the snapshot will probably also
fail. In the second, the snapshot might already be in use.

On the other hand, returning nil means the snapshot doesn't exist (and
it can't be recreated while we hold the lock) or it was partially
complete; in either case it's OK (but not necessary) to delete it.

Copilot AI left a comment

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.

🟢 Approval recommended

The implementation has coherent freeze/thaw cleanup, focused unit coverage, and no unresolved correctness issues.

Review details

Files not reviewed (1)

  • internal/fsfreeze/sys/zsysnum_linux.go: Generated file
  • Files reviewed: 11/12 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@dmitry-lyfar
dmitry-lyfar merged commit d0e7d4c into main Sep 10, 2026
25 checks passed
@dmitry-lyfar
dmitry-lyfar deleted the feature/fsfreeze branch September 10, 2026 04:03
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.

3 participants