On Mon, Feb 23, 2026 at 19:52:22 -0300, Lucas Amaral wrote:
> Previously, users had to manually specify a TCP port when starting
> a pull-mode backup with an NBD server. A TODO comment in
> qemuBackupPrepare() noted this limitation and pointed toward using
> virPortAllocator, as done for migration, VNC, and SPICE ports.
> 
> Add backup_port_min and backup_port_max configuration options to
> qemu.conf, defaulting to 10809-10872 (10809 is the IANA-assigned
> NBD port; range of 64 matches the migration port pattern).
> 
> When a pull-mode backup is started without specifying a TCP port,
> a port is now acquired automatically from the configured range via
> virPortAllocatorAcquire(). The port is released when the backup
> ends or if startup fails.
> 
> Signed-off-by: Lucas Amaral <[email protected]>
> ---

[...]


>  docs/formatbackup.rst              |  3 ++-
>  src/qemu/libvirtd_qemu.aug         |  2 ++
>  src/qemu/qemu.conf.in              |  9 ++++++++
>  src/qemu/qemu_backup.c             | 33 +++++++++++++++++++++---------
>  src/qemu/qemu_conf.c               | 25 ++++++++++++++++++++++
>  src/qemu/qemu_conf.h               |  6 ++++++
>  src/qemu/qemu_domain.h             |  1 +
>  src/qemu/qemu_driver.c             |  6 ++++++
>  src/qemu/test_libvirtd_qemu.aug.in |  2 ++
>  9 files changed, 76 insertions(+), 11 deletions(-)

Sorry for the delay in reviewing this patch.

The code looks good, but normally we'd request splitting of the
'qemu.conf' related changes into a separate patch.

In this case I'll do the split (obviously preserving authorship) before
pushing so that you don't need to follow up with another version.

