libgfapi: revamp glfs_new function

Current glfs_new() function is not flexible enough to error out
and destroy the struct members or objects initialized just before the
error path/condition. This make the structs or objects to continue or
left out with partially recorded data in fs and ctx structs and cause
crashes/issues later in the code path. This patch avoid the issue.

Change-Id: Ie4514b82b24723a46681cc7832a08870afc0cb28
BUG: 1202492 
Signed-off-by: Humble Devassy Chirammal <hchiramm@redhat.com>
Reviewed-on: http://review.gluster.org/9903
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Poornima G <pgurusid@redhat.com>
Reviewed-by: soumya k <skoduri@redhat.com>
Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
This commit is contained in:
Humble Devassy Chirammal 2015-03-20 18:57:52 +05:30 committed by Kaleb KEITHLEY
parent b247ff4b29
commit 299f6ce2b1
2 changed files with 85 additions and 34 deletions

View File

@ -556,56 +556,105 @@ glfs_poller (void *data)
struct glfs *
pub_glfs_new (const char *volname)
{
struct glfs *fs = NULL;
int ret = -1;
glusterfs_ctx_t *ctx = NULL;
struct glfs *fs = NULL;
int ret = -1;
glusterfs_ctx_t *ctx = NULL;
gf_boolean_t cleanup_fini = _gf_false;
if (!volname) {
errno = EINVAL;
return NULL;
}
ctx = glusterfs_ctx_new ();
if (!ctx) {
return NULL;
}
fs = CALLOC (1, sizeof (*fs));
if (!fs)
return NULL;
/* first globals init, for gf_mem_acct_enable_set () */
ret = glusterfs_globals_init (ctx);
if (ret)
return NULL;
ret = pthread_mutex_init (&fs->mutex, NULL);
if (ret != 0)
goto freefs;
ret = pthread_cond_init (&fs->cond, NULL);
if (ret != 0)
goto mutex_destroy;
ret = pthread_cond_init (&fs->child_down_cond, NULL);
if (ret != 0)
goto cond_destroy;
ret = pthread_mutex_init (&fs->upcall_list_mutex, NULL);
if (ret != 0)
goto cond_child_destroy;
cleanup_fini = _gf_true;
ctx = glusterfs_ctx_new ();
if (!ctx)
goto freefs;
/* first globals init, for gf_mem_acct_enable_set () */
ret = glusterfs_globals_init (ctx);
if (ret)
goto freefs;
if (!THIS->ctx)
THIS->ctx = ctx;
/* then ctx_defaults_init, for xlator_mem_acct_init(THIS) */
ret = glusterfs_ctx_defaults_init (ctx);
if (ret)
return NULL;
/* then ctx_defaults_init, for xlator_mem_acct_init(THIS) */
fs = CALLOC (1, sizeof (*fs));
if (!fs)
return NULL;
fs->ctx = ctx;
ret = glusterfs_ctx_defaults_init (ctx);
if (ret)
goto freefs;
glfs_set_logging (fs, "/dev/null", 0);
fs->ctx = ctx;
fs->ctx->cmd_args.volfile_id = gf_strdup (volname);
ret = glfs_set_logging (fs, "/dev/null", 0);
if (ret)
goto freefs;
fs->volname = strdup (volname);
fs->ctx->cmd_args.volfile_id = gf_strdup (volname);
if (!(fs->ctx->cmd_args.volfile_id))
goto freefs;
pthread_mutex_init (&fs->mutex, NULL);
pthread_cond_init (&fs->cond, NULL);
pthread_cond_init (&fs->child_down_cond, NULL);
INIT_LIST_HEAD (&fs->openfds);
fs->volname = strdup (volname);
if (!fs->volname)
goto freefs;
INIT_LIST_HEAD (&fs->openfds);
INIT_LIST_HEAD (&fs->upcall_list);
pthread_mutex_init (&fs->upcall_list_mutex, NULL);
fs->pin_refcnt = 0;
return fs;
return fs;
cond_child_destroy:
pthread_cond_destroy (&fs->child_down_cond);
cond_destroy:
pthread_cond_destroy (&fs->cond);
mutex_destroy:
pthread_mutex_destroy (&fs->mutex);
freefs:
/*
* When pthread_*init() fails there is no way for other cleanup
* funtions (glfs_fini/glfs_free_from_ctx) to know which of them succeded
* and which did not(unless there is a flag). Hence pthread cleanup is done
* in this funtion.Anything that fails after pthread_*_init() succeeds, should
* directly call glfs_fini() to cleanup the resources.
*/
if (!cleanup_fini)
FREE(fs);
else
glfs_fini (fs);
fs = NULL;
return fs;
}
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_new, 3.4.0);

View File

@ -111,11 +111,13 @@ void* __gf_default_realloc (void *oldptr, size_t size)
#define CALLOC(cnt,size) __gf_default_calloc(cnt,size)
#define REALLOC(ptr,size) __gf_default_realloc(ptr,size)
#define FREE(ptr) \
if (ptr != NULL) { \
free ((void *)ptr); \
ptr = (void *)0xeeeeeeee; \
}
#define FREE(ptr) \
do { \
if (ptr != NULL) { \
free ((void *)ptr); \
ptr = (void *)0xeeeeeeee; \
} \
} while (0)
#define GF_CALLOC(nmemb, size, type) __gf_calloc (nmemb, size, type, #type)