[libvirt] [PATCH 3/4] storage: Convert virStoragePoolObjList to use virObjectRWLockable
John Ferlan
jferlan at redhat.com
Wed Dec 13 20:06:31 UTC 2017
On 12/13/2017 11:40 AM, Michal Privoznik wrote:
> On 12/05/2017 02:43 AM, John Ferlan wrote:
>> Now that we have a private storage pool list, we can take the next
>> step and convert to using objects. In this case, we're going to use
>> RWLockable objects (just like every other driver) with two hash
>> tables for lookup by UUID or Name.
>>
>> Along the way the ForEach and Search API's will be adjusted to use
>> the related Hash API's and the various FindBy functions altered and
>> augmented to allow for HashLookup w/ and w/o the pool lock already
>> taken.
>>
>> After virStoragePoolObjRemove we will need to virObjectUnref(obj)
>> after to indicate the caller is "done" with it's reference. The
>> Unlock occurs during the Remove.
>>
>> The NumOf, GetNames, and Export functions all have their own callback
>> functions to return the required data and the FindDuplicate code
>> can use the HashSearch function callbacks.
>>
>> Signed-off-by: John Ferlan <jferlan at redhat.com>
>> ---
>> src/conf/virstorageobj.c | 638 +++++++++++++++++++++++++++++--------------
>> src/conf/virstorageobj.h | 3 -
>> src/libvirt_private.syms | 1 -
>> src/storage/storage_driver.c | 8 +-
>> src/test/test_driver.c | 7 +-
>> 5 files changed, 449 insertions(+), 208 deletions(-)
>>
>> diff --git a/src/conf/virstorageobj.c b/src/conf/virstorageobj.c
>> index a48346b24..0e5c98bf7 100644
>> --- a/src/conf/virstorageobj.c
>> +++ b/src/conf/virstorageobj.c
>> @@ -27,6 +27,7 @@
>> #include "viralloc.h"
>> #include "virerror.h"
>> #include "virfile.h"
>> +#include "virhash.h"
>> #include "virlog.h"
>> #include "virscsihost.h"
>> #include "virstring.h"
>> @@ -37,9 +38,12 @@
>> VIR_LOG_INIT("conf.virstorageobj");
>>
>> static virClassPtr virStoragePoolObjClass;
>> +static virClassPtr virStoragePoolObjListClass;
>>
>> static void
>> virStoragePoolObjDispose(void *opaque);
>> +static void
>> +virStoragePoolObjListDispose(void *opaque);
>>
>>
>> struct _virStorageVolDefList {
>> @@ -63,8 +67,15 @@ struct _virStoragePoolObj {
>> };
>>
>> struct _virStoragePoolObjList {
>> - size_t count;
>> - virStoragePoolObjPtr *objs;
>> + virObjectRWLockable parent;
>> +
>> + /* uuid string -> virStoragePoolObj mapping
>> + * for (1), lockless lookup-by-uuid */
>> + virHashTable *objs;
>> +
>> + /* name string -> virStoragePoolObj mapping
>> + * for (1), lockless lookup-by-name */
>> + virHashTable *objsName;
>> };
>>
>>
>> @@ -77,6 +88,12 @@ virStoragePoolObjOnceInit(void)
>> virStoragePoolObjDispose)))
>> return -1;
>>
>> + if (!(virStoragePoolObjListClass = virClassNew(virClassForObjectRWLockable(),
>> + "virStoragePoolObjList",
>> + sizeof(virStoragePoolObjList),
>> + virStoragePoolObjListDispose)))
>> + return -1;
>> +
>> return 0;
>> }
>>
>> @@ -240,13 +257,15 @@ virStoragePoolObjDispose(void *opaque)
>>
>>
>> void
>> -virStoragePoolObjListFree(virStoragePoolObjListPtr pools)
>> +virStoragePoolObjListDispose(void *opaque)
>> {
>> - size_t i;
>> - for (i = 0; i < pools->count; i++)
>> - virObjectUnref(pools->objs[i]);
>> - VIR_FREE(pools->objs);
>> - VIR_FREE(pools);
>> + virStoragePoolObjListPtr pools = opaque;
>> +
>> + if (!pools)
>> + return;
>
> This shouldn't be needed. This function is called iff pools are still
> not NULL.
>
Oh right, it's removed...
>> +
>> + virHashFree(pools->objs);
>> + virHashFree(pools->objsName);
>> }
>>
>>
>> @@ -255,13 +274,44 @@ virStoragePoolObjListNew(void)
>> {
>> virStoragePoolObjListPtr pools;
>>
>> - if (VIR_ALLOC(pools) < 0)
>> + if (virStoragePoolObjInitialize() < 0)
>> + return NULL;
>> +
>> + if (!(pools = virObjectRWLockableNew(virStoragePoolObjListClass)))
>> + return NULL;
>> +
>> + if (!(pools->objs = virHashCreate(20, virObjectFreeHashData)) ||
>> + !(pools->objsName = virHashCreate(20, virObjectFreeHashData))) {
>> + virObjectUnref(pools);
>> return NULL;
>> + }
>>
>> return pools;
>> }
>>
>>
>> +struct _virStoragePoolObjListForEachData {
>> + virStoragePoolObjListIterator iter;
>> + const void *opaque;
>> +};
>> +
>> +static int
>> +virStoragePoolObjListForEachCb(void *payload,
>> + const void *name ATTRIBUTE_UNUSED,
>> + void *opaque)
>> +{
>> + virStoragePoolObjPtr obj = payload;
>> + struct _virStoragePoolObjListForEachData *data =
>> + (struct _virStoragePoolObjListForEachData *)opaque;
>
> Do we need this typecast? I don't think so. You're assigning void
> *payload to virStoragePoolObjPtr obj directly, without any typecast.
>
True - it's probably a holdover from undoing something. Been too long
to remember though. Consider it gone.
>> +
>> + virObjectLock(obj);
>> + data->iter(obj, data->opaque);
>> + virObjectUnlock(obj);
>> +
>> + return 0;
>> +}
>> +
>> +
>> /**
>> * virStoragePoolObjListForEach
>> * @pools: Pointer to pools object
>> @@ -279,15 +329,35 @@ virStoragePoolObjListForEach(virStoragePoolObjListPtr pools,
>> virStoragePoolObjListIterator iter,
>> const void *opaque)
>> {
>> - size_t i;
>> - virStoragePoolObjPtr obj;
>> + struct _virStoragePoolObjListForEachData data = { .iter = iter,
>> + .opaque = opaque };
>>
>> - for (i = 0; i < pools->count; i++) {
>> - obj = pools->objs[i];
>> - virObjectLock(obj);
>> - iter(obj, opaque);
>> - virObjectUnlock(obj);
>> - }
>> + virObjectRWLockRead(pools);
>> + virHashForEach(pools->objs, virStoragePoolObjListForEachCb, &data);
>> + virObjectRWUnlock(pools);
>> +}
>> +
>> +
>> +struct _virStoragePoolObjListSearchData {
>> + virStoragePoolObjListSearcher searcher;
>> + const void *opaque;
>> +};
>> +
>> +
>> +static int
>> +virStoragePoolObjListSearchCb(const void *payload,
>> + const void *name ATTRIBUTE_UNUSED,
>> + const void *opaque)
>> +{
>> + virStoragePoolObjPtr obj = (virStoragePoolObjPtr) payload;
>> + struct _virStoragePoolObjListSearchData *data =
>> + (struct _virStoragePoolObjListSearchData *)opaque;
>
> Of course, typecast is needed here because we need to drop 'const'.
> Grrr. I wonder if locking an object is considered as modifying it. IOW
> if virObjectLock() should take 'void *' or 'const void *'.
>
I would think taking a lock is considered violation of const-ness. I can
certainly see cause for why a Search callback would say don't change
something though.
Taking a different approach - if the caller knew that the opaque was a
LockableObject, then it could do the right thing and keep the const
argument. It could probably even be better if it was a RWReadLock.
But that's a different rabbit-hole that I'm not sure I want to jump into
yet. Although I did dip my toes in that water and got more or less
rejected, so this is as close as I think I'm going to get for now.
Thanks for the review -
John
>> +
>> + virObjectLock(obj);
>> + if (data->searcher(obj, data->opaque))
>> + return 1;
>> + virObjectUnlock(obj);
>> + return 0;
>> }
>
> Michal
>
More information about the libvir-list
mailing list