From: Wolfgang Bumiller Date: Mon, 13 Jun 2016 12:31:09 +0000 (+0200) Subject: Fix #132: hold a lock while setting up vlan bridges X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=commitdiff_plain;h=a712bf6e378dc0ab56647bfe7649072eb4ee394f;hp=6a47f4b05d0db016ae8faf6b1ddb778cf738ca47 Fix #132: hold a lock while setting up vlan bridges It's possible for two simultaneous VM starts to try to create vlan bridges on non-vlan-aware bridges simultaneously, which causes one of them to fail with the error "can't add bridge ...". --- diff --git a/src/PVE/Network.pm b/src/PVE/Network.pm index 405f14b..b760c42 100644 --- a/src/PVE/Network.pm +++ b/src/PVE/Network.pm @@ -2,7 +2,7 @@ package PVE::Network; use strict; use warnings; -use PVE::Tools qw(run_command); +use PVE::Tools qw(run_command lock_file); use PVE::ProcFSTools; use PVE::INotify; use File::Basename; @@ -454,23 +454,24 @@ sub activate_bridge_vlan { die "no physical interface on bridge '$bridge'\n" if scalar(@ifaces) == 0; - # add bridgevlan if it doesn't already exist - if (! -d "/sys/class/net/$bridgevlan") { - system("/sbin/brctl addbr $bridgevlan") == 0 || - die "can't add bridge $bridgevlan\n"; - } + lock_network(sub { + # add bridgevlan if it doesn't already exist + if (! -d "/sys/class/net/$bridgevlan") { + system("/sbin/brctl addbr $bridgevlan") == 0 || + die "can't add bridge $bridgevlan\n"; + } - # for each physical interface (eth or bridge) bind them to bridge vlan - foreach my $iface (@ifaces) { - activate_bridge_vlan_slave($bridgevlan, $iface, $tag); - } + # for each physical interface (eth or bridge) bind them to bridge vlan + foreach my $iface (@ifaces) { + activate_bridge_vlan_slave($bridgevlan, $iface, $tag); + } - #fixme: set other bridge flags + #fixme: set other bridge flags - # be sure to have the bridge up - system("/sbin/ip link set $bridgevlan up") == 0 || - die "can't up bridge $bridgevlan\n"; - + # be sure to have the bridge up + system("/sbin/ip link set $bridgevlan up") == 0 || + die "can't up bridge $bridgevlan\n"; + }); return $bridgevlan; } @@ -533,4 +534,11 @@ sub is_ip_in_cidr { return $cidr_obj->overlaps($ip_obj) == $Net::IP::IP_B_IN_A_OVERLAP; } +sub lock_network { + my ($code, @param) = @_; + my $res = lock_file('/var/lock/pve-network.lck', 10, $code, @param); + die $@ if $@; + return $res; +} + 1;