From: Fiona Ebner Date: Tue, 19 Dec 2023 13:44:59 +0000 (+0100) Subject: fix #4501: TCP migration: start vm: move port reservation and usage closer together X-Git-Url: https://git.proxmox.com/?p=qemu-server.git;a=commitdiff_plain;h=498d7da470671dd05f569b2a9a8fd01ef544c055 fix #4501: TCP migration: start vm: move port reservation and usage closer together Currently, volume activation, PCI reservation and resetting systemd scope happen in between, so the 5 second expiretime used for port reservation is not always enough. It's possible to defer telling QEMU where it should listen for migration and do so after it has been started via QMP. Therefore, the port reservation can be moved very close to the actual usage. Mentioned here for completeness and can still be done as an additional change later if desired: next_migrate_port could be modified to optionally return the open socket and it should be possible to pass the file descriptor directly to QEMU, but that would require accepting the connection before on the Perl side (otherwise leads to ENOTCONN 107). While it would avoid any races, it's not the most elegant and the change at hand should be enough in all practical situations. Signed-off-by: Fiona Ebner Acked-by: Thomas Lamprecht Tested-by: Hannes Duerr --- diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 2063e66..3b1540b 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -5804,10 +5804,9 @@ sub vm_start_nolock { $migrate->{addr} = "[$migrate->{addr}]" if Net::IP::ip_is_ipv6($migrate->{addr}); } - my $pfamily = PVE::Tools::get_host_address_family($nodename); - $migrate->{port} = PVE::Tools::next_migrate_port($pfamily); - $migrate->{uri} = "tcp:$migrate->{addr}:$migrate->{port}"; - push @$cmd, '-incoming', $migrate->{uri}; + # see #4501: port reservation should be done close to usage - tell QEMU where to listen + # via QMP later + push @$cmd, '-incoming', 'defer'; push @$cmd, '-S'; } elsif ($statefile eq 'unix') { @@ -5991,8 +5990,15 @@ sub vm_start_nolock { eval { PVE::QemuServer::PCI::reserve_pci_usage($pci_reserve_list, $vmid, undef, $pid) }; warn $@ if $@; - if (defined($res->{migrate})) { - print "migration listens on $res->{migrate}->{uri}\n"; + if (defined(my $migrate = $res->{migrate})) { + if ($migrate->{proto} eq 'tcp') { + my $nodename = nodename(); + my $pfamily = PVE::Tools::get_host_address_family($nodename); + $migrate->{port} = PVE::Tools::next_migrate_port($pfamily); + $migrate->{uri} = "tcp:$migrate->{addr}:$migrate->{port}"; + mon_cmd($vmid, "migrate-incoming", uri => $migrate->{uri}); + } + print "migration listens on $migrate->{uri}\n"; } elsif ($statefile) { eval { mon_cmd($vmid, "cont"); }; warn $@ if $@;