> diff --git a/docs/formatbackup.rst b/docs/formatbackup.rst
> index df6392e3bd..24857eaf72 100644
> --- a/docs/formatbackup.rst
> +++ b/docs/formatbackup.rst
> @@ -42,7 +42,8 @@ were supplied). The following child elements and attributes 
> are supported:
>     ```protocol`` element of a disk 
> <formatdomain.html#hard-drives-floppy-disks-cdroms>`__ attached
>     via NBD in the domain (such as transport, socket, name, port, or tls),
>     necessary to set up an NBD server that exposes the content of each disk at
> -   the time the backup is started.
> +   the time the backup is started. For TCP transport, if ``port`` is 
> omitted, a
> +   port is allocated automatically from the range configured in 
> ``/etc/libvirt/qemu.conf``.
>  
>     In addition to the above the NBD server used for backups allows using
>     ``transport='fd' fdgroup='NAME'`` where ``NAME`` is the name used with
> diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
> index 0286582169..eb790d48be 100644
> --- a/src/qemu/libvirtd_qemu.aug
> +++ b/src/qemu/libvirtd_qemu.aug
> @@ -146,6 +146,8 @@ module Libvirtd_qemu =
>                   | int_entry "migration_port_min"
>                   | int_entry "migration_port_max"
>                   | str_entry "migration_host"
> +                 | int_entry "backup_port_min"
> +                 | int_entry "backup_port_max"
>  
>     let log_entry = bool_entry "log_timestamp"
>  
> diff --git a/src/qemu/qemu.conf.in b/src/qemu/qemu.conf.in
> index 2d1c67034d..5eacd70022 100644
> --- a/src/qemu/qemu.conf.in
> +++ b/src/qemu/qemu.conf.in
> @@ -969,6 +969,15 @@
>  #migration_port_max = 49215
>  
>  
> +# Port range used for automatic allocation of NBD backup server ports.
> +# When a pull-mode backup is started without specifying a TCP port, a
> +# port from this range will be assigned automatically. The NBD standard
> +# port is 10809.
> +#
> +#backup_port_min = 10809
> +#backup_port_max = 10872
> +
> +
>  # Timestamp QEMU's log messages (if QEMU supports it)
>  #
>  # Defaults to 1.
> diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c
> index 44514d08fc..12ef64b14e 100644
> --- a/src/qemu/qemu_backup.c
> +++ b/src/qemu/qemu_backup.c
> @@ -32,6 +32,7 @@
>  #include "storage_source.h"
>  #include "storage_source_conf.h"
>  #include "virerror.h"
> +#include "virportallocator.h"
>  #include "virlog.h"
>  #include "virbuffer.h"
>  #include "backup_conf.h"
> @@ -71,16 +72,7 @@ qemuBackupPrepare(virDomainBackupDef *def)
>  
>          switch (def->server->transport) {
>          case VIR_STORAGE_NET_HOST_TRANS_TCP:
> -            /* TODO: Update qemu.conf to provide a port range,
> -             * probably starting at 10809, for obtaining automatic
> -             * port via virPortAllocatorAcquire, as well as store
> -             * somewhere if we need to call virPortAllocatorRelease
> -             * during BackupEnd. Until then, user must provide port */
> -            if (!def->server->port) {
> -                virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
> -                               _("<domainbackup> must specify TCP port for 
> now"));
> -                return -1;
> -            }
> +            /* port is auto-allocated if not set */
>              break;
>  
>          case VIR_STORAGE_NET_HOST_TRANS_UNIX:
> @@ -841,6 +833,16 @@ qemuBackupBegin(virDomainObj *vm,
>      if (qemuBackupPrepare(def) < 0)
>          goto endjob;
>  
> +    if (pull && def->server &&
> +        def->server->transport == VIR_STORAGE_NET_HOST_TRANS_TCP &&
> +        !def->server->port) {
> +        unsigned short port = 0;
> +        if (virPortAllocatorAcquire(priv->driver->backupPorts, &port) < 0)
> +            goto endjob;
> +        def->server->port = port;
> +        priv->backupNBDPort = port;
> +    }

This code belongs to BackupPrepare instead of the comment.

> +
>      if (qemuBackupBeginPrepareTLS(vm, cfg, def, &tlsProps, &tlsSecretProps) 
> < 0)
>          goto endjob;
>  
> @@ -969,6 +971,11 @@ qemuBackupBegin(virDomainObj *vm,
>          qemuDomainObjExitMonitor(vm);
>      }
>  
> +    if (ret < 0 && priv->backupNBDPort) {
> +        virPortAllocatorRelease(priv->backupNBDPort);
> +        priv->backupNBDPort = 0;
> +    }
> +
>      if (ret < 0 && !job_started && priv->backup)
>          def = g_steal_pointer(&priv->backup);
>  
> @@ -1026,6 +1033,12 @@ qemuBackupNotifyBlockjobEndStopNBD(virDomainObj *vm,
>      qemuDomainObjExitMonitor(vm);
>  
>      backup->nbdStopped = true;
> +
> +    if (priv->backupNBDPort) {
> +        virPortAllocatorRelease(priv->backupNBDPort);
> +        priv->backupNBDPort = 0;
> +        backup->server->port = 0;
> +    }
>  }
>  
>  
> diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
> index de6e51177a..99e6a29148 100644
> --- a/src/qemu/qemu_conf.c
> +++ b/src/qemu/qemu_conf.c
> @@ -74,6 +74,9 @@ VIR_LOG_INIT("qemu.qemu_conf");
>  #define QEMU_MIGRATION_PORT_MIN 49152
>  #define QEMU_MIGRATION_PORT_MAX 49215
>  
> +#define QEMU_BACKUP_PORT_MIN 10809
> +#define QEMU_BACKUP_PORT_MAX 10872
> +
>  VIR_ENUM_IMPL(virQEMUSchedCore,
>                QEMU_SCHED_CORE_LAST,
>                "none",
> @@ -265,6 +268,9 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool 
> privileged,
>      cfg->migrationPortMin = QEMU_MIGRATION_PORT_MIN;
>      cfg->migrationPortMax = QEMU_MIGRATION_PORT_MAX;
>  
> +    cfg->backupPortMin = QEMU_BACKUP_PORT_MIN;
> +    cfg->backupPortMax = QEMU_BACKUP_PORT_MAX;
> +
>      /* For privileged driver, try and find hugetlbfs mounts automatically.
>       * Non-privileged driver requires admin to create a dir for the
>       * user, chown it, and then let user configure it manually. */
> @@ -985,6 +991,25 @@ virQEMUDriverConfigLoadNetworkEntry(virQEMUDriverConfig 
> *cfg,
>          return -1;
>      }
>  
> +    if (virConfGetValueUInt(conf, "backup_port_min", &cfg->backupPortMin) < 
> 0)
> +        return -1;
> +    if (cfg->backupPortMin <= 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("%1$s: backup_port_min: port must be greater than 
> 0"),
> +                        filename);
> +        return -1;
> +    }
> +
> +    if (virConfGetValueUInt(conf, "backup_port_max", &cfg->backupPortMax) < 
> 0)
> +        return -1;
> +    if (cfg->backupPortMax > 65535 ||
> +        cfg->backupPortMax < cfg->backupPortMin) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                        _("%1$s: backup_port_max: port must be between the 
> minimal port %2$d and 65535"),
> +                       filename, cfg->backupPortMin);

Pre existing problem (in other port ranges) that I'll fix in a follow-up.
VIR_ERR_INTERNAL_ERROR is not appropriate error code for user
mis-configuration.

> +        return -1;
> +    }
> +
>      if (virConfGetValueString(conf, "migration_host", &cfg->migrateHost) < 0)
>          return -1;
>      virStringStripIPv6Brackets(cfg->migrateHost);

Reviewed-by: Peter Krempa <[email protected]>

Reply via email to