[libvirt] [PATCH v2] virnetdevmacvlan.c: Introduce mutex for macvlan creation
Daniel P. Berrange
berrange at redhat.com
Fri Mar 1 10:45:46 UTC 2013
On Fri, Mar 01, 2013 at 11:36:24AM +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.
> ---
>
> diff to v1:
> -don't increase @retries
> -move error reporting to virNetDevMacVLanCreateMutexOnceInit
>
> src/util/virnetdevmacvlan.c | 37 ++++++++++++++++++++++++++++++++-----
> 1 file changed, 32 insertions(+), 5 deletions(-)
>
> diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
> index a74db1e..ddea11f 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,19 @@ 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)
> +{
> + if (virMutexInit(&virNetDevMacVLanCreateMutex) < 0) {
> + virReportSystemError(errno, "%s", _("unable to init mutex"));
> + return -1;
> + }
> + return 0;
> +}
> +
> +VIR_ONCE_GLOBAL_INIT(virNetDevMacVLanCreateMutex);
> +
> /**
> * virNetDevMacVLanCreate:
> *
> @@ -829,7 +843,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;
>
> @@ -871,22 +885,35 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
> } else {
> create_name:
> retries = 5;
> + if (virNetDevMacVLanCreateMutexInitialize() < 0)
> + return -1;
> + virMutexLock(&virNetDevMacVLanCreateMutex);
> for (c = 0; c < 8192; c++) {
> snprintf(ifname, sizeof(ifname), pattern, c);
> - if ((ret = virNetDevExists(ifname)) < 0)
> + if ((ret = virNetDevExists(ifname)) < 0) {
> + virMutexUnlock(&virNetDevMacVLanCreateMutex);
> return -1;
> + }
> if (!ret) {
> rc = virNetDevMacVLanCreate(ifname, type, macaddress, linkdev,
> macvtapMode, &do_retry);
> - if (rc == 0)
> + if (rc == 0) {
> + cr_ifname = ifname;
> break;
> + }
>
> if (do_retry && --retries)
> continue;
> - return -1;
> + break;
> }
> }
> - cr_ifname = ifname;
> +
> + virMutexUnlock(&virNetDevMacVLanCreateMutex);
> + if (!cr_ifname) {
> + virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> + _("Unable to create macvlan device"));
> + return -1;
> + }
> }
>
> if (virNetDevVPortProfileAssociate(cr_ifname,
ACK
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