Skip to content

Linstor add support for incremental nasbackup - #14194

Open
rp- wants to merge 7 commits into
apache:4.22from
LINBIT:linstor-4.22-nasbackup-incremental
Open

rp- wants to merge 7 commits into
apache:4.22from
LINBIT:linstor-4.22-nasbackup-incremental

Conversation

@rp-

@rp- rp- commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR adds incremental NAS backup support for KVM VMs whose disks live on raw block-device storage such as LINSTOR/DRBD.

#13877 (backport of #13074) implements incremental NAS backups with QEMU dirty bitmaps and libvirt checkpoints. Bitmap persistence is a qcow2-only feature, so allVolumesOnCheckpointCapableStorage() excludes raw block devices and every LINSTOR VM stays pinned to full-only backups regardless of the configured cadence. On top of that, the push-mode full backup of a raw device writes a fully allocated qcow2 which then needs a second qemu-img convert pass to reclaim space.

This PR adds a content-based backup path driven by libvirt pull mode and routes VMs on content-diff-capable storage (currently LINSTOR) to it:

nasbackup.sh – new content backup method

The script gets a --method option next to -M|--mode: qcow2 (default, the existing push-mode path with dirty bitmaps) or content. With --method content, libvirt is asked for a pull-mode backup: it starts an NBD server exposing a point-in-time view of each disk, held consistent by copy-before-write into host-local fleecing scratch images. The backup is then derived from that export:

  • full: qemu-img convert from the NBD export straight into a sparse qcow2 in a single pass. This replaces the bloated push-mode output and its re-convert pass.
  • incremental: a qcow2 overlay backed by the NBD export, then a safe qemu-img rebase onto the parent backup. This merges in exactly the clusters that differ and yields a delta qcow2 backed by the parent, with a relative backing path. The chain has the same shape as a bitmap incremental, so the existing restore and cascade-delete logic applies unchanged.

A missing or short parent list degrades to a full and emits INCREMENTAL_FALLBACK=true, mirroring the push-mode fallback. Also handles the raw /dev/drbdN device paths of long-running VMs the same way the push/stopped paths do (via get_linstor_uuid_from_device).

The scratch dir is host-local and configurable with -S (default /var/tmp). It must not be on the NAS share, since copy-before-write runs inline with guest writes. NBD socket paths are validated against the kernel's 108-byte UNIX socket limit up front instead of failing opaquely in qemu-img later.

If the scratch area fills up during a backup, copy-before-write fails the guest's writes and QEMU pauses the VM. Before starting, the script therefore checks that the scratch filesystem has free space for a share of the VM's total disk size, the worst case since each block is saved at most once (--scratch-min-free-percent, default 25, 0 disables the check). Otherwise the backup fails up front with a message naming the required and available space. Concurrent pull-mode backups sharing one scratch filesystem are not accounted for together.

