[libvirt] [PATCH v2 1/1] gluster: cache glfs connection object per volume

Daniel P. Berrange berrange at redhat.com
Wed Nov 30 11:29:28 UTC 2016


On Wed, Nov 30, 2016 at 04:06:37PM +0530, prasanna.kalever at redhat.com wrote:
> diff --git a/src/storage/storage_backend_gluster.c b/src/storage/storage_backend_gluster.c
> index 8e86704..18b7fc3 100644
> --- a/src/storage/storage_backend_gluster.c
> +++ b/src/storage/storage_backend_gluster.c
> @@ -31,11 +31,34 @@
>  #include "virstoragefile.h"
>  #include "virstring.h"
>  #include "viruri.h"
> +#include "viratomic.h"
>  
>  #define VIR_FROM_THIS VIR_FROM_STORAGE
>  
>  VIR_LOG_INIT("storage.storage_backend_gluster");
>  
> +static bool virGlusterGlobalError;
> +static virOnceControl glusterConnOnce = VIR_ONCE_CONTROL_INITIALIZER;
> +
> +typedef struct _virStorageBackendGlusterState virStorageBackendGlusterState;
> +typedef virStorageBackendGlusterState *virStorageBackendGlusterStatePtr;
> +
> +typedef struct _virStorageFileBackendGlusterPriv virStorageFileBackendGlusterPriv;
> +typedef virStorageFileBackendGlusterPriv *virStorageFileBackendGlusterPrivPtr;
> +
> +typedef struct _unixSocketAddress unixSocketAddress;
> +
> +typedef struct _inetSocketAddress inetSocketAddress;
> +
> +typedef struct _glusterServer glusterServer;
> +typedef struct _glusterServer *glusterServerPtr;

*all* structs should be fully namespaced. ie have a VirStorageBackendGluster
name prefix


> +struct _virStorageBackendGlusterStatePreopened {
> +    virStorageFileBackendGlusterPrivPtr priv;
> +    unsigned int nservers;

size_t

> +    glusterServerPtr *hosts;
> +    char *volname;
> +    volatile int ref;
> +};
> +
> +struct _virStorageBackendGlusterconnCache {
> +    virMutex lock;
> +    size_t nConn;
> +    virStorageBackendGlusterStatePtrPreopened *conn;
> +};
> +
> +virStorageBackendGlusterconnCachePtr connCache = {0,};

'static'

and all static vars are initialized to zero so kill {0,}

> +static void
> +virGlusterConnAlloc(void)
> +{
> +    if ((VIR_ALLOC(connCache) < 0))
> +        virGlusterGlobalError = false;
> +}
> +
> +static int
> +virStorageBackendGlusterSetPreopened(virStorageSourcePtr src,
> +                                     virStorageFileBackendGlusterPrivPtr priv)
> +{
> +    unsigned int idx;
> +    virStorageBackendGlusterStatePtrPreopened entry = NULL;
> +
> +    if (connCache == NULL && (virOnce(&glusterConnOnce,
> +                                      virGlusterConnAlloc) < 0))
> +        return -1;

Checking if connCache is NULL before calling virOnce is pointless.
The whole point of virOnce is that you can blindly call it multiple
times and it'll only run once.

> +    if (virGlusterGlobalError)
> +        return -1;
> +
> +    if (!connCache->nConn) {
> +        if (virMutexInit(&connCache->lock) < 0) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("Unable to initialize mutex"));
> +            return -1;
> +        }
> +    }

This is not thread safe - mutex initialization should be in the
virOnce intializer.

> +
> +    for (idx = 0; idx < connCache->nConn; idx++) {
> +        if (STREQ(connCache->conn[idx]->volname, src->volume))
> +            return 0;
> +    }

Not thread safe since connCache is not locked at this time

