[libvirt] [PATCH] Release conn lock before reporting errors

Daniel P. Berrange berrange at redhat.com
Wed Jul 22 16:08:42 UTC 2009


On Wed, Jul 22, 2009 at 11:13:45AM -0400, Laine Stump wrote:
> This is a follow-on to 528d37. It's fixing several other cases in
> datatypes.c where we try to report an error while holding the conn's
> lock, which can't work because the error reporting also tries to lock
> the conn.
> 
> ---
>  src/datatypes.c |  133 ++++++++++++++++++++++++++++++++++---------------------
>  1 files changed, 82 insertions(+), 51 deletions(-)

ACK, same pattern as previous patch.

Daniel

> 
> diff --git a/src/datatypes.c b/src/datatypes.c
> index ba5401d..c2030dd 100644
> --- a/src/datatypes.c
> +++ b/src/datatypes.c
> @@ -270,11 +270,13 @@ virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
>      /* TODO check the UUID */
>      if (ret == NULL) {
>          if (VIR_ALLOC(ret) < 0) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
>          ret->name = strdup(name);
>          if (ret->name == NULL) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
> @@ -285,6 +287,7 @@ virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
>              memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
>  
>          if (virHashAddEntry(conn->domains, name, ret) < 0) {
> +            virMutexUnlock(&conn->lock);
>              virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
>                              _("failed to add domain to connection hash table"));
>              goto error;
> @@ -299,7 +302,6 @@ virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
>      return(ret);
>  
>   error:
> -    virMutexUnlock(&conn->lock);
>      if (ret != NULL) {
>          VIR_FREE(ret->name);
>          VIR_FREE(ret);
> @@ -325,24 +327,28 @@ virReleaseDomain(virDomainPtr domain) {
>      DEBUG("release domain %p %s", domain, domain->name);
>  
>      /* TODO search by UUID first as they are better differenciators */
> -    if (virHashRemoveEntry(conn->domains, domain->name, NULL) < 0)
> +    if (virHashRemoveEntry(conn->domains, domain->name, NULL) < 0) {
> +        virMutexUnlock(&conn->lock);
>          virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
>                          _("domain missing from connection hash table"));
> +        conn = NULL;
> +    }
>  
>      domain->magic = -1;
>      domain->id = -1;
>      VIR_FREE(domain->name);
>      VIR_FREE(domain);
>  
> -    DEBUG("unref connection %p %d", conn, conn->refs);
> -    conn->refs--;
> -    if (conn->refs == 0) {
> -        virReleaseConnect(conn);
> -        /* Already unlocked mutex */
> -        return;
> +    if (conn) {
> +        DEBUG("unref connection %p %d", conn, conn->refs);
> +        conn->refs--;
> +        if (conn->refs == 0) {
> +            virReleaseConnect(conn);
> +            /* Already unlocked mutex */
> +            return;
> +        }
> +        virMutexUnlock(&conn->lock);
>      }
> -
> -    virMutexUnlock(&conn->lock);
>  }
>  
>  
> @@ -406,11 +412,13 @@ virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) {
>      /* TODO check the UUID */
>      if (ret == NULL) {
>          if (VIR_ALLOC(ret) < 0) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
>          ret->name = strdup(name);
>          if (ret->name == NULL) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
> @@ -420,6 +428,7 @@ virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) {
>              memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
>  
>          if (virHashAddEntry(conn->networks, name, ret) < 0) {
> +            virMutexUnlock(&conn->lock);
>              virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
>                              _("failed to add network to connection hash table"));
>              goto error;
> @@ -431,7 +440,6 @@ virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) {
>      return(ret);
>  
>   error:
> -    virMutexUnlock(&conn->lock);
>      if (ret != NULL) {
>          VIR_FREE(ret->name);
>          VIR_FREE(ret);
> @@ -457,23 +465,27 @@ virReleaseNetwork(virNetworkPtr network) {
>      DEBUG("release network %p %s", network, network->name);
>  
>      /* TODO search by UUID first as they are better differenciators */
> -    if (virHashRemoveEntry(conn->networks, network->name, NULL) < 0)
> +    if (virHashRemoveEntry(conn->networks, network->name, NULL) < 0) {
> +        virMutexUnlock(&conn->lock);
>          virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
>                          _("network missing from connection hash table"));
> +        conn = NULL;
> +    }
>  
>      network->magic = -1;
>      VIR_FREE(network->name);
>      VIR_FREE(network);
>  
> -    DEBUG("unref connection %p %d", conn, conn->refs);
> -    conn->refs--;
> -    if (conn->refs == 0) {
> -        virReleaseConnect(conn);
> -        /* Already unlocked mutex */
> -        return;
> +    if (conn) {
> +        DEBUG("unref connection %p %d", conn, conn->refs);
> +        conn->refs--;
> +        if (conn->refs == 0) {
> +            virReleaseConnect(conn);
> +            /* Already unlocked mutex */
> +            return;
> +        }
> +        virMutexUnlock(&conn->lock);
>      }
> -
> -    virMutexUnlock(&conn->lock);
>  }
>  
>  
> @@ -714,11 +726,13 @@ virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uui
>      /* TODO check the UUID */
>      if (ret == NULL) {
>          if (VIR_ALLOC(ret) < 0) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
>          ret->name = strdup(name);
>          if (ret->name == NULL) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
> @@ -728,6 +742,7 @@ virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uui
>              memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
>  
>          if (virHashAddEntry(conn->storagePools, name, ret) < 0) {
> +            virMutexUnlock(&conn->lock);
>              virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
>                              _("failed to add storage pool to connection hash table"));
>              goto error;
> @@ -739,7 +754,6 @@ virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uui
>      return(ret);
>  
>  error:
> -    virMutexUnlock(&conn->lock);
>      if (ret != NULL) {
>          VIR_FREE(ret->name);
>          VIR_FREE(ret);
> @@ -766,23 +780,27 @@ virReleaseStoragePool(virStoragePoolPtr pool) {
>      DEBUG("release pool %p %s", pool, pool->name);
>  
>      /* TODO search by UUID first as they are better differenciators */
> -    if (virHashRemoveEntry(conn->storagePools, pool->name, NULL) < 0)
> +    if (virHashRemoveEntry(conn->storagePools, pool->name, NULL) < 0) {
> +        virMutexUnlock(&conn->lock);
>          virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
>                          _("pool missing from connection hash table"));
> +        conn = NULL;
> +    }
>  
>      pool->magic = -1;
>      VIR_FREE(pool->name);
>      VIR_FREE(pool);
>  
> -    DEBUG("unref connection %p %d", conn, conn->refs);
> -    conn->refs--;
> -    if (conn->refs == 0) {
> -        virReleaseConnect(conn);
> -        /* Already unlocked mutex */
> -        return;
> +    if (conn) {
> +        DEBUG("unref connection %p %d", conn, conn->refs);
> +        conn->refs--;
> +        if (conn->refs == 0) {
> +            virReleaseConnect(conn);
> +            /* Already unlocked mutex */
> +            return;
> +        }
> +        virMutexUnlock(&conn->lock);
>      }
> -
> -    virMutexUnlock(&conn->lock);
>  }
>  
>  
> @@ -845,16 +863,19 @@ virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const c
>      ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key);
>      if (ret == NULL) {
>          if (VIR_ALLOC(ret) < 0) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
>          ret->pool = strdup(pool);
>          if (ret->pool == NULL) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
>          ret->name = strdup(name);
>          if (ret->name == NULL) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
> @@ -864,6 +885,7 @@ virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const c
>          ret->conn = conn;
>  
>          if (virHashAddEntry(conn->storageVols, key, ret) < 0) {
> +            virMutexUnlock(&conn->lock);
>              virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
>                              _("failed to add storage vol to connection hash table"));
>              goto error;
> @@ -875,7 +897,6 @@ virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const c
>      return(ret);
>  
>  error:
> -    virMutexUnlock(&conn->lock);
>      if (ret != NULL) {
>          VIR_FREE(ret->name);
>          VIR_FREE(ret->pool);
> @@ -903,24 +924,28 @@ virReleaseStorageVol(virStorageVolPtr vol) {
>      DEBUG("release vol %p %s", vol, vol->name);
>  
>      /* TODO search by UUID first as they are better differenciators */
> -    if (virHashRemoveEntry(conn->storageVols, vol->key, NULL) < 0)
> +    if (virHashRemoveEntry(conn->storageVols, vol->key, NULL) < 0) {
> +        virMutexUnlock(&conn->lock);
>          virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
>                          _("vol missing from connection hash table"));
> +        conn = NULL;
> +    }
>  
>      vol->magic = -1;
>      VIR_FREE(vol->name);
>      VIR_FREE(vol->pool);
>      VIR_FREE(vol);
>  
> -    DEBUG("unref connection %p %d", conn, conn->refs);
> -    conn->refs--;
> -    if (conn->refs == 0) {
> -        virReleaseConnect(conn);
> -        /* Already unlocked mutex */
> -        return;
> +    if (conn) {
> +        DEBUG("unref connection %p %d", conn, conn->refs);
> +        conn->refs--;
> +        if (conn->refs == 0) {
> +            virReleaseConnect(conn);
> +            /* Already unlocked mutex */
> +            return;
> +        }
> +        virMutexUnlock(&conn->lock);
>      }
> -
> -    virMutexUnlock(&conn->lock);
>  }
>  
>  
> @@ -981,7 +1006,8 @@ virGetNodeDevice(virConnectPtr conn, const char *name)
>  
>      ret = (virNodeDevicePtr) virHashLookup(conn->nodeDevices, name);
>      if (ret == NULL) {
> -       if (VIR_ALLOC(ret) < 0) {
> +        if (VIR_ALLOC(ret) < 0) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
> @@ -989,11 +1015,13 @@ virGetNodeDevice(virConnectPtr conn, const char *name)
>          ret->conn = conn;
>          ret->name = strdup(name);
>          if (ret->name == NULL) {
> +            virMutexUnlock(&conn->lock);
>              virReportOOMError(conn);
>              goto error;
>          }
>  
>          if (virHashAddEntry(conn->nodeDevices, name, ret) < 0) {
> +            virMutexUnlock(&conn->lock);
>              virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
>                              _("failed to add node dev to conn hash table"));
>              goto error;
> @@ -1005,7 +1033,6 @@ virGetNodeDevice(virConnectPtr conn, const char *name)
>      return(ret);
>  
>  error:
> -    virMutexUnlock(&conn->lock);
>      if (ret != NULL) {
>          VIR_FREE(ret->name);
>          VIR_FREE(ret);
> @@ -1031,24 +1058,28 @@ virReleaseNodeDevice(virNodeDevicePtr dev) {
>      virConnectPtr conn = dev->conn;
>      DEBUG("release dev %p %s", dev, dev->name);
>  
> -    if (virHashRemoveEntry(conn->nodeDevices, dev->name, NULL) < 0)
> +    if (virHashRemoveEntry(conn->nodeDevices, dev->name, NULL) < 0) {
> +        virMutexUnlock(&conn->lock);
>          virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
>                          _("dev missing from connection hash table"));
> +        conn = NULL;
> +    }
>  
>      dev->magic = -1;
>      VIR_FREE(dev->name);
>      VIR_FREE(dev->parent);
>      VIR_FREE(dev);
>  
> -    DEBUG("unref connection %p %d", conn, conn->refs);
> -    conn->refs--;
> -    if (conn->refs == 0) {
> -        virReleaseConnect(conn);
> -        /* Already unlocked mutex */
> -        return;
> +    if (conn) {
> +        DEBUG("unref connection %p %d", conn, conn->refs);
> +        conn->refs--;
> +        if (conn->refs == 0) {
> +            virReleaseConnect(conn);
> +            /* Already unlocked mutex */
> +            return;
> +        }
> +        virMutexUnlock(&conn->lock);
>      }
> -
> -    virMutexUnlock(&conn->lock);
>  }
>  
>  
> -- 
> 1.6.0.6
> 
> --
> Libvir-list mailing list
> Libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list