diff options
Diffstat (limited to 'libglusterfs')
-rw-r--r-- | libglusterfs/src/glusterfs.h | 2 | ||||
-rw-r--r-- | libglusterfs/src/graph.c | 60 | ||||
-rw-r--r-- | libglusterfs/src/xlator.c | 115 | ||||
-rw-r--r-- | libglusterfs/src/xlator.h | 3 |
4 files changed, 140 insertions, 40 deletions
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 1302a11d82b..c482b3d2242 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -603,6 +603,8 @@ struct gf_flock { #define SECURE_ACCESS_FILE GLUSTERD_DEFAULT_WORKDIR "/secure-access" int glusterfs_graph_prepare (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx); +int glusterfs_graph_destroy_residual (glusterfs_graph_t *graph); +int glusterfs_graph_deactivate (glusterfs_graph_t *graph); int glusterfs_graph_destroy (glusterfs_graph_t *graph); int glusterfs_graph_activate (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx); glusterfs_graph_t *glusterfs_graph_construct (FILE *fp); diff --git a/libglusterfs/src/graph.c b/libglusterfs/src/graph.c index f6db5557a33..b427740f10f 100644 --- a/libglusterfs/src/graph.c +++ b/libglusterfs/src/graph.c @@ -328,6 +328,19 @@ glusterfs_graph_init (glusterfs_graph_t *graph) return 0; } +int +glusterfs_graph_deactivate (glusterfs_graph_t *graph) +{ + xlator_t *top = NULL; + + if (graph == NULL) + goto out; + + top = graph->top; + xlator_tree_fini (top); + out: + return 0; +} static int _log_if_unknown_option (dict_t *dict, char *key, data_t *value, void *data) @@ -763,14 +776,53 @@ glusterfs_graph_reconfigure (glusterfs_graph_t *oldgraph, } int -glusterfs_graph_destroy (glusterfs_graph_t *graph) +glusterfs_graph_destroy_residual (glusterfs_graph_t *graph) { - GF_VALIDATE_OR_GOTO ("graph", graph, out); + int ret = -1; - xlator_tree_free (graph->first); + if (graph == NULL) + return ret; + + ret = xlator_tree_free_memacct (graph->first); list_del_init (&graph->list); GF_FREE (graph); + + return ret; +} + +/* This function destroys all the xlator members except for the + * xlator strcuture and its mem accounting field. + * + * If otherwise, it would destroy the master xlator object as well + * its mem accounting, which would mean after calling glusterfs_graph_destroy() + * there cannot be any reference to GF_FREE() from the master xlator, this is + * not possible because of the following dependencies: + * - glusterfs_ctx_t will have mem pools allocated by the master xlators + * - xlator objects will have references to those mem pools(g: dict) + * + * Ordering the freeing in any of the order will also not solve the dependency: + * - Freeing xlator objects(including memory accounting) before mem pools + * destruction will mean not use GF_FREE while destroying mem pools. + * - Freeing mem pools and then destroying xlator objects would lead to crashes + * when xlator tries to unref dict or other mem pool objects. + * + * Hence the way chosen out of this interdependency is to split xlator object + * free into two stages: + * - Free all the xlator members excpet for its mem accounting structure + * - Free all the mem accouting structures of xlator along with the xlator + * object itself. + */ +int +glusterfs_graph_destroy (glusterfs_graph_t *graph) +{ + int ret = 0; + + GF_VALIDATE_OR_GOTO ("graph", graph, out); + + ret = xlator_tree_free_members (graph->first); + + ret = glusterfs_graph_destroy_residual (graph); out: - return 0; + return ret; } diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index 7b873fcc79d..3378a35d54a 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -552,12 +552,62 @@ xlator_list_destroy (xlator_list_t *list) return 0; } - -int -xlator_tree_free (xlator_t *tree) +static int +xlator_members_free (xlator_t *xl) { volume_opt_list_t *vol_opt = NULL; volume_opt_list_t *tmp = NULL; + + if (!xl) + return 0; + + GF_FREE (xl->name); + GF_FREE (xl->type); + if (xl->dlhandle) + dlclose (xl->dlhandle); + if (xl->options) + dict_unref (xl->options); + + xlator_list_destroy (xl->children); + + xlator_list_destroy (xl->parents); + + list_for_each_entry_safe (vol_opt, tmp, &xl->volume_options, list) { + list_del_init (&vol_opt->list); + GF_FREE (vol_opt); + } + + return 0; +} + +/* This function destroys all the xlator members except for the + * xlator strcuture and its mem accounting field. + * + * If otherwise, it would destroy the master xlator object as well + * its mem accounting, which would mean after calling glusterfs_graph_destroy() + * there cannot be any reference to GF_FREE() from the master xlator, this is + * not possible because of the following dependencies: + * - glusterfs_ctx_t will have mem pools allocated by the master xlators + * - xlator objects will have references to those mem pools(g: dict) + * + * Ordering the freeing in any of the order will also not solve the dependency: + * - Freeing xlator objects(including memory accounting) before mem pools + * destruction will mean not use GF_FREE while destroying mem pools. + * - Freeing mem pools and then destroying xlator objects would lead to crashes + * when xlator tries to unref dict or other mem pool objects. + * + * Hence the way chosen out of this interdependency is to split xlator object + * free into two stages: + * - Free all the xlator members excpet for its mem accounting structure + * - Free all the mem accouting structures of xlator along with the xlator + * object itself. + * + * This two stages of destruction, is mainly required for glfs_fini(). + */ + +int +xlator_tree_free_members (xlator_t *tree) +{ xlator_t *trav = tree; xlator_t *prev = tree; @@ -568,18 +618,32 @@ xlator_tree_free (xlator_t *tree) while (prev) { trav = prev->next; - if (prev->dlhandle) - dlclose (prev->dlhandle); - dict_unref (prev->options); - GF_FREE (prev->name); - GF_FREE (prev->type); - xlator_list_destroy (prev->children); - xlator_list_destroy (prev->parents); - - list_for_each_entry_safe (vol_opt, tmp, &prev->volume_options, - list) { - list_del_init (&vol_opt->list); - GF_FREE (vol_opt); + xlator_members_free (prev); + prev = trav; + } + + return 0; +} + +int +xlator_tree_free_memacct (xlator_t *tree) +{ + xlator_t *trav = tree; + xlator_t *prev = tree; + int i = 0; + + if (!tree) { + gf_log ("parser", GF_LOG_ERROR, "Translator tree not found"); + return -1; + } + + while (prev) { + trav = prev->next; + if (prev->mem_acct.rec) { + for (i = 0; i < prev->mem_acct.num_types; i++) { + LOCK_DESTROY (&(prev->mem_acct.rec[i].lock)); + } + FREE (prev->mem_acct.rec); } GF_FREE (prev); prev = trav; @@ -588,7 +652,6 @@ xlator_tree_free (xlator_t *tree) return 0; } - void loc_wipe (loc_t *loc) { @@ -766,28 +829,10 @@ loc_is_root (loc_t *loc) int xlator_destroy (xlator_t *xl) { - volume_opt_list_t *vol_opt = NULL; - volume_opt_list_t *tmp = NULL; - if (!xl) return 0; - GF_FREE (xl->name); - GF_FREE (xl->type); - if (xl->dlhandle) - dlclose (xl->dlhandle); - if (xl->options) - dict_destroy (xl->options); - - xlator_list_destroy (xl->children); - - xlator_list_destroy (xl->parents); - - list_for_each_entry_safe (vol_opt, tmp, &xl->volume_options, list) { - list_del_init (&vol_opt->list); - GF_FREE (vol_opt); - } - + xlator_members_free (xl); GF_FREE (xl); return 0; diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index 0c4e820c2d3..c1813abe6a2 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -919,7 +919,8 @@ int xlator_init (xlator_t *this); int xlator_destroy (xlator_t *xl); int32_t xlator_tree_init (xlator_t *xl); -int32_t xlator_tree_free (xlator_t *xl); +int32_t xlator_tree_free_members (xlator_t *xl); +int32_t xlator_tree_free_memacct (xlator_t *xl); void xlator_tree_fini (xlator_t *xl); |