diff options
| author | Humble Devassy Chirammal <hchiramm@redhat.com> | 2015-03-20 18:57:52 +0530 | 
|---|---|---|
| committer | Kaleb KEITHLEY <kkeithle@redhat.com> | 2015-03-30 05:31:34 -0700 | 
| commit | 299f6ce2b17216a6c09d5345139b9a78f7505b24 (patch) | |
| tree | 9be7929ddc9618a975d4ed3c341957f25d926150 /api/src | |
| parent | b247ff4b297481148ab2fe4c7b832aac85f6ad72 (diff) | |
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>
Diffstat (limited to 'api/src')
| -rw-r--r-- | api/src/glfs.c | 107 | 
1 files changed, 78 insertions, 29 deletions
diff --git a/api/src/glfs.c b/api/src/glfs.c index 8bd410c716d..4ae4d769471 100644 --- a/api/src/glfs.c +++ b/api/src/glfs.c @@ -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; - -	glfs_set_logging (fs, "/dev/null", 0); +        ret = glusterfs_ctx_defaults_init (ctx); +        if (ret) +                goto freefs; -	fs->ctx->cmd_args.volfile_id = gf_strdup (volname); +        fs->ctx = ctx; -	fs->volname = strdup (volname); +        ret = glfs_set_logging (fs, "/dev/null", 0); +        if (ret) +                goto freefs; -	pthread_mutex_init (&fs->mutex, NULL); -	pthread_cond_init (&fs->cond, NULL); -        pthread_cond_init (&fs->child_down_cond, NULL); +        fs->ctx->cmd_args.volfile_id = gf_strdup (volname); +        if (!(fs->ctx->cmd_args.volfile_id)) +                goto freefs; -	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);  | 
