[libvirt] [PATCH] virnetdevmacvlan.c: Introduce mutex for macvlan creation

Daniel P. Berrange berrange at redhat.com
Fri Mar 1 10:06:48 UTC 2013


On Thu, Feb 28, 2013 at 04:25:30PM +0100, Michal Privoznik wrote:
> Currently, after we removed the qemu driver lock, it may happen
> that two or more threads will start up a machine with macvlan and
> race over virNetDevMacVLanCreateWithVPortProfile(). However,
> there's a racy section in which we are generating a sequence of
> possible device names and detecting if they exits. If we found
> one which doesn't we try to create a device with that name.
> However, the other thread is doing just the same. Assume it will
> succeed and we must therefore fail. If this happens more than 5
> times (which in massive parallel startup surely will) we return
> -1 without any error reported. This patch is a simple hack to
> both of these problems. It introduces a mutex, so only one thread
> will enter the section, and if it runs out of possibilities,
> error is reported. Moreover, the number of retries is raised to 20.
> ---
> 
> This is just a quick hack which aim is to be as small as possible in order to
> be well understood and hence included in the release. After the release, this
> should be totally dropped in flavour of virNetDevNameAllocator.
> 
>  src/util/virnetdevmacvlan.c | 38 ++++++++++++++++++++++++++++++++------
>  1 file changed, 32 insertions(+), 6 deletions(-)
> 
> diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
> index a74db1e..bf5e7e0 100644
> --- a/src/util/virnetdevmacvlan.c
> +++ b/src/util/virnetdevmacvlan.c
> @@ -31,6 +31,7 @@
>  #include "virmacaddr.h"
>  #include "virutil.h"
>  #include "virerror.h"
> +#include "virthread.h"
>  
>  #define VIR_FROM_THIS VIR_FROM_NET
>  
> @@ -71,6 +72,15 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST,
>  # define MACVLAN_NAME_PREFIX	"macvlan"
>  # define MACVLAN_NAME_PATTERN	"macvlan%d"
>  
> +virMutex virNetDevMacVLanCreateMutex;
> +
> +static int virNetDevMacVLanCreateMutexOnceInit(void)
> +{
> +    return virMutexInit(&virNetDevMacVLanCreateMutex);
> +}
> +
> +VIR_ONCE_GLOBAL_INIT(virNetDevMacVLanCreateMutex);
> +
>  /**
>   * virNetDevMacVLanCreate:
>   *
> @@ -829,7 +839,7 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
>      char ifname[IFNAMSIZ];
>      int retries, do_retry = 0;
>      uint32_t macvtapMode;
> -    const char *cr_ifname;
> +    const char *cr_ifname = NULL;
>      int ret;
>      int vf = -1;
>  
> @@ -870,23 +880,39 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
>              return -1;
>      } else {
>  create_name:
> -        retries = 5;
> +        if (virNetDevMacVLanCreateMutexInitialize() < 0) {
> +            virReportSystemError(errno, "%s", _("unable to init mutext"));
> +            return -1;
> +        }

This is flawed - the way the global initializers work is that you
must report the error in the initializer. It preserves it in a
dedicated virERrorPtr and then copies it to the current virErrorPtr
thread local back in the calling code.

> +
> +        retries = 20;

I think this is not required now we are using a mutex to serialize
everything. The only race is between libvirtd and non-libvirtd apps
creating macvtap devices, which basically doesn't exist.

Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list