[libvirt] PATCH: 4/28: Thread safety for test driver

Daniel Veillard veillard at redhat.com
Mon Dec 1 17:26:03 UTC 2008


On Sun, Nov 30, 2008 at 11:27:14PM +0000, Daniel P. Berrange wrote:
> This patch makes the test driver thread safe, adding a global driver lock,
> and the neccessary locking calls on domain/network/storagepool objects.
> 
> You'll notice there are many calls to
> 
>  virDomainObjUnlock
> 
> but very few corresponding  calls to
> 
>    virDomainObjLock
> 
> This is because the contract of  virDomainFindByUUID declares that the
> object it returns is already locked.
> 
> Methods which create / delete virDomainObj instances have to keep the
> global driver lock held for their whole duration, but others can drop
> it immediately after getting the virDomainObjPtr instance.

  Okay, what about virDomainFindByID and virDomainFindByName ? They lock
  too or we are just avoiding them ?

> +++ b/src/test.c
> @@ -58,6 +58,8 @@ typedef struct _testCell *testCellPtr;
>  #define MAX_CELLS 128
>  
>  struct _testConn {
> +    PTHREAD_MUTEX_T(lock);
> +

  hum, 
[...]
> +
> +static void testDriverLock(testConnPtr driver)
> +{
> +    pthread_mutex_lock(&driver->lock);
> +}
> +
> +static void testDriverUnlock(testConnPtr driver)
> +{
> +    pthread_mutex_unlock(&driver->lock);
> +}
>
>  static virCapsPtr
>  testBuildCapabilities(virConnectPtr conn) {
> @@ -200,6 +212,8 @@ static int testOpenDefault(virConnectPtr
>          return VIR_DRV_OPEN_ERROR;
>      }
>      conn->privateData = privconn;
> +    pthread_mutex_init(&privconn->lock, NULL);

  Can we abstract the mutex types and ops a little ? if libvirt were
to be ported to a platform/compiler where pthreads are not available
they would be able to fallback to xmlMutexPtr from libvirt which is
ported to all platforms where libxml2 is usable (as far as I know).

> +    testDriverLock(privconn);
>  
>      if (gettimeofday(&tv, NULL) < 0) {
>          testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of day"));
> @@ -232,6 +246,7 @@ static int testOpenDefault(virConnectPtr
>      domobj->def->id = privconn->nextDomID++;
>      domobj->state = VIR_DOMAIN_RUNNING;
>      domobj->persistent = 1;
> +    virDomainObjUnlock(domobj);

  the locking path is unclear here testOpenDefault uses
  virDomainAssignDef which then relies on virDomainFindByName() which
  would lock the domain object, right ?

>      if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML)))
>          goto error;
> @@ -241,6 +256,7 @@ static int testOpenDefault(virConnectPtr
>      }
>      netobj->active = 1;
>      netobj->persistent = 1;
> +    virNetworkObjUnlock(netobj);

  same with virNetworkAssignDef()

>      if (!(pooldef = virStoragePoolDefParse(conn, defaultPoolXML, NULL)))
>          goto error;
> @@ -250,10 +266,15 @@ static int testOpenDefault(virConnectPtr
>          virStoragePoolDefFree(pooldef);
>          goto error;
>      }
> -    if (testStoragePoolObjSetDefaults(poolobj) == -1)
> +
> +    if (testStoragePoolObjSetDefaults(poolobj) == -1) {
> +        virStoragePoolObjUnlock(poolobj);
>          goto error;

  ideally done in the error: switch but this makes things harder

> +    }
>      poolobj->active = 1;
> +    virStoragePoolObjUnlock(poolobj);
>  
> +    testDriverUnlock(privconn);
>      return VIR_DRV_OPEN_SUCCESS;
>  
>  error:
> @@ -261,6 +282,7 @@ error:
>      virNetworkObjListFree(&privconn->networks);
>      virStoragePoolObjListFree(&privconn->pools);
>      virCapabilitiesFree(privconn->caps);
> +    testDriverUnlock(privconn);
>      VIR_FREE(privconn);
>      return VIR_DRV_OPEN_ERROR;
>  }
> @@ -307,6 +329,8 @@ static int testOpenFromFile(virConnectPt

  okay, similar to testOpenDefault()

[...]
> @@ -710,7 +748,11 @@ static virDomainPtr testLookupDomainByID
>      virDomainPtr ret = NULL;
>      virDomainObjPtr dom;
>  
> -    if ((dom = virDomainFindByID(&privconn->domains, id)) == NULL) {
> +    testDriverLock(privconn);
> +    dom = virDomainFindByID(&privconn->domains, id);
> +    testDriverUnlock(privconn);

  so all virDomainFindBy__ do the locking, fine.

[...]
> @@ -750,7 +800,11 @@ static virDomainPtr testLookupDomainByNa
>      virDomainPtr ret = NULL;
>      virDomainObjPtr dom;
>  
> -    if ((dom = virDomainFindByName(&privconn->domains, name)) == NULL) {
> +    testDriverLock(privconn);
> +    dom = virDomainFindByName(&privconn->domains, name);
> +    testDriverUnlock(privconn);
> +
> +    if (dom == NULL) {

  actually a lot of those sequences are common, and correspond to the
macros. later we may want to refactor maybe

[...]
> @@ -797,10 +859,14 @@ static int testDestroyDomain (virDomainP
>      if (!privdom->persistent) {
>          virDomainRemoveInactive(&privconn->domains,
>                                  privdom);

  will virDomainRemoveInactive also  remove the lock before destroying
  the object ? the answer is surely in a later patch

[...]
> @@ -884,9 +959,17 @@ static int testShutdownDomain (virDomain
>      privdom->state = VIR_DOMAIN_SHUTOFF;
>      domain->id = -1;
>      privdom->def->id = -1;
> +    if (!privdom->persistent) {
> +        virDomainRemoveInactive(&privconn->domains,
> +                                privdom);
> +        privdom = NULL;
> +    }
>      ret = 0;

  hum, not specific to threading, we are improving the driver here.

>  cleanup:
> +    if (privdom)
> +        virDomainObjUnlock(privdom);
> +    testDriverUnlock(privconn);
>      return ret;
>  }
>  

  okay, others functions are easier, but it's still painful to review.

> diff --git a/tests/virsh-all b/tests/virsh-all
> --- a/tests/virsh-all
> +++ b/tests/virsh-all
> @@ -22,6 +22,7 @@ fi
>  fi
>  
>  test -z "$srcdir" && srcdir=$(pwd)
> +test -z "$abs_top_srcdir" && abs_top_srcdir=$(pwd)/..
>  . "$srcdir/test-lib.sh"

  ???

I hope it's worth the effort, it's a lot of complexity added.
One of the things which worries me is that detecting errors will be
hard, you end up with a locked server that can be far from trivial
to debug.
I'm really wondering how we could automate testing or at least ease the
debug,

  +1

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list