A pull-mode job never ends on its own, so an EXIT/INT/TERM/HUP trap ends it (via abort_backup_job() from #14305), removes the scratch dir and cleans up on any failed exit. The freeze/thaw handling uses the helpers from #14305 as well.

NASBackupProvider – routing and cadence

  • New decideContentChain() mirrors the bitmap cadence logic (stopped VMs, nas.backup.full.every, chain length) but anchors on backup history alone. There is no host-side bitmap that can be invalidated, so a VM restart, live migration or restore cannot break the chain; content comparison is stateless and self-correcting.
  • The master switch nas.backup.incremental.enabled applies first: with incrementals disabled every VM, LINSTOR included, keeps the legacy push-mode full backup. Enabling incrementals is the opt-in to the content-based path.
  • ChainDecision separates the two concerns: mode is full or incremental, a new method field is qcow2 or content. Further methods (e.g. an RBD diff) can be added without new mode tokens.
  • ChainDecision carries the parent backup uuid directly, since a content chain has no bitmap name to resolve the parent by.
  • Mixed-storage VMs (e.g. root on LINSTOR, data disk on NFS) stay off the content path: one backup run uses one mode.

LibvirtTakeBackupCommandWrapper / agent

TakeBackupCommand carries the new method field, passed to the script as --method. When absent the agent assumes qcow2, so a management server that does not send it keeps working. A content incremental requires only its per-disk parent paths, no bitmap. New agent.properties keys:

  • nas.backup.pull.scratch.dir (default /var/tmp): host-local scratch area.
  • nas.backup.pull.scratch.min.free.percent (default 25): free space the scratch area needs before a pull-mode backup starts, as a percentage of the VM's total disk size.

The agent kills a timed-out script with SIGKILL, which no trap can catch, so after a pull-mode timeout the wrapper aborts the backup job itself.

Restore onto LINSTOR: do not skip zero regions (bug fix, independent of the above)

replaceBlockDeviceWithBackup ran qemu-img convert with --target-is-zero whenever the target device existed, skipping every zero/unallocated qcow2 cluster of the backup. On an in-place restore those clusters kept the volume's current data, and a new LINSTOR volume on thick LVM is not zeroed either. A new KVMStoragePool.newVolumeReadsAsZero() hook (false by default, LinstorStoragePool answers it with LinstorUtil.resourceSupportZeroBlocks()) now limits zero skipping to freshly created volumes on thin or ZFS backed pools. RBD targets were never affected.

Behaviour for VMs on qcow2/NFS/Ceph storage is unchanged; they keep using the bitmap path from #13877.

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

How Has This Been Tested?

Unit tests

Six new NASBackupProviderTest cases cover the routing and cadence decisions:

  • decideChainReturnsLegacyFullForLinstorWhenIncrementalDisabled
  • decideChainReturnsContentFullForStoppedLinstorVm
  • decideChainReturnsContentIncrementalForLinstorWithValidParent
  • decideChainReturnsContentFullForLinstorAtChainEnd
  • allVolumesOnContentDiffCapableStorageFalseForMixedStorage
  • allVolumesOnContentDiffCapableStorageFalseForNoVolumes

LibvirtTakeBackupCommandWrapperTest covers the --method / scratch arguments, the method validation and the job abort after a pull-mode timeout. LibvirtRestoreBackupCommandWrapperTest covers zero skipping for in-place, new thick and new thin LINSTOR restores.

All NASBackupProviderTest (29), LibvirtTakeBackupCommandWrapperTest (10) and LibvirtRestoreBackupCommandWrapperTest (23) cases pass, as do the full core, KVM plugin and NAS plugin suites, after rebasing onto current 4.22.

End-to-end on a 3-host KVM/LINSTOR cluster, run on the initial revision, before the review changes above (EXIT trap, method field, scratch space check, legacy full while incrementals are off, restore fix); not yet repeated on the current one (management server + 3 agents, NFS backup repository, nas.backup.incremental.enabled=true, nas.backup.full.every=3):

# Test case Expected Result
1 Full backup of a running LINSTOR VM single sparse qcow2 per disk, no bitmap/checkpoint, restore works Pass
2 Four consecutive backups of a running LINSTOR VM with full.every=3 FULL / INCREMENTAL / INCREMENTAL / FULL recorded in DB Pass
3 Backup size 8 GiB volume: ~1.9 GiB sparse full; deltas of a few MiB after small guest writes Pass
4 Chain layout Incrementals have a relative backing path to the parent; 3-level chain clean under qemu-img check Pass
5 Restore from the tail incremental VM boots and answers on the network Pass
6 VM on qcow2/NFS storage Still takes the bitmap path from #13877, no behaviour change Pass

How did you try to break this feature and the system with this change?

  • Long scratch path: pointed nas.backup.pull.scratch.dir at a deep directory so the NBD socket path exceeded 108 bytes. The script fails up front with a clear message and a hint to shorten the dir, instead of an opaque qemu-img connection error mid-backup; cleanup runs and no partial backup dir is left behind.
  • Scratch on the NAS share: verified guest writes stall during the backup when copy-before-write goes to the remote share. This is why the scratch dir is host-local by default and documented as such.
  • Missing parent: deleted the parent backup files and requested an incremental. The script falls back to a full, signals INCREMENTAL_FALLBACK=true, and the DB records a full.
  • VM restart / live migration between backups: since no host-side bitmap exists, the next backup is still incremental and the delta is correct. This is the case where the bitmap chain has to restart.
  • Mixed storage: VM with a LINSTOR root disk and an NFS data disk stays on the legacy full-only path; no half-content, half-bitmap chain is produced.
  • Failure mid-loop (killed qemu-img during the pull): the backup job is aborted, scratch dir and partial output removed, mount released; the next backup succeeds.
  • Legacy DRBD device paths (/dev/drbdN instead of /dev/drbd/by-res/… in live XML): resolved via udev like the push path; if the UUID cannot be derived the backup fails hard rather than producing a file restore cannot find.

@rp- rp- added this to the 4.22.2 milestone Sep 17, 2026
@rp-
rp- requested a review from abh1sar September 17, 2026 14:21
@rp- rp- self-assigned this Sep 17, 2026
@rp-
rp- requested a review from sureshanaparti September 17, 2026 14:22
@rp- rp- changed the title Linstor 4.22 nasbackup incremental Linstor add support for incremental nasbackup Sep 17, 2026
@codecov

codecov Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.33333% with 38 lines in your changes missing coverage. Please review.
✅ Project coverage is 18.04%. Comparing base (dfff32e) to head (1d9b64c).

Files with missing lines Patch % Lines
...rg/apache/cloudstack/backup/NASBackupProvider.java 65.62% 17 Missing and 5 partials ⚠️
...ource/wrapper/LibvirtTakeBackupCommandWrapper.java 82.85% 2 Missing and 4 partials ⚠️
...rg/apache/cloudstack/backup/TakeBackupCommand.java 50.00% 3 Missing ⚠️
...m/cloud/hypervisor/kvm/storage/KVMStoragePool.java 0.00% 3 Missing ⚠️
...oud/hypervisor/kvm/storage/LinstorStoragePool.java 0.00% 3 Missing ⚠️
...ce/wrapper/LibvirtRestoreBackupCommandWrapper.java 83.33% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               4.22   #14194      +/-   ##
============================================
+ Coverage     18.01%   18.04%   +0.02%     
- Complexity    16265    16298      +33     
============================================
  Files          5936     5936              
  Lines        536395   536506     +111     
  Branches      65701    65726      +25     
============================================
+ Hits          96658    96811     +153     
+ Misses       428710   428656      -54     
- Partials      11027    11039      +12     
Flag Coverage Δ
uitests 4.04% <ø> (ø)
unittests 19.12% <68.33%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sureshanaparti

Copy link
Copy Markdown
Contributor

@rp- are the changes here relavant for 4.22 branch? if so, please re-target to 4.22.

@rp-
rp- changed the base branch from main to 4.22 September 17, 2026 20:15
@rp-

rp- commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

@rp- are the changes here relavant for 4.22 branch? if so, please re-target to 4.22.

thanks, missed the wrong base branch

@rp-

rp- commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

@blueorangutan package

@blueorangutan

Copy link
Copy Markdown

@rp- a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan

Copy link
Copy Markdown

Packaging result [SF]: ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 19402

@weizhouapache

Copy link
Copy Markdown
Member

@blueorangutan package

@blueorangutan

Copy link
Copy Markdown

@weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan

Copy link
Copy Markdown

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 19405

@weizhouapache

Copy link
Copy Markdown
Member

@blueorangutan test

@blueorangutan

Copy link
Copy Markdown

@weizhouapache a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@rp-
rp- requested a review from weizhouapache October 5, 2026 11:58
@rp-

rp- commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Also pinging for this here @sureshanaparti to be included in 4.22.2

@blueorangutan

Copy link
Copy Markdown

[SF] Trillian test result (tid-17075)
Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
Total time taken: 53992 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr14194-t17075-kvm-ol8.zip
Smoke tests completed. 149 look OK, 0 have errors, 0 did not run
Only failed and skipped tests results shown below:

Test Result Time (s) Test File

@weizhouapache weizhouapache left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

code lgtm

@github-actions

Copy link
Copy Markdown

This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch.

1 similar comment
@github-actions

Copy link
Copy Markdown

This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch.

@abh1sar abh1sar 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.

I found one issue not in this PR, but related to Linstor NAS backup support.
replaceBlockDeviceWithBackup calls QemuImg with skipZeroIfSupported=true.
This means restore assumes that the target disk is zeroes and doesn't copy zeroed blocks. This doesn't work for in-place restore. In that case every zero region of the backup is skipped and the volume keeps whatever was there.

if backup_out=$(virsh -c qemu:///system backup-begin --domain "$VM" --backupxml "$backupxml" 2>&1); then
backup_begin=1
fi

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.

The backup job will be left forever running if there is an interrupt or error before calling domjobabort.
Consider adding a trap and cleanup.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

should be handled now with 2171023

* does anchor a chain so later content-incrementals can hang off it.
*/
static ChainDecision contentFull() {
return new ChainDecision(NASBackupChainKeys.TYPE_CONTENT_FULL, null, null, null,

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.

Instead of overloading the mode for each ChainDecision, I suggest adding a new method field to it.
The method can be qcow2 / content / none / rbd_diff(ceph - can be added later).
The mode will still say full and incremental for each method.

#14386 also adds rbd-full and rbd-incremental. I think a new method will be a better choice for both PRs.

cc @weizhouapache

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in c144d09

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nice @rp-

I will see if I can use method in my PR for RBD volumes #14386, for example method=rbd

*
* @since 4.22.0
*/
public static final Property<String> NAS_BACKUP_PULL_SCRATCH_DIR = new Property<>("nas.backup.pull.scratch.dir", "/var/tmp");

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.

If the scratch dir gets full, the VM writes are stalled and it is paused. If I am not wrong, the VM is never resumed.
Consider either creating the scratch dir as a new volume on the Linstor pool itself / do a space check before starting backup / test the pause and resume workflow.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes this is the real problem with the pull mode, I added a disk space check and also by default now use the old push mode (with its drawbacks), but now it is an opt-in and admins have to make sure they have enough space or configure a correct scratch dir.

# room for the write churn during the backup. 711 lets the qemu process traverse in to
# the files libvirt creates as root.
local scratch_dir
scratch_dir=$(mktemp -d "$SCRATCH_PARENT/csbackup-scratch.XXXXXX") || {

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.

what happens to the running vm if /var/tmp fills up during a long backup of a busy disk? does the backup just fail or can the vm writes start failing too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

the check before start helps, but with the default 25 a busy vm that rewrites more than a quarter of its disk still gets paused and stays paused. can we stop the backup and resume the vm when the scratch area runs low?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well its a setting and should be set to the users usage scenarios, even 50% can be too much if you think of a VM with a really large data disk like 20TB which maybe doesn't do much writes, but still you would need then a scratch space of 10TB...

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.

fair, with pull mode opt-in and the size up to the admin thats fine

// Those VMs take the content-based pull-mode path instead. It is chosen regardless of the
// master switch, because even a full backup benefits: pull mode writes a sparse qcow2 in a
// single pass rather than a fully allocated one needing a second re-convert pass.
if (allVolumesOnContentDiffCapableStorage(vm)) {

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.

should linstor vms stay on the old full backup when incremental is turned off? right now they switch to the new method after upgrade even if the admin never opted in

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes it is probably the safer bet to keep the push mode by default and let people opt in to the pull mode (then they should also be aware to configure a proper scratch dir

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.

makes sense, checking the incremental setting first in 3c1820b covers it

rp- added 7 commits October 13, 2026 14:54
Raw block-device disks such as LINSTOR/DRBD cannot carry QEMU persistent dirty
bitmaps -- persistence is a qcow2-only feature -- so libvirt checkpoints, and
with them the push-mode incremental path, are unavailable there. Those VMs were
therefore pinned to full-only backups, and push mode additionally wrote a fully
allocated qcow2 that needed a second re-convert pass to reclaim space.

Add a content-based path driven by libvirt pull mode. libvirt exposes a
point-in-time NBD view of each disk, held consistent by copy-before-write into
local fleecing scratch images, and the backup is derived from that export:

  content-full         qemu-img convert -> sparse qcow2 in a single pass, so the
                       bloated push output and its re-convert pass both go away.
  content-incremental  a qcow2 overlay backed by the NBD export, then a safe
                       rebase onto the parent, merging in exactly the clusters
                       that differ -> a delta qcow2 backed by the parent.

The delta has the same chain shape the push-mode incremental produces (relative
backing path), so the existing restore and cascade-delete logic applies
unchanged. A missing or short parent list degrades to a full and emits
INCREMENTAL_FALLBACK=true, mirroring the push-mode fallback.

Unlike a storage-snapshot based diff there is no trailing DRBD metadata to clip:
the DRBD device, and therefore the NBD export, is already net-sized.

The scratch dir is host-local and configurable with -S, defaulting to /var/tmp;
it must not sit on the NAS share since copy-before-write runs inline with guest
writes. NBD socket paths are validated against the kernel's 108-byte limit up
front to avoid an opaque qemu-img failure later.
The incremental NAS backup feature gates on QEMU dirty bitmaps, which can only be
persisted inside a qcow2. LINSTOR volumes are raw DRBD block devices, so
allVolumesOnCheckpointCapableStorage() rejected them and every LINSTOR VM was
pinned to full-only backups regardless of the configured cadence.

Route those VMs to the content-based path instead, which derives the delta by
comparing the disk's point-in-time NBD export against the parent backup rather
than by tracking dirty blocks:

- decideContentChain() mirrors the bitmap cadence logic (master switch, stopped
  VMs, nas.backup.full.every, chain length) but anchors on backup history alone.
  There is no host-side bitmap to invalidate, so unlike the bitmap chain a VM
  restart, live migration or restore cannot break it -- content comparison is
  stateless and self-correcting.
- The path is taken even when the incremental master switch is off, because a
  content-full is still a single-pass sparse write, strictly better than the
  fully allocated push-mode output it replaces.
- ChainDecision carries the parent backup uuid directly, since a content chain
  has no bitmap name to resolve the parent by.
- Mixed-storage VMs stay off the content path: one backup run uses one mode.

The agent wrapper accepts the two new modes -- content-incremental requires only
its per-disk parent paths, no bitmap -- and passes the host-local pull-mode
scratch directory from the new nas.backup.pull.scratch.dir agent property.

Adds 6 unit tests covering the routing and cadence decisions. All 21 pre-existing
NASBackupProviderTest cases and the KVM wrapper tests still pass.
A pull-mode backup job never finishes on its own; nasbackup.sh ends it with
domjobabort once the data is read. Any exit the script did not plan for -- an
unexpected error under "set -e", SIGINT/SIGTERM/SIGHUP -- left the job running,
keeping the NBD server and the growing fleecing images alive and blocking every
later backup or migration of the VM.

Arm an EXIT trap once the scratch dir exists: it aborts the job (through
apache#14305's BACKUP_JOB_ACTIVE/abort_backup_job), removes the scratch dir and runs
cleanup(). This replaces the per-error-path abort/cleanup copies.

The agent kills a timed-out script with SIGKILL, which no trap can catch, so
LibvirtTakeBackupCommandWrapper aborts the job itself after a pull-mode timeout.
The content-based path overloaded ChainDecision.mode with content-full and
content-incremental, and apache#14386 is adding rbd-full and rbd-incremental the same
way. Split the two concerns as suggested in review: mode stays full or
incremental, and a new method field says how the backup is taken -- qcow2 (push
mode with dirty bitmaps) or content (pull mode). Further methods such as an RBD
diff can be added without new mode tokens.

TakeBackupCommand gets a method field and nasbackup.sh a --method option. Both
default to qcow2 when absent, so a management server that does not send a method
keeps working against an upgraded agent. legacy-full is unchanged: rewriting it
as full plus a "none" method would break incremental-disabled backups on agents
that have not been upgraded yet.
Copy-before-write saves every guest block that is overwritten during a
pull-mode backup into the host-local scratch area. If that fills up, the guest's
writes fail, QEMU pauses the VM (the default werror=enospc policy) and nothing
resumes it.

Each block is saved at most once, so the VM's total disk size is the worst case.
Refuse to start the backup unless the scratch area has the share of that set by
the new agent.properties option nas.backup.pull.scratch.min.free.percent. The
default of 25 assumes the guest overwrites at most a quarter of its disks while
a backup runs; 100 rules out a full scratch area, 0 disables the check. The
check does not account for concurrent pull-mode backups sharing the same
scratch filesystem.
… off

LINSTOR VMs took the content-based pull-mode path even with
nas.backup.incremental.enabled off, so an upgrade switched existing users to
the new mechanism, with its host-local scratch space requirement, without them
opting in.

Apply the master switch before the storage routing: with incrementals disabled
every VM, LINSTOR included, gets the legacy push-mode full as before. Enabling
incrementals is the opt-in to the content-based path.
replaceBlockDeviceWithBackup created its QemuImg with skipZeroIfSupported, so
for an existing target device qemu-img convert ran with --target-is-zero and
skipped every zero region of the backup -- at qcow2 cluster granularity, not
the -S 1M chunk size. On an in-place restore the volume keeps its old data
there, silently corrupting the restored disk. A newly created LINSTOR volume is
only safe on thin or ZFS backed pools; thick LVM hands out stale data too.

Add KVMStoragePool.newVolumeReadsAsZero(), false by default; LinstorStoragePool
answers it with LinstorUtil.resourceSupportZeroBlocks(), the check
LinstorStorageAdaptor.copyPhysicalDisk already uses. The restore now skips zero
regions only on a volume it just created and the pool reports as zeroed, and
requests -n explicitly for an existing target, which it previously got only
through the zero-skipping branch. RBD targets are unaffected: --target-is-zero
never applied to them.

@Damans227 Damans227 left a comment

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.

thanks @rp-, fixes look right. LGTM

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants