diff options
Diffstat (limited to 'libglusterfs/src/xlator.c')
| -rw-r--r-- | libglusterfs/src/xlator.c | 432 |
1 files changed, 234 insertions, 198 deletions
diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index cbbe8cf7f12..9a2582d45d5 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -8,12 +8,12 @@ cases as published by the Free Software Foundation. */ -#include "xlator.h" +#include "glusterfs/xlator.h" #include <dlfcn.h> #include <netdb.h> #include <fnmatch.h> -#include "defaults.h" -#include "libglusterfs-messages.h" +#include "glusterfs/defaults.h" +#include "glusterfs/libglusterfs-messages.h" #define SET_DEFAULT_FOP(fn) \ do { \ @@ -143,6 +143,7 @@ fill_defaults(xlator_t *xl) SET_DEFAULT_FOP(getspec); SET_DEFAULT_FOP(icreate); SET_DEFAULT_FOP(namelink); + SET_DEFAULT_FOP(copy_file_range); if (!xl->cbks) xl->cbks = &default_cbks; @@ -183,9 +184,11 @@ xlator_volopt_dynload(char *xlator_type, void **dl_handle, volume_opt_list_t *opt_list) { int ret = -1; + int flag = 0; char *name = NULL; void *handle = NULL; xlator_api_t *xlapi = NULL; + volume_option_t *opt = NULL; GF_VALIDATE_OR_GOTO("xlator", xlator_type, out); @@ -193,8 +196,10 @@ xlator_volopt_dynload(char *xlator_type, void **dl_handle, * need this check */ if (!strstr(xlator_type, "rpc-transport")) ret = gf_asprintf(&name, "%s/%s.so", XLATORDIR, xlator_type); - else + else { + flag = 1; ret = gf_asprintf(&name, "%s/%s.so", XLATORPARENTDIR, xlator_type); + } if (-1 == ret) { goto out; } @@ -205,34 +210,34 @@ xlator_volopt_dynload(char *xlator_type, void **dl_handle, handle = dlopen(name, RTLD_NOW); if (!handle) { - gf_msg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED, "%s", - dlerror()); + gf_smsg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED, "error=%s", + dlerror(), NULL); goto out; } - /* check new struct first, and then check this */ - xlapi = dlsym(handle, "xlator_api"); - if (!xlapi) { - gf_msg("xlator", GF_LOG_DEBUG, 0, LG_MSG_DLSYM_ERROR, - "dlsym(xlator_api) on %s. " - "Fall back to old symbols", - dlerror()); - /* This case is not an error for now, so allow it - to fall back to old methods. */ - opt_list->given_opt = dlsym(handle, "options"); - if (!opt_list->given_opt) { - dlerror(); - gf_msg("xlator", GF_LOG_ERROR, 0, LG_MSG_LOAD_FAILED, - "Failed to load xlator opt table"); + if (flag == 0) { + /* check new struct first, and then check this */ + xlapi = dlsym(handle, "xlator_api"); + if (!xlapi) { + gf_smsg("xlator", GF_LOG_ERROR, 0, LG_MSG_DLSYM_ERROR, "error=%s", + dlerror(), NULL); goto out; } - } else { + opt_list->given_opt = xlapi->options; if (!opt_list->given_opt) { - gf_msg("xlator", GF_LOG_ERROR, 0, LG_MSG_LOAD_FAILED, - "Failed to load xlator options table"); + gf_smsg("xlator", GF_LOG_ERROR, 0, LG_MSG_LOAD_FAILED, NULL); goto out; } + } else { + opt = dlsym(handle, "options"); + if (!opt) { + gf_smsg("xlator", GF_LOG_ERROR, 0, LG_MSG_DLSYM_ERROR, "error=%s", + dlerror(), NULL); + goto out; + } + + opt_list->given_opt = opt; } *dl_handle = handle; @@ -248,134 +253,29 @@ out: return ret; } -int -xlator_dynload_oldway(xlator_t *xl) -{ - int i = 0; - int ret = -1; - void *handle = NULL; - volume_opt_list_t *vol_opt = NULL; - class_methods_t *vtbl = NULL; - - handle = xl->dlhandle; - - xl->fops = dlsym(handle, "fops"); - if (!xl->fops) { - gf_msg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLSYM_ERROR, - "dlsym(fops) on %s", dlerror()); - goto out; - } - - xl->cbks = dlsym(handle, "cbks"); - if (!xl->cbks) { - gf_msg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLSYM_ERROR, - "dlsym(cbks) on %s", dlerror()); - goto out; - } - - /* - * If class_methods exists, its contents override any definitions of - * init or fini for that translator. Otherwise, we fall back to the - * older method of looking for init and fini directly. - */ - vtbl = dlsym(handle, "class_methods"); - if (vtbl) { - xl->init = vtbl->init; - xl->fini = vtbl->fini; - xl->reconfigure = vtbl->reconfigure; - xl->notify = vtbl->notify; - } else { - if (!(*VOID(&xl->init) = dlsym(handle, "init"))) { - gf_msg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLSYM_ERROR, - "dlsym(init) on %s", dlerror()); - goto out; - } - - if (!(*VOID(&(xl->fini)) = dlsym(handle, "fini"))) { - gf_msg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLSYM_ERROR, - "dlsym(fini) on %s", dlerror()); - goto out; - } - if (!(*VOID(&(xl->reconfigure)) = dlsym(handle, "reconfigure"))) { - gf_msg_trace("xlator", 0, - "dlsym(reconfigure) on %s " - "-- neglecting", - dlerror()); - } - if (!(*VOID(&(xl->notify)) = dlsym(handle, "notify"))) { - gf_msg_trace("xlator", 0, - "dlsym(notify) on %s -- " - "neglecting", - dlerror()); - } - } - - if (!(xl->dumpops = dlsym(handle, "dumpops"))) { - gf_msg_trace("xlator", 0, - "dlsym(dumpops) on %s -- " - "neglecting", - dlerror()); - } - - if (!(*VOID(&(xl->mem_acct_init)) = dlsym(handle, "mem_acct_init"))) { - gf_msg_trace(xl->name, 0, - "dlsym(mem_acct_init) on %s -- " - "neglecting", - dlerror()); - } - - vol_opt = GF_CALLOC(1, sizeof(volume_opt_list_t), - gf_common_mt_volume_opt_list_t); - - if (!vol_opt) { - goto out; - } - - INIT_LIST_HEAD(&vol_opt->list); - vol_opt->given_opt = dlsym(handle, "options"); - if (!vol_opt->given_opt) { - vol_opt->given_opt = default_options; - } - list_add_tail(&vol_opt->list, &xl->volume_options); - - /* make sure 'min' is set to high value, so it would be - properly set later */ - for (i = 0; i < GF_FOP_MAXVALUE; i++) { - xl->stats.interval.latencies[i].min = 0xffffffff; - } - - ret = 0; - -out: - return ret; -} - -int -xlator_dynload_newway(xlator_t *xl) +static int +xlator_dynload_apis(xlator_t *xl) { int ret = -1; void *handle = NULL; volume_opt_list_t *vol_opt = NULL; xlator_api_t *xlapi = NULL; + int i = 0; handle = xl->dlhandle; xlapi = dlsym(handle, "xlator_api"); if (!xlapi) { - gf_msg("xlator", GF_LOG_INFO, 0, LG_MSG_DLSYM_ERROR, - "dlsym(xlator_api) on %s. " - "Fall back to old symbols", - dlerror()); - /* This case is not an error for now, so allow it - to fall back to old methods. */ - ret = 1; + gf_smsg("xlator", GF_LOG_ERROR, 0, LG_MSG_DLSYM_ERROR, "dlsym=%s", + dlerror(), NULL); + ret = -1; goto out; } xl->fops = xlapi->fops; if (!xl->fops) { - gf_msg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLSYM_ERROR, - "%s: struct missing (fops)", xl->name); + gf_smsg("xlator", GF_LOG_WARNING, 0, LG_MSG_STRUCT_MISS, "name=%s", + xl->name, NULL); goto out; } @@ -386,8 +286,8 @@ xlator_dynload_newway(xlator_t *xl) xl->init = xlapi->init; if (!xl->init) { - gf_msg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLSYM_ERROR, - "%s: method missing (init)", xl->name); + gf_smsg("xlator", GF_LOG_WARNING, 0, LG_MSG_METHOD_MISS, "name=%s", + xl->name, NULL); goto out; } @@ -458,6 +358,10 @@ xlator_dynload_newway(xlator_t *xl) memcpy(xl->op_version, xlapi->op_version, sizeof(uint32_t) * GF_MAX_RELEASES); + for (i = 0; i < GF_FOP_MAXVALUE; i++) { + gf_latency_reset(&xl->stats.interval.latencies[i]); + } + ret = 0; out: return ret; @@ -485,21 +389,15 @@ xlator_dynload(xlator_t *xl) handle = dlopen(name, RTLD_NOW); if (!handle) { - gf_msg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED, "%s", - dlerror()); + gf_smsg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED, "error=%s", + dlerror(), NULL); goto out; } xl->dlhandle = handle; - ret = xlator_dynload_newway(xl); + ret = xlator_dynload_apis(xl); if (-1 == ret) goto out; - if (1 == ret) { - /* it means we don't find the new symbol in xlator code */ - ret = xlator_dynload_oldway(xl); - if (-1 == ret) - goto out; - } fill_defaults(xl); @@ -559,10 +457,8 @@ xlator_set_inode_lru_limit(xlator_t *this, void *data) if (this->itable) { if (!data) { - gf_msg(this->name, GF_LOG_WARNING, 0, LG_MSG_INVALID_ENTRY, - "input data is NULL. " - "Cannot update the lru limit of the inode" - " table. Continuing with older value"); + gf_smsg(this->name, GF_LOG_WARNING, 0, LG_MSG_INPUT_DATA_NULL, + NULL); goto out; } inode_lru_limit = *(int *)data; @@ -735,20 +631,16 @@ xlator_init(xlator_t *xl) xl->instance_name = NULL; GF_ATOMIC_INIT(xl->xprtrefcnt, 0); - GF_ATOMIC_INIT(xl->fd_cnt, 0); if (!xl->init) { - gf_msg(xl->name, GF_LOG_WARNING, 0, LG_MSG_INIT_FAILED, - "No init() found"); + gf_smsg(xl->name, GF_LOG_WARNING, 0, LG_MSG_INIT_FAILED, NULL); goto out; } ret = __xlator_init(xl); if (ret) { - gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_VOLUME_ERROR, - "Initialization of volume '%s' failed," - " review your volfile again", - xl->name); + gf_smsg(xl->name, GF_LOG_ERROR, 0, LG_MSG_VOLUME_ERROR, "name=%s", + xl->name, NULL); goto out; } @@ -781,6 +673,7 @@ xlator_fini_rec(xlator_t *xl) trav = trav->next; } + xl->cleanup_starting = 1; if (xl->init_succeeded) { if (xl->fini) { old_THIS = THIS; @@ -788,8 +681,14 @@ xlator_fini_rec(xlator_t *xl) xl->fini(xl); - if (xl->local_pool) + if (xl->local_pool) { mem_pool_destroy(xl->local_pool); + xl->local_pool = NULL; + } + if (xl->itable) { + inode_table_destroy(xl->itable); + xl->itable = NULL; + } THIS = old_THIS; } else { @@ -858,6 +757,19 @@ xlator_mem_acct_init(xlator_t *xl, int num_types) } void +xlator_mem_acct_unref(struct mem_acct *mem_acct) +{ + uint32_t i; + + if (GF_ATOMIC_DEC(mem_acct->refcnt) == 0) { + for (i = 0; i < mem_acct->num_types; i++) { + LOCK_DESTROY(&(mem_acct->rec[i].lock)); + } + FREE(mem_acct); + } +} + +void xlator_tree_fini(xlator_t *xl) { xlator_t *top = NULL; @@ -888,7 +800,6 @@ xlator_list_destroy(xlator_list_t *list) int xlator_memrec_free(xlator_t *xl) { - uint32_t i = 0; struct mem_acct *mem_acct = NULL; if (!xl) { @@ -897,13 +808,8 @@ xlator_memrec_free(xlator_t *xl) mem_acct = xl->mem_acct; if (mem_acct) { - for (i = 0; i < mem_acct->num_types; i++) { - LOCK_DESTROY(&(mem_acct->rec[i].lock)); - } - if (GF_ATOMIC_DEC(mem_acct->refcnt) == 0) { - FREE(mem_acct); - xl->mem_acct = NULL; - } + xlator_mem_acct_unref(mem_acct); + xl->mem_acct = NULL; } return 0; @@ -920,7 +826,7 @@ xlator_members_free(xlator_t *xl) GF_FREE(xl->name); GF_FREE(xl->type); - if (!(xl->ctx && xl->ctx->cmd_args.valgrind) && xl->dlhandle) + if (!(xl->ctx && xl->ctx->cmd_args.vgtool != _gf_none) && xl->dlhandle) dlclose(xl->dlhandle); if (xl->options) dict_unref(xl->options); @@ -970,8 +876,7 @@ xlator_tree_free_members(xlator_t *tree) xlator_t *prev = tree; if (!tree) { - gf_msg("parser", GF_LOG_ERROR, 0, LG_MSG_TREE_NOT_FOUND, - "Translator tree not found"); + gf_smsg("parser", GF_LOG_ERROR, 0, LG_MSG_TREE_NOT_FOUND, NULL); return -1; } @@ -991,8 +896,7 @@ xlator_tree_free_memacct(xlator_t *tree) xlator_t *prev = tree; if (!tree) { - gf_msg("parser", GF_LOG_ERROR, 0, LG_MSG_TREE_NOT_FOUND, - "Translator tree not found"); + gf_smsg("parser", GF_LOG_ERROR, 0, LG_MSG_TREE_NOT_FOUND, NULL); return -1; } @@ -1016,7 +920,6 @@ xlator_mem_free(xlator_t *xl) return 0; if (xl->options) { - dict_ref(xl->options); dict_unref(xl->options); xl->options = NULL; } @@ -1035,7 +938,7 @@ xlator_mem_free(xlator_t *xl) static void xlator_call_fini(xlator_t *this) { - if (!this || this->cleanup_starting) + if (!this || this->call_cleanup) return; this->cleanup_starting = 1; this->call_cleanup = 1; @@ -1054,6 +957,8 @@ xlator_mem_cleanup(xlator_t *this) xlator_list_t **trav_p = NULL; xlator_t *top = NULL; xlator_t *victim = NULL; + glusterfs_graph_t *graph = NULL; + gf_boolean_t graph_cleanup = _gf_false; if (this->call_cleanup || !this->ctx) return; @@ -1061,6 +966,12 @@ xlator_mem_cleanup(xlator_t *this) this->call_cleanup = 1; ctx = this->ctx; + inode_table = this->itable; + if (inode_table) { + inode_table_destroy(inode_table); + this->itable = NULL; + } + xlator_call_fini(trav); while (prev) { @@ -1069,12 +980,6 @@ xlator_mem_cleanup(xlator_t *this) prev = trav; } - inode_table = this->itable; - if (inode_table) { - inode_table_destroy(inode_table); - this->itable = NULL; - } - if (this->fini) { this->fini(this); } @@ -1084,17 +989,28 @@ xlator_mem_cleanup(xlator_t *this) if (ctx->active) { top = ctx->active->first; LOCK(&ctx->volfile_lock); - /* TODO here we have leak for xlator node in a graph */ - /* Need to move only top xlator from a graph */ for (trav_p = &top->children; *trav_p; trav_p = &(*trav_p)->next) { victim = (*trav_p)->xlator; if (victim->call_cleanup && !strcmp(victim->name, this->name)) { + graph_cleanup = _gf_true; (*trav_p) = (*trav_p)->next; break; } } UNLOCK(&ctx->volfile_lock); } + + if (graph_cleanup) { + prev = this; + graph = ctx->active; + pthread_mutex_lock(&graph->mutex); + while (prev) { + trav = prev->next; + GF_FREE(prev); + prev = trav; + } + pthread_mutex_unlock(&graph->mutex); + } } void @@ -1394,8 +1310,21 @@ xlator_destroy(xlator_t *xl) return 0; } +static int32_t +gf_bin_to_string(char *dst, size_t size, void *src, size_t len) +{ + if (len >= size) { + return EINVAL; + } + + memcpy(dst, src, len); + dst[len] = 0; + + return 0; +} + int -is_gf_log_command(xlator_t *this, const char *name, char *value) +is_gf_log_command(xlator_t *this, const char *name, char *value, size_t size) { xlator_t *trav = NULL; char key[1024] = { @@ -1407,7 +1336,11 @@ is_gf_log_command(xlator_t *this, const char *name, char *value) glusterfs_ctx_t *ctx = NULL; if (!strcmp("trusted.glusterfs.syslog", name)) { - ret = gf_string2boolean(value, &syslog_flag); + ret = gf_bin_to_string(key, sizeof(key), value, size); + if (ret != 0) { + goto out; + } + ret = gf_string2boolean(key, &syslog_flag); if (ret) { ret = EOPNOTSUPP; goto out; @@ -1423,7 +1356,12 @@ is_gf_log_command(xlator_t *this, const char *name, char *value) if (fnmatch("trusted.glusterfs*set-log-level", name, FNM_NOESCAPE)) goto out; - log_level = glusterd_check_log_level(value); + ret = gf_bin_to_string(key, sizeof(key), value, size); + if (ret != 0) { + goto out; + } + + log_level = glusterd_check_log_level(key); if (log_level == -1) { ret = EOPNOTSUPP; goto out; @@ -1431,9 +1369,9 @@ is_gf_log_command(xlator_t *this, const char *name, char *value) /* Some crude way to change the log-level of process */ if (!strcmp(name, "trusted.glusterfs.set-log-level")) { - gf_msg("glusterfs", gf_log_get_loglevel(), 0, LG_MSG_SET_LOG_LEVEL, - "setting log level to %d (old-value=%d)", log_level, - gf_log_get_loglevel()); + gf_smsg("glusterfs", gf_log_get_loglevel(), 0, LG_MSG_SET_LOG_LEVEL, + "new-value=%d", log_level, "old-value=%d", + gf_log_get_loglevel(), NULL); gf_log_set_loglevel(this->ctx, log_level); ret = 0; goto out; @@ -1441,9 +1379,9 @@ is_gf_log_command(xlator_t *this, const char *name, char *value) if (!strcmp(name, "trusted.glusterfs.fuse.set-log-level")) { /* */ - gf_msg(this->name, gf_log_get_xl_loglevel(this), 0, - LG_MSG_SET_LOG_LEVEL, "setting log level to %d (old-value=%d)", - log_level, gf_log_get_xl_loglevel(this)); + gf_smsg(this->name, gf_log_get_xl_loglevel(this), 0, + LG_MSG_SET_LOG_LEVEL, "new-value=%d", log_level, "old-value=%d", + gf_log_get_xl_loglevel(this), NULL); gf_log_set_xl_loglevel(this, log_level); ret = 0; goto out; @@ -1459,10 +1397,9 @@ is_gf_log_command(xlator_t *this, const char *name, char *value) while (trav) { snprintf(key, 1024, "trusted.glusterfs.%s.set-log-level", trav->name); if (fnmatch(name, key, FNM_NOESCAPE) == 0) { - gf_msg(trav->name, gf_log_get_xl_loglevel(trav), 0, - LG_MSG_SET_LOG_LEVEL, - "setting log level to %d (old-value=%d)", log_level, - gf_log_get_xl_loglevel(trav)); + gf_smsg(trav->name, gf_log_get_xl_loglevel(trav), 0, + LG_MSG_SET_LOG_LEVEL, "new-value%d", log_level, + "old-value=%d", gf_log_get_xl_loglevel(trav), NULL); gf_log_set_xl_loglevel(trav, log_level); ret = 0; } @@ -1494,9 +1431,7 @@ glusterd_check_log_level(const char *value) } if (log_level == -1) - gf_msg(THIS->name, GF_LOG_ERROR, 0, LG_MSG_INIT_FAILED, - "Invalid log-level. possible values are " - "DEBUG|WARNING|ERROR|CRITICAL|NONE|TRACE"); + gf_smsg(THIS->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_INIT, NULL); return log_level; } @@ -1555,3 +1490,104 @@ glusterfs_delete_volfile_checksum(glusterfs_ctx_t *ctx, const char *volfile_id) return 0; } + +/* + The function is required to take dict ref for every xlator at graph. + At the time of compare graph topology create a graph and populate + key values in the dictionary, after finished graph comparison we do destroy + the new graph.At the time of construct graph we don't take any reference + so to avoid dict leak at the of destroying graph due to ref counter underflow + we need to call dict_ref here. + +*/ + +void +gluster_graph_take_reference(xlator_t *tree) +{ + xlator_t *trav = tree; + xlator_t *prev = tree; + + if (!tree) { + gf_smsg("parser", GF_LOG_ERROR, 0, LG_MSG_TREE_NOT_FOUND, NULL); + return; + } + + while (prev) { + trav = prev->next; + if (prev->options) + dict_ref(prev->options); + prev = trav; + } + return; +} + +gf_boolean_t +mgmt_is_multiplexed_daemon(char *name) +{ + const char *mux_daemons[] = {"glustershd", NULL}; + int i; + + if (!name) + return _gf_false; + + for (i = 0; mux_daemons[i]; i++) { + if (!strcmp(name, mux_daemons[i])) + return _gf_true; + } + return _gf_false; +} + +gf_boolean_t +xlator_is_cleanup_starting(xlator_t *this) +{ + gf_boolean_t cleanup = _gf_false; + glusterfs_graph_t *graph = NULL; + xlator_t *xl = NULL; + + if (!this) { + gf_smsg("xlator", GF_LOG_WARNING, EINVAL, LG_MSG_OBJECT_NULL, "xlator", + NULL); + goto out; + } + + graph = this->graph; + if (!graph) { + gf_smsg("xlator", GF_LOG_WARNING, EINVAL, LG_MSG_GRAPH_NOT_SET, + "name=%s", this->name, NULL); + goto out; + } + + xl = graph->first; + if (xl && xl->cleanup_starting) + cleanup = _gf_true; +out: + return cleanup; +} + +int +graph_total_client_xlator(glusterfs_graph_t *graph) +{ + xlator_t *xl = NULL; + int count = 0; + + if (!graph) { + gf_smsg("xlator", GF_LOG_WARNING, EINVAL, LG_MSG_OBJECT_NULL, "graph", + NULL); + goto out; + } + + xl = graph->first; + if (!strcmp(xl->type, "protocol/server")) { + gf_msg_debug(xl->name, 0, "Return because it is a server graph"); + return 0; + } + + while (xl) { + if (strcmp(xl->type, "protocol/client") == 0) { + count++; + } + xl = xl->next; + } +out: + return count; +} |