> +
> +    if (VIR_ALLOC(entry) < 0)
> +        return -1;
> +
> +    if (VIR_STRDUP(entry->volname, src->volume) < 0)
> +        goto error;
> +
> +    if (VIR_ALLOC_N(entry->hosts, entry->nservers) < 0)
> +        goto error;
> +
> +    entry->nservers = src->nhosts;
> +
> +    for (idx = 0; idx < src->nhosts; idx++) {
> +        if (VIR_ALLOC(entry->hosts[idx]) < 0)
> +            goto error;
> +        if (src->hosts[idx].transport == VIR_STORAGE_NET_HOST_TRANS_UNIX) {
> +            if (VIR_STRDUP(entry->hosts[idx]->u.uds.path,
> +                           src->hosts[idx].socket) < 0)
> +               goto error;
> +            entry->hosts[idx]->type = VIR_STORAGE_NET_HOST_TRANS_UNIX;
> +        } else if (src->hosts[idx].transport ==
> +                   VIR_STORAGE_NET_HOST_TRANS_TCP) {
> +            if (VIR_STRDUP(entry->hosts[idx]->u.tcp.host,
> +                           src->hosts[idx].name) < 0)
> +                goto error;
> +            if (VIR_STRDUP(entry->hosts[idx]->u.tcp.port,
> +                           src->hosts[idx].port) < 0)
> +                goto error;
> +            entry->hosts[idx]->type = VIR_STORAGE_NET_HOST_TRANS_TCP;
> +        } else {
> +            entry->hosts[idx]->type = VIR_STORAGE_NET_HOST_TRANS_LAST;
> +        }
> +    }
> +    entry->priv = priv;
> +
> +    virMutexLock(&connCache->lock);
> +    virAtomicIntSet(&entry->ref, 1);
> +    if (VIR_INSERT_ELEMENT(connCache->conn, -1, connCache->nConn, entry) < 0) {
> +        virMutexUnlock(&connCache->lock);
> +        goto error;
> +    }
> +    virMutexUnlock(&connCache->lock);
> +
> +    return 0;
> +
> + error:
> +    for (idx = 0; idx < entry->nservers; idx++) {
> +        if (entry->hosts[idx]->type == VIR_STORAGE_NET_HOST_TRANS_UNIX) {
> +            VIR_FREE(entry->hosts[idx]->u.uds.path);
> +        } else {
> +            VIR_FREE(entry->hosts[idx]->u.tcp.host);
> +            VIR_FREE(entry->hosts[idx]->u.tcp.port);
> +        }
> +        VIR_FREE(entry->hosts[idx]);
> +    }
> +
> +    VIR_FREE(entry->hosts);
> +    VIR_FREE(entry->volname);
> +    VIR_FREE(entry);
> +
> +    return -1;
> +}
> +
> +static glfs_t *
> +virStorageBackendGlusterFindPreopened(virStorageSourcePtr src)
> +{
> +    unsigned int cIdx, sIdx, nIdx; /* connectionIdx, savedIdx, newIdx */
> +    bool flag = false;
> +
> +    if (connCache == NULL)
> +        return NULL;

Not thread safe, since something could be in middlle of calling
the virOnce to initialize this.

> +
> +    virStorageBackendGlusterStatePtrPreopened entry;
> +
> +    for (cIdx = 0; cIdx < connCache->nConn; cIdx++) {
> +        entry = connCache->conn[cIdx];

You've not locked connCache, and same in later methods

> +        if (STREQ(entry->volname, src->volume)) {
> +            if (entry->nservers == src->nhosts) {
> +                for (sIdx = 0; sIdx < entry->nservers; sIdx++) {
> +                    for (nIdx = 0; nIdx < src->nhosts; nIdx++) {
> +                        if (entry->hosts[sIdx]->type ==
> +                            src->hosts[nIdx].transport) {
> +                            if (entry->hosts[sIdx]->type
> +                                    == VIR_STORAGE_NET_HOST_TRANS_UNIX) {
> +                                if (STREQ(entry->hosts[sIdx]->u.uds.path,
> +                                          src->hosts[nIdx].socket)) {
> +                                    flag = true;
> +                                    break;
> +                                }
> +                            } else {
> +                                if (STREQ(entry->hosts[sIdx]->u.tcp.host,
> +                                          src->hosts[nIdx].name) &&
> +                                    STREQ(entry->hosts[sIdx]->u.tcp.port,
> +                                          src->hosts[nIdx].port)) {
> +                                    flag = true;
> +                                    break;
> +                                }
> +                            }
> +                        }
> +                    }
> +                    if (!flag)
> +                        return NULL;
> +                    flag = false;
> +                }
> +                virAtomicIntInc(&entry->ref);
> +                return entry->priv->vol;
> +            } else {
> +                return NULL;
> +            }
> +        }
> +    }
> +    return NULL;
> +}
Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://entangle-photo.org       -o-    http://search.cpan.org/~danberr/ :|




More information about the libvir-list mailing list