[PATCH 0/4] qemu: backup: Add support for FD passing for output images and sparsifying of full backup output
Peter Krempa (4): schemas: Introduce 'fdgroup' type and refactor uses qemu: don't create files for fd-passed new images backup: Allow FD-passing for backup output/scratch file backup: Add support for sparsifying output images of full backups docs/formatbackup.rst | 5 +++++ src/conf/backup_conf.c | 18 +++++++++++++++++- src/conf/backup_conf.h | 2 ++ src/conf/schemas/domainbackup.rng | 14 +++++++++++++- src/conf/schemas/domaincommon.rng | 18 ++++++++++++------ src/qemu/qemu_backup.c | 6 ++++++ src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_snapshot.c | 2 +- .../domainbackupxml2xmlin/backup-pull-fd.xml | 4 ++-- .../backup-push-sparsify.xml | 12 ++++++++++++ .../domainbackupxml2xmlout/backup-pull-fd.xml | 4 ++-- .../backup-push-sparsify.xml | 19 +++++++++++++++++++ tests/genericxml2xmltest.c | 1 + 13 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 tests/domainbackupxml2xmlin/backup-push-sparsify.xml create mode 100644 tests/domainbackupxml2xmlout/backup-push-sparsify.xml -- 2.56.0
From: Peter Krempa <pkrempa@redhat.com> Add a common definition of the 'fdgroup' type used for named FDs passed to a VM. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/schemas/domainbackup.rng | 2 +- src/conf/schemas/domaincommon.rng | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/conf/schemas/domainbackup.rng b/src/conf/schemas/domainbackup.rng index 91cf2a7bbd..7140dd7516 100644 --- a/src/conf/schemas/domainbackup.rng +++ b/src/conf/schemas/domainbackup.rng @@ -94,7 +94,7 @@ <attribute name="transport"> <value>fd</value> </attribute> - <attribute name="fdgroup"/> + <ref name="fdgroupattr"/> </group> </choice> </element> diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index d1b10c1c5f..9a74e101a9 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -249,6 +249,16 @@ </choice> </define> + <define name="fdgroupattr"> + <attribute name="fdgroup"/> + </define> + + <define name="fdgroup"> + <optional> + <ref name="fdgroupattr"/> + </optional> + </define> + <define name="osxen"> <choice> <group> @@ -1419,9 +1429,7 @@ <attribute name="enabled"> <ref name="virYesNo"/> </attribute> - <optional> - <attribute name="fdgroup"/> - </optional> + <ref name='fdgroup'/> </element> </define> @@ -2006,9 +2014,7 @@ <ref name="vmwarePath"/> </choice> </attribute> - <optional> - <attribute name="fdgroup"/> - </optional> + <ref name="fdgroup"/> </optional> <ref name="diskSourceCommon"/> <optional> -- 2.56.0
From: Peter Krempa <pkrempa@redhat.com> Code paths which create a file, such as snapshots or backups technically make use of FD-passed new images, but would still attempt to create the file based on the path, which is not desired as the path may not exist in the environment. Skip the creation when FD passing is in use. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_backup.c | 1 + src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_snapshot.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index a0544c83dc..b4e5b7347f 100644 --- a/src/qemu/qemu_backup.c +++ b/src/qemu/qemu_backup.c @@ -451,6 +451,7 @@ qemuBackupDiskPrepareOneStorage(virDomainObj *vm, if (!reuse_external && dd->store->type == VIR_STORAGE_TYPE_FILE && + !virStorageSourceIsFD(dd->store) && virStorageSourceSupportsCreate(dd->store)) { if (virFileExists(dd->store->path)) { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5922065897..fa5b589c29 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -14904,7 +14904,7 @@ qemuDomainBlockCopyCommon(virDomainObj *vm, /* pre-create the image file. This is required so that libvirt can properly * label the image for access by qemu */ - if (!existing) { + if (!existing && !virStorageSourceIsFD(mirror)) { if (supports_create) { if (virStorageSourceCreate(mirror) < 0) { virReportSystemError(errno, "%s", _("failed to create copy target")); diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 07548ca62e..f3d5b066f3 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -1351,7 +1351,7 @@ qemuSnapshotDiskPrepareOne(qemuSnapshotDiskContext *snapctxt, dd->initialized = true; - if (!reuse) { + if (!reuse && !virStorageSourceIsFD(dd->src)) { /* pre-create the image file so that we can label it before handing it to qemu */ if (dd->src->type != VIR_STORAGE_TYPE_BLOCK) { if (virStorageSourceCreate(dd->src) < 0) { -- 2.56.0
From: Peter Krempa <pkrempa@redhat.com> Allow clients to pass in FD for the scratch or output file of the backup. All code is in place now, it just needs to be allowed in the schema. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/schemas/domainbackup.rng | 2 ++ tests/domainbackupxml2xmlin/backup-pull-fd.xml | 4 ++-- tests/domainbackupxml2xmlout/backup-pull-fd.xml | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/conf/schemas/domainbackup.rng b/src/conf/schemas/domainbackup.rng index 7140dd7516..745a91c33c 100644 --- a/src/conf/schemas/domainbackup.rng +++ b/src/conf/schemas/domainbackup.rng @@ -187,6 +187,7 @@ <attribute name="file"> <ref name="absFilePath"/> </attribute> + <ref name="fdgroup"/> <interleave> <zeroOrMore> <ref name="devSeclabel"/> @@ -269,6 +270,7 @@ <attribute name="file"> <ref name="absFilePath"/> </attribute> + <ref name="fdgroup"/> <interleave> <zeroOrMore> <ref name="devSeclabel"/> diff --git a/tests/domainbackupxml2xmlin/backup-pull-fd.xml b/tests/domainbackupxml2xmlin/backup-pull-fd.xml index 02ae20d665..1a9765d988 100644 --- a/tests/domainbackupxml2xmlin/backup-pull-fd.xml +++ b/tests/domainbackupxml2xmlin/backup-pull-fd.xml @@ -3,11 +3,11 @@ <server transport='fd' fdgroup='nbdfd'/> <disks> <disk name='vda' type='file'> - <scratch file='/path/to/file'/> + <scratch file='/path/to/file' fdgroup='scratchfd-vda'/> </disk> <disk name='hda' backup='no'/> <disk name='vdc' type='file' backupmode='full'> - <scratch file='/path/to/file'/> + <scratch file='/path/to/file' fdgroup='scratchfd-vdc'/> </disk> <disk name='vdd' type='file' backupmode='incremental'> <scratch file='/path/to/file'/> diff --git a/tests/domainbackupxml2xmlout/backup-pull-fd.xml b/tests/domainbackupxml2xmlout/backup-pull-fd.xml index 16b9b0be50..348fc21134 100644 --- a/tests/domainbackupxml2xmlout/backup-pull-fd.xml +++ b/tests/domainbackupxml2xmlout/backup-pull-fd.xml @@ -3,11 +3,11 @@ <server transport='fd' fdgroup='nbdfd'/> <disks> <disk name='vda' backup='yes' type='file' backupmode='incremental' incremental='1525889631'> - <scratch file='/path/to/file'/> + <scratch file='/path/to/file' fdgroup='scratchfd-vda'/> </disk> <disk name='hda' backup='no'/> <disk name='vdc' backup='yes' type='file' backupmode='full'> - <scratch file='/path/to/file'/> + <scratch file='/path/to/file' fdgroup='scratchfd-vdc'/> </disk> <disk name='vdd' backup='yes' type='file' backupmode='incremental' incremental='1525889631'> <scratch file='/path/to/file'/> -- 2.56.0
From: Peter Krempa <pkrempa@redhat.com> When taking a full backup of a VM which has potentially fully-allocated zero blocks the output image will not be sparse. Add an option to sparsify full backups so that they potentially skip large blocks of NUL blocks. For incremental backup images this is obviously not possible as any NUL blocks were actually zeroed-out by the VM so they need to be written as-is. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/formatbackup.rst | 5 +++++ src/conf/backup_conf.c | 18 +++++++++++++++++- src/conf/backup_conf.h | 2 ++ src/conf/schemas/domainbackup.rng | 10 ++++++++++ src/qemu/qemu_backup.c | 5 +++++ .../backup-push-sparsify.xml | 12 ++++++++++++ .../backup-push-sparsify.xml | 19 +++++++++++++++++++ tests/genericxml2xmltest.c | 1 + 8 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 tests/domainbackupxml2xmlin/backup-push-sparsify.xml create mode 100644 tests/domainbackupxml2xmlout/backup-push-sparsify.xml diff --git a/docs/formatbackup.rst b/docs/formatbackup.rst index 24857eaf72..db7ccf802b 100644 --- a/docs/formatbackup.rst +++ b/docs/formatbackup.rst @@ -115,6 +115,11 @@ were supplied). The following child elements and attributes are supported: for an incremental backup exported via NBD export name for the given disk. Valid only for pull mode backups. + ``sparsify`` + Valid only for ``full`` push mode backups. + Requests that any zero blocks are un-allocated in the backup file even + when they were allocated in the source. :since:`Since 12.9.0` + ``type`` A mandatory attribute to describe the type of the disk, except when ``backup='no'`` is used. Valid values include ``file``, or ``block``. diff --git a/src/conf/backup_conf.c b/src/conf/backup_conf.c index b20292af3d..87a5b64116 100644 --- a/src/conf/backup_conf.c +++ b/src/conf/backup_conf.c @@ -129,7 +129,11 @@ virDomainBackupDiskDefParseXML(xmlNodePtr node, if (def->backup == VIR_TRISTATE_BOOL_NO) return 0; - if (!push) { + if (push) { + if (virXMLPropTristateBool(node, "sparsify", VIR_XML_PROP_NONE, + &def->sparsify) < 0) + return -1; + } else { def->exportname = virXMLPropString(node, "exportname"); def->exportbitmap = virXMLPropString(node, "exportbitmap"); } @@ -325,6 +329,10 @@ virDomainBackupDiskDefFormat(virBuffer *buf, virBufferEscapeString(&attrBuf, " exportname='%s'", disk->exportname); virBufferEscapeString(&attrBuf, " exportbitmap='%s'", disk->exportbitmap); + if (disk->sparsify != VIR_TRISTATE_BOOL_ABSENT) + virBufferAsprintf(&attrBuf, " sparsify='%s'", + virTristateBoolTypeToString(disk->sparsify)); + if (disk->store->id != 0) virBufferAsprintf(&attrBuf, " index='%u'", disk->store->id); @@ -535,6 +543,14 @@ virDomainBackupAlignDisks(virDomainBackupDef *def, if (!backupdisk->incremental && backupdisk->backupmode == VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_INCREMENTAL) backupdisk->incremental = g_strdup(def->incremental); + + if (backupdisk->sparsify == VIR_TRISTATE_BOOL_YES && + backupdisk->backupmode == VIR_DOMAIN_BACKUP_DISK_BACKUP_MODE_INCREMENTAL) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("The 'sparsify' mode of disk '%1$s' can be used only for full backup"), + backupdisk->name); + return -1; + } } return 0; diff --git a/src/conf/backup_conf.h b/src/conf/backup_conf.h index f90a4dcaee..49417ca90d 100644 --- a/src/conf/backup_conf.h +++ b/src/conf/backup_conf.h @@ -65,6 +65,8 @@ struct _virDomainBackupDiskDef { char *exportname; /* name of the NBD export for pull mode backup */ char *exportbitmap; /* name of the bitmap exposed in NBD for pull mode backup */ + virTristateBool sparsify; /* sparsify full backup output file */ + /* details of target for push-mode, or of the scratch file for pull-mode */ virStorageSource *store; diff --git a/src/conf/schemas/domainbackup.rng b/src/conf/schemas/domainbackup.rng index 745a91c33c..7924420815 100644 --- a/src/conf/schemas/domainbackup.rng +++ b/src/conf/schemas/domainbackup.rng @@ -175,9 +175,19 @@ <!-- Allow to plainly select a disk for backup without any other config --> <group> <ref name="backupAttr"/> + <optional> + <attribute name="sparsify"> + <ref name="virYesNo"/> + </attribute> + </optional> </group> <group> <ref name="backupAttr"/> + <optional> + <attribute name="sparsify"> + <ref name="virYesNo"/> + </attribute> + </optional> <attribute name="type"> <value>file</value> </attribute> diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index b4e5b7347f..d46d488b03 100644 --- a/src/qemu/qemu_backup.c +++ b/src/qemu/qemu_backup.c @@ -315,6 +315,11 @@ qemuBackupDiskPrepareDataOne(virDomainObj *vm, dd->backingStore = dd->terminator = virStorageSourceNew(); } + if (backupdisk->sparsify == VIR_TRISTATE_BOOL_YES) { + backupdisk->store->detect_zeroes = VIR_DOMAIN_DISK_DETECT_ZEROES_UNMAP; + backupdisk->store->discard = VIR_DOMAIN_DISK_DISCARD_UNMAP; + } + if (qemuDomainPrepareStorageSourceBlockdev(NULL, dd->store, priv, cfg) < 0) return -1; diff --git a/tests/domainbackupxml2xmlin/backup-push-sparsify.xml b/tests/domainbackupxml2xmlin/backup-push-sparsify.xml new file mode 100644 index 0000000000..e8403da037 --- /dev/null +++ b/tests/domainbackupxml2xmlin/backup-push-sparsify.xml @@ -0,0 +1,12 @@ +<domainbackup mode="push"> + <disks> + <disk name='vda' type='file' sparsify='no'> + <driver type='raw'/> + <target file='/path/to/file'/> + </disk> + <disk name='vdb' type='file' backupmode='full' sparsify='yes'/> + <disk name='vdc'/> + <disk name='vdd' backup='yes' incremental='test'/> + <disk name='hda' backup='no'/> + </disks> +</domainbackup> diff --git a/tests/domainbackupxml2xmlout/backup-push-sparsify.xml b/tests/domainbackupxml2xmlout/backup-push-sparsify.xml new file mode 100644 index 0000000000..d402f8acd4 --- /dev/null +++ b/tests/domainbackupxml2xmlout/backup-push-sparsify.xml @@ -0,0 +1,19 @@ +<domainbackup mode='push'> + <disks> + <disk name='vda' backup='yes' type='file' backupmode='full' sparsify='no'> + <driver type='raw'/> + <target file='/path/to/file'/> + </disk> + <disk name='vdb' backup='yes' type='file' backupmode='full' sparsify='yes'> + <target file='/fake/vdb.qcow2.SUFFIX'/> + </disk> + <disk name='vdc' backup='yes' type='file' backupmode='full'> + <target file='/fake/vdc.qcow2.SUFFIX'/> + </disk> + <disk name='vdd' backup='yes' type='file' backupmode='incremental' incremental='test'> + <target file='/fake/vdd.qcow2.SUFFIX'/> + </disk> + <disk name='hda' backup='no'/> + <disk name='vdextradisk' backup='no'/> + </disks> +</domainbackup> diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c index 269de3501f..7a8074bbe5 100644 --- a/tests/genericxml2xmltest.c +++ b/tests/genericxml2xmltest.c @@ -267,6 +267,7 @@ mymain(void) DO_TEST_BACKUP("backup-push"); DO_TEST_BACKUP("backup-push-seclabel"); DO_TEST_BACKUP("backup-push-encrypted"); + DO_TEST_BACKUP("backup-push-sparsify"); DO_TEST_BACKUP_FULL("backup-pull-internal-invalid", true); -- 2.56.0
On a Monday in 2026, Peter Krempa via Devel wrote:
Peter Krempa (4): schemas: Introduce 'fdgroup' type and refactor uses qemu: don't create files for fd-passed new images backup: Allow FD-passing for backup output/scratch file backup: Add support for sparsifying output images of full backups
docs/formatbackup.rst | 5 +++++ src/conf/backup_conf.c | 18 +++++++++++++++++- src/conf/backup_conf.h | 2 ++ src/conf/schemas/domainbackup.rng | 14 +++++++++++++- src/conf/schemas/domaincommon.rng | 18 ++++++++++++------ src/qemu/qemu_backup.c | 6 ++++++ src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_snapshot.c | 2 +- .../domainbackupxml2xmlin/backup-pull-fd.xml | 4 ++-- .../backup-push-sparsify.xml | 12 ++++++++++++ .../domainbackupxml2xmlout/backup-pull-fd.xml | 4 ++-- .../backup-push-sparsify.xml | 19 +++++++++++++++++++ tests/genericxml2xmltest.c | 1 + 13 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 tests/domainbackupxml2xmlin/backup-push-sparsify.xml create mode 100644 tests/domainbackupxml2xmlout/backup-push-sparsify.xml
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
participants (2)
-
Ján Tomko -
Peter Krempa