diff options
Diffstat (limited to 'libglusterfs/src/xlator.c')
| -rw-r--r-- | libglusterfs/src/xlator.c | 1347 |
1 files changed, 554 insertions, 793 deletions
diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index c2f585d03..a277c58a8 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2009 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> This file is part of GlusterFS. - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -28,791 +19,349 @@ #include <fnmatch.h> #include "defaults.h" - #define SET_DEFAULT_FOP(fn) do { \ - if (!xl->fops->fn) \ - xl->fops->fn = default_##fn; \ - } while (0) + if (!xl->fops->fn) \ + xl->fops->fn = default_##fn; \ + } while (0) #define SET_DEFAULT_CBK(fn) do { \ - if (!xl->cbks->fn) \ - xl->cbks->fn = default_##fn; \ - } while (0) + if (!xl->cbks->fn) \ + xl->cbks->fn = default_##fn; \ + } while (0) -#define GF_OPTION_LIST_EMPTY(_opt) (_opt->value[0] == NULL) - static void fill_defaults (xlator_t *xl) { - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return; - } + if (xl == NULL) { + gf_log_callingfn ("xlator", GF_LOG_WARNING, "invalid argument"); + return; + } - SET_DEFAULT_FOP (create); - SET_DEFAULT_FOP (open); - SET_DEFAULT_FOP (stat); - SET_DEFAULT_FOP (readlink); - SET_DEFAULT_FOP (mknod); - SET_DEFAULT_FOP (mkdir); - SET_DEFAULT_FOP (unlink); - SET_DEFAULT_FOP (rmdir); - SET_DEFAULT_FOP (symlink); - SET_DEFAULT_FOP (rename); - SET_DEFAULT_FOP (link); - SET_DEFAULT_FOP (truncate); - SET_DEFAULT_FOP (readv); - SET_DEFAULT_FOP (writev); - SET_DEFAULT_FOP (statfs); - SET_DEFAULT_FOP (flush); - SET_DEFAULT_FOP (fsync); - SET_DEFAULT_FOP (setxattr); - SET_DEFAULT_FOP (getxattr); - SET_DEFAULT_FOP (fsetxattr); - SET_DEFAULT_FOP (fgetxattr); - SET_DEFAULT_FOP (removexattr); - SET_DEFAULT_FOP (opendir); - SET_DEFAULT_FOP (readdir); - SET_DEFAULT_FOP (readdirp); - SET_DEFAULT_FOP (fsyncdir); - SET_DEFAULT_FOP (access); - SET_DEFAULT_FOP (ftruncate); - SET_DEFAULT_FOP (fstat); - SET_DEFAULT_FOP (lk); - SET_DEFAULT_FOP (inodelk); - SET_DEFAULT_FOP (finodelk); - SET_DEFAULT_FOP (entrylk); - SET_DEFAULT_FOP (fentrylk); - SET_DEFAULT_FOP (lookup); - SET_DEFAULT_FOP (rchecksum); - SET_DEFAULT_FOP (xattrop); - SET_DEFAULT_FOP (fxattrop); + SET_DEFAULT_FOP (create); + SET_DEFAULT_FOP (open); + SET_DEFAULT_FOP (stat); + SET_DEFAULT_FOP (readlink); + SET_DEFAULT_FOP (mknod); + SET_DEFAULT_FOP (mkdir); + SET_DEFAULT_FOP (unlink); + SET_DEFAULT_FOP (rmdir); + SET_DEFAULT_FOP (symlink); + SET_DEFAULT_FOP (rename); + SET_DEFAULT_FOP (link); + SET_DEFAULT_FOP (truncate); + SET_DEFAULT_FOP (readv); + SET_DEFAULT_FOP (writev); + SET_DEFAULT_FOP (statfs); + SET_DEFAULT_FOP (flush); + SET_DEFAULT_FOP (fsync); + SET_DEFAULT_FOP (setxattr); + SET_DEFAULT_FOP (getxattr); + SET_DEFAULT_FOP (fsetxattr); + SET_DEFAULT_FOP (fgetxattr); + SET_DEFAULT_FOP (removexattr); + SET_DEFAULT_FOP (fremovexattr); + SET_DEFAULT_FOP (opendir); + SET_DEFAULT_FOP (readdir); + SET_DEFAULT_FOP (readdirp); + SET_DEFAULT_FOP (fsyncdir); + SET_DEFAULT_FOP (access); + SET_DEFAULT_FOP (ftruncate); + SET_DEFAULT_FOP (fstat); + SET_DEFAULT_FOP (lk); + SET_DEFAULT_FOP (inodelk); + SET_DEFAULT_FOP (finodelk); + SET_DEFAULT_FOP (entrylk); + SET_DEFAULT_FOP (fentrylk); + SET_DEFAULT_FOP (lookup); + SET_DEFAULT_FOP (rchecksum); + SET_DEFAULT_FOP (xattrop); + SET_DEFAULT_FOP (fxattrop); SET_DEFAULT_FOP (setattr); SET_DEFAULT_FOP (fsetattr); + SET_DEFAULT_FOP (fallocate); + SET_DEFAULT_FOP (discard); + SET_DEFAULT_FOP (zerofill); SET_DEFAULT_FOP (getspec); - SET_DEFAULT_CBK (release); - SET_DEFAULT_CBK (releasedir); - SET_DEFAULT_CBK (forget); + SET_DEFAULT_CBK (release); + SET_DEFAULT_CBK (releasedir); + SET_DEFAULT_CBK (forget); - if (!xl->notify) - xl->notify = default_notify; + if (!xl->notify) + xl->notify = default_notify; if (!xl->mem_acct_init) xl->mem_acct_init = default_mem_acct_init; - return; + return; } -/* RFC 1123 & 952 */ -static char -valid_host_name (char *address, int length) -{ - int i = 0; - char ret = 1; - if ((length > 75) || (length == 1)) { - ret = 0; - goto out; - } +int +xlator_set_type_virtual (xlator_t *xl, const char *type) +{ + GF_VALIDATE_OR_GOTO ("xlator", xl, out); + GF_VALIDATE_OR_GOTO ("xlator", type, out); - if (!isalnum (address[length - 1])) { - ret = 0; - goto out; - } + xl->type = gf_strdup (type); - for (i = 0; i < length; i++) { - if (!isalnum (address[i]) && (address[i] != '.') - && (address[i] != '-')) { - ret = 0; - goto out; - } - } + if (xl->type) + return 0; out: - return ret; + return -1; } -static char -valid_ipv4_address (char *address, int length) + +int +xlator_volopt_dynload (char *xlator_type, void **dl_handle, + volume_opt_list_t *opt_list) { - int octets = 0; - int value = 0; - char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; - char ret = 1; - - tmp = gf_strdup (address); - prev = tmp; - prev = strtok_r (tmp, ".", &ptr); - - while (prev != NULL) - { - octets++; - value = strtol (prev, &endptr, 10); - if ((value > 255) || (value < 0) || (endptr != NULL)) { - ret = 0; - goto out; - } - - prev = strtok_r (NULL, ".", &ptr); - } + int ret = -1; + char *name = NULL; + void *handle = NULL; - if (octets != 4) { - ret = 0; + GF_VALIDATE_OR_GOTO ("xlator", xlator_type, out); + + ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xlator_type); + if (-1 == ret) { + gf_log ("xlator", GF_LOG_ERROR, "asprintf failed"); + goto out; } -out: - GF_FREE (tmp); - return ret; -} + ret = -1; -static char -valid_ipv6_address (char *address, int length) -{ - int hex_numbers = 0; - int value = 0; - char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; - char ret = 1; - - tmp = gf_strdup (address); - prev = strtok_r (tmp, ":", &ptr); - - while (prev != NULL) - { - hex_numbers++; - value = strtol (prev, &endptr, 16); - if ((value > 0xffff) || (value < 0) - || (endptr != NULL && *endptr != '\0')) { - ret = 0; - goto out; - } - - prev = strtok_r (NULL, ":", &ptr); + gf_log ("xlator", GF_LOG_TRACE, "attempt to load file %s", name); + + handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); + if (!handle) { + gf_log ("xlator", GF_LOG_WARNING, "%s", dlerror ()); + goto out; } - - if (hex_numbers > 8) { - ret = 0; + + if (!(opt_list->given_opt = dlsym (handle, "options"))) { + dlerror (); + gf_log ("xlator", GF_LOG_ERROR, + "Failed to load xlator opt table"); + goto out; } -out: - GF_FREE (tmp); + *dl_handle = handle; + + ret = 0; + out: + GF_FREE (name); + + gf_log ("xlator", GF_LOG_DEBUG, "Returning %d", ret); return ret; + } -static char -valid_internet_address (char *address) + +int +xlator_dynload (xlator_t *xl) { - char ret = 0; - int length = 0; + int ret = -1; + char *name = NULL; + void *handle = NULL; + volume_opt_list_t *vol_opt = NULL; + class_methods_t *vtbl = NULL; + + GF_VALIDATE_OR_GOTO ("xlator", xl, out); + + INIT_LIST_HEAD (&xl->volume_options); - if (address == NULL) { + ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xl->type); + if (-1 == ret) { + gf_log ("xlator", GF_LOG_ERROR, "asprintf failed"); goto out; } - length = strlen (address); - if (length == 0) { + ret = -1; + + gf_log ("xlator", GF_LOG_TRACE, "attempt to load file %s", name); + + handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); + if (!handle) { + gf_log ("xlator", GF_LOG_WARNING, "%s", dlerror ()); goto out; } + xl->dlhandle = handle; - if (valid_ipv4_address (address, length) - || valid_ipv6_address (address, length) - || valid_host_name (address, length)) { - ret = 1; + if (!(xl->fops = dlsym (handle, "fops"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(fops) on %s", + dlerror ()); + goto out; } -out: - return ret; -} + if (!(xl->cbks = dlsym (handle, "cbks"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(cbks) on %s", + dlerror ()); + goto out; + } -int -_volume_option_value_validate (xlator_t *xl, - data_pair_t *pair, - volume_option_t *opt) -{ - int i = 0; - int ret = -1; - uint64_t input_size = 0; - long long inputll = 0; - - /* Key is valid, validate the option */ - switch (opt->type) { - case GF_OPTION_TYPE_PATH: - { - if (strstr (pair->value->data, "../")) { - gf_log (xl->name, GF_LOG_ERROR, - "invalid path given '%s'", - pair->value->data); - ret = -1; + /* + * 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_log ("xlator", GF_LOG_WARNING, "dlsym(init) on %s", + dlerror ()); goto out; } - /* Make sure the given path is valid */ - if (pair->value->data[0] != '/') { - gf_log (xl->name, GF_LOG_WARNING, - "option %s %s: '%s' is not an " - "absolute path name", - pair->key, pair->value->data, - pair->value->data); - } - ret = 0; - } - break; - case GF_OPTION_TYPE_INT: - { - /* Check the range */ - if (gf_string2longlong (pair->value->data, - &inputll) != 0) { - gf_log (xl->name, GF_LOG_ERROR, - "invalid number format \"%s\" in " - "\"option %s\"", - pair->value->data, pair->key); - goto out; - } - - if ((opt->min == 0) && (opt->max == 0)) { - gf_log (xl->name, GF_LOG_DEBUG, - "no range check required for " - "'option %s %s'", - pair->key, pair->value->data); - ret = 0; - break; - } - if ((inputll < opt->min) || - (inputll > opt->max)) { - gf_log (xl->name, GF_LOG_WARNING, - "'%lld' in 'option %s %s' is out of " - "range [%"PRId64" - %"PRId64"]", - inputll, pair->key, - pair->value->data, - opt->min, opt->max); - } - ret = 0; - } - break; - case GF_OPTION_TYPE_SIZET: - { - /* Check the range */ - if (gf_string2bytesize (pair->value->data, - &input_size) != 0) { - gf_log (xl->name, GF_LOG_ERROR, - "invalid size format \"%s\" in " - "\"option %s\"", - pair->value->data, pair->key); - goto out; - } - - if ((opt->min == 0) && (opt->max == 0)) { - gf_log (xl->name, GF_LOG_DEBUG, - "no range check required for " - "'option %s %s'", - pair->key, pair->value->data); - ret = 0; - break; - } - if ((input_size < opt->min) || - (input_size > opt->max)) { - gf_log (xl->name, GF_LOG_ERROR, - "'%"PRId64"' in 'option %s %s' is " - "out of range [%"PRId64" - %"PRId64"]", - input_size, pair->key, - pair->value->data, - opt->min, opt->max); - } - ret = 0; - } - break; - case GF_OPTION_TYPE_BOOL: - { - /* Check if the value is one of - '0|1|on|off|no|yes|true|false|enable|disable' */ - gf_boolean_t bool_value; - if (gf_string2boolean (pair->value->data, - &bool_value) != 0) { - gf_log (xl->name, GF_LOG_ERROR, - "option %s %s: '%s' is not a valid " - "boolean value", - pair->key, pair->value->data, - pair->value->data); - goto out; - } - ret = 0; - } - break; - case GF_OPTION_TYPE_XLATOR: - { - /* Check if the value is one of the xlators */ - xlator_t *xlopt = xl; - while (xlopt->prev) - xlopt = xlopt->prev; - - while (xlopt) { - if (strcmp (pair->value->data, - xlopt->name) == 0) { - ret = 0; - break; - } - xlopt = xlopt->next; - } - if (!xlopt) { - gf_log (xl->name, GF_LOG_ERROR, - "option %s %s: '%s' is not a " - "valid volume name", - pair->key, pair->value->data, - pair->value->data); - } - ret = 0; - } - break; - case GF_OPTION_TYPE_STR: - { - /* Check if the '*str' is valid */ - if (GF_OPTION_LIST_EMPTY(opt)) { - ret = 0; + if (!(*VOID(&(xl->fini)) = dlsym (handle, "fini"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(fini) on %s", + dlerror ()); goto out; } + if (!(*VOID(&(xl->reconfigure)) = dlsym (handle, + "reconfigure"))) { + gf_log ("xlator", GF_LOG_TRACE, + "dlsym(reconfigure) on %s -- neglecting", + dlerror()); + } + if (!(*VOID(&(xl->notify)) = dlsym (handle, "notify"))) { + gf_log ("xlator", GF_LOG_TRACE, + "dlsym(notify) on %s -- neglecting", + dlerror ()); + } - for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && - opt->value[i]; i++) { - if (strcasecmp (opt->value[i], - pair->value->data) == 0) { - ret = 0; - break; - } - } - - if ((i == ZR_OPTION_MAX_ARRAY_SIZE) - || ((i < ZR_OPTION_MAX_ARRAY_SIZE) - && (!opt->value[i]))) { - /* enter here only if - * 1. reached end of opt->value array and haven't - * validated input - * OR - * 2. valid input list is less than - * ZR_OPTION_MAX_ARRAY_SIZE and input has not - * matched all possible input values. - */ - char given_array[4096] = {0,}; - for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && - opt->value[i]; i++) { - strcat (given_array, opt->value[i]); - strcat (given_array, ", "); - } - - gf_log (xl->name, GF_LOG_ERROR, - "option %s %s: '%s' is not valid " - "(possible options are %s)", - pair->key, pair->value->data, - pair->value->data, given_array); - - goto out; - } - } - break; - case GF_OPTION_TYPE_PERCENT: - { - uint32_t percent = 0; - - - /* Check if the value is valid percentage */ - if (gf_string2percent (pair->value->data, - &percent) != 0) { - gf_log (xl->name, GF_LOG_ERROR, - "invalid percent format \"%s\" " - "in \"option %s\"", - pair->value->data, pair->key); - goto out; - } - - if ((percent < 0) || (percent > 100)) { - gf_log (xl->name, GF_LOG_ERROR, - "'%d' in 'option %s %s' is out of " - "range [0 - 100]", - percent, pair->key, - pair->value->data); - } - ret = 0; - } - break; - case GF_OPTION_TYPE_PERCENT_OR_SIZET: - { - uint32_t percent = 0; - uint64_t input_size = 0; - - /* Check if the value is valid percentage */ - if (gf_string2percent (pair->value->data, - &percent) == 0) { - if (percent > 100) { - gf_log (xl->name, GF_LOG_DEBUG, - "value given was greater than 100, " - "assuming this is actually a size"); - if (gf_string2bytesize (pair->value->data, - &input_size) == 0) { - /* Check the range */ - if ((opt->min == 0) && - (opt->max == 0)) { - gf_log (xl->name, GF_LOG_DEBUG, - "no range check " - "required for " - "'option %s %s'", - pair->key, - pair->value->data); - // It is a size - ret = 0; - goto out; - } - if ((input_size < opt->min) || - (input_size > opt->max)) { - gf_log (xl->name, GF_LOG_ERROR, - "'%"PRId64"' in " - "'option %s %s' is out" - " of range [%"PRId64"" - "- %"PRId64"]", - input_size, pair->key, - pair->value->data, - opt->min, opt->max); - } - // It is a size - ret = 0; - goto out; - } else { - // It's not a percent or size - gf_log (xl->name, GF_LOG_ERROR, - "invalid number format \"%s\" " - "in \"option %s\"", - pair->value->data, pair->key); - } - - } - // It is a percent - ret = 0; - goto out; - } else { - if (gf_string2bytesize (pair->value->data, - &input_size) == 0) { - /* Check the range */ - if ((opt->min == 0) && (opt->max == 0)) { - gf_log (xl->name, GF_LOG_DEBUG, - "no range check required for " - "'option %s %s'", - pair->key, pair->value->data); - // It is a size - ret = 0; - goto out; - } - if ((input_size < opt->min) || - (input_size > opt->max)) { - gf_log (xl->name, GF_LOG_ERROR, - "'%"PRId64"' in 'option %s %s'" - " is out of range [%"PRId64" -" - " %"PRId64"]", - input_size, pair->key, - pair->value->data, - opt->min, opt->max); - } - } else { - // It's not a percent or size - gf_log (xl->name, GF_LOG_ERROR, - "invalid number format \"%s\" " - "in \"option %s\"", - pair->value->data, pair->key); - } - //It is a size - ret = 0; - goto out; - } - - } - break; - case GF_OPTION_TYPE_TIME: - { - uint32_t input_time = 0; - - /* Check if the value is valid percentage */ - if (gf_string2time (pair->value->data, - &input_time) != 0) { - gf_log (xl->name, - GF_LOG_ERROR, - "invalid time format \"%s\" in " - "\"option %s\"", - pair->value->data, pair->key); - goto out; - } - - if ((opt->min == 0) && (opt->max == 0)) { - gf_log (xl->name, GF_LOG_DEBUG, - "no range check required for " - "'option %s %s'", - pair->key, pair->value->data); - ret = 0; - goto out; - } - if ((input_time < opt->min) || - (input_time > opt->max)) { - gf_log (xl->name, GF_LOG_ERROR, - "'%"PRIu32"' in 'option %s %s' is " - "out of range [%"PRId64" - %"PRId64"]", - input_time, pair->key, - pair->value->data, - opt->min, opt->max); - } - ret = 0; - } - break; - case GF_OPTION_TYPE_DOUBLE: - { - double input_time = 0.0; - - /* Check if the value is valid double */ - if (gf_string2double (pair->value->data, - &input_time) != 0) { - gf_log (xl->name, - GF_LOG_ERROR, - "invalid time format \"%s\" in \"option %s\"", - pair->value->data, pair->key); - goto out; - } - - if (input_time < 0.0) { - gf_log (xl->name, - GF_LOG_ERROR, - "invalid time format \"%s\" in \"option %s\"", - pair->value->data, pair->key); - goto out; - } - - if ((opt->min == 0) && (opt->max == 0)) { - gf_log (xl->name, GF_LOG_DEBUG, - "no range check required for 'option %s %s'", - pair->key, pair->value->data); - ret = 0; - goto out; - } - ret = 0; - } - break; - case GF_OPTION_TYPE_INTERNET_ADDRESS: - { - if (valid_internet_address (pair->value->data)) { - ret = 0; - } else { - gf_log (xl->name, GF_LOG_ERROR, "internet address '%s'" - " does not conform to standards.", - pair->value->data); - goto out; - } - } - break; - case GF_OPTION_TYPE_ANY: - /* NO CHECK */ - ret = 0; - break; - } - -out: - return ret; -} + } -int -validate_xlator_volume_options (xlator_t *xl, volume_option_t *opt) -{ - int i = 0; - int ret = -1; - int index = 0; - volume_option_t *trav = NULL; - data_pair_t *pairs = NULL; - - if (!opt) { - ret = 0; - goto out; - } + if (!(xl->dumpops = dlsym (handle, "dumpops"))) { + gf_log ("xlator", GF_LOG_TRACE, + "dlsym(dumpops) on %s -- neglecting", dlerror ()); + } - /* First search for not supported options, if any report error */ - pairs = xl->options->members_list; - while (pairs) { - ret = -1; - for (index = 0; - opt[index].key && opt[index].key[0] ; index++) { - trav = &(opt[index]); - for (i = 0 ; - (i < ZR_VOLUME_MAX_NUM_KEY) && - trav->key[i]; i++) { - /* Check if the key is valid */ - if (fnmatch (trav->key[i], - pairs->key, FNM_NOESCAPE) == 0) { - ret = 0; - break; - } - } - if (!ret) { - if (i) { - gf_log (xl->name, GF_LOG_WARNING, - "option '%s' is deprecated, " - "preferred is '%s', continuing" - " with correction", - trav->key[i], trav->key[0]); - /* TODO: some bytes lost */ - pairs->key = gf_strdup (trav->key[0]); - } - break; - } - } - if (!ret) { - ret = _volume_option_value_validate (xl, pairs, trav); - if (-1 == ret) { - goto out; - } - } - - pairs = pairs->next; - } - - ret = 0; - out: - return ret; -} + if (!(*VOID(&(xl->mem_acct_init)) = dlsym (handle, "mem_acct_init"))) { + gf_log (xl->name, GF_LOG_TRACE, + "dlsym(mem_acct_init) on %s -- neglecting", + dlerror ()); + } -int32_t -xlator_set_type (xlator_t *xl, - const char *type) -{ - int ret = 0; - char *name = NULL; - void *handle = NULL; - volume_opt_list_t *vol_opt = NULL; - - if (xl == NULL || type == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return -1; - } + vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), + gf_common_mt_volume_opt_list_t); - xl->type = gf_strdup (type); + if (!vol_opt) { + goto out; + } - ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, type); - if (-1 == ret) { - gf_log ("xlator", GF_LOG_ERROR, "asprintf failed"); - return -1; + if (!(vol_opt->given_opt = dlsym (handle, "options"))) { + dlerror (); + gf_log (xl->name, GF_LOG_TRACE, + "Strict option validation not enforced -- neglecting"); } + INIT_LIST_HEAD (&vol_opt->list); + list_add_tail (&vol_opt->list, &xl->volume_options); - gf_log ("xlator", GF_LOG_TRACE, "attempt to load file %s", name); + fill_defaults (xl); - handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); - if (!handle) { - gf_log ("xlator", GF_LOG_DEBUG, "%s", dlerror ()); - return -1; - } - xl->dlhandle = handle; + ret = 0; - if (!(xl->fops = dlsym (handle, "fops"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(fops) on %s", - dlerror ()); - return -1; - } +out: + GF_FREE (name); + return ret; +} - if (!(xl->cbks = dlsym (handle, "cbks"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(cbks) on %s", - dlerror ()); - return -1; - } - if (!(xl->init = dlsym (handle, "init"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(init) on %s", - dlerror ()); - return -1; - } +int +xlator_set_type (xlator_t *xl, const char *type) +{ + int ret = 0; - if (!(xl->fini = dlsym (handle, "fini"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(fini) on %s", - dlerror ()); - return -1; - } + ret = xlator_set_type_virtual (xl, type); + if (!ret) + ret = xlator_dynload (xl); - if (!(xl->notify = dlsym (handle, "notify"))) { - gf_log ("xlator", GF_LOG_DEBUG, - "dlsym(notify) on %s -- neglecting", dlerror ()); - } + return ret; +} - if (!(xl->dumpops = dlsym (handle, "dumpops"))) { - gf_log ("xlator", GF_LOG_DEBUG, - "dlsym(dumpops) on %s -- neglecting", dlerror ()); - } - if (!(xl->mem_acct_init = dlsym (handle, "mem_acct_init"))) { - gf_log (xl->name, GF_LOG_DEBUG, - "dlsym(mem_acct_init) on %s -- neglecting", - dlerror ()); - } +void +xlator_foreach (xlator_t *this, + void (*fn)(xlator_t *each, + void *data), + void *data) +{ + xlator_t *first = NULL; + xlator_t *old_THIS = NULL; - INIT_LIST_HEAD (&xl->volume_options); + GF_VALIDATE_OR_GOTO ("xlator", this, out); + GF_VALIDATE_OR_GOTO ("xlator", fn, out); - vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), - gf_common_mt_volume_opt_list_t); + first = this; - if (!(vol_opt->given_opt = dlsym (handle, "options"))) { - dlerror (); - gf_log (xl->name, GF_LOG_DEBUG, - "Strict option validation not enforced -- neglecting"); - } - list_add_tail (&vol_opt->list, &xl->volume_options); + while (first->prev) + first = first->prev; + + while (first) { + old_THIS = THIS; + THIS = first; + + fn (first, data); - fill_defaults (xl); + THIS = old_THIS; + first = first->next; + } - GF_FREE (name); - return 0; +out: + return; } void -xlator_foreach (xlator_t *this, - void (*fn)(xlator_t *each, - void *data), - void *data) +xlator_foreach_depth_first (xlator_t *this, + void (*fn)(xlator_t *each, void *data), + void *data) { - xlator_t *first = NULL; - - if (this == NULL || fn == NULL || data == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return; - } - - first = this; + xlator_list_t *subv = NULL; - while (first->prev) - first = first->prev; + subv = this->children; - while (first) { - fn (first, data); - first = first->next; + while (subv) { + xlator_foreach_depth_first (subv->xlator, fn, data); + subv = subv->next; } + + fn (this, data); } xlator_t * xlator_search_by_name (xlator_t *any, const char *name) { - xlator_t *search = NULL; + xlator_t *search = NULL; - if (any == NULL || name == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return NULL; - } + GF_VALIDATE_OR_GOTO ("xlator", any, out); + GF_VALIDATE_OR_GOTO ("xlator", name, out); - search = any; + search = any; - while (search->prev) - search = search->prev; + while (search->prev) + search = search->prev; - while (search) { - if (!strcmp (search->name, name)) - break; - search = search->next; - } + while (search) { + if (!strcmp (search->name, name)) + break; + search = search->next; + } - return search; +out: + return search; } - static int __xlator_init(xlator_t *xl) { @@ -833,20 +382,15 @@ __xlator_init(xlator_t *xl) int xlator_init (xlator_t *xl) { - int32_t ret = 0; - - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return 0; - } + int32_t ret = -1; - ret = -1; + GF_VALIDATE_OR_GOTO ("xlator", xl, out); if (xl->mem_acct_init) xl->mem_acct_init (xl); if (!xl->init) { - gf_log (xl->name, GF_LOG_DEBUG, "No init() found"); + gf_log (xl->name, GF_LOG_WARNING, "No init() found"); goto out; } @@ -864,40 +408,49 @@ xlator_init (xlator_t *xl) ret = 0; out: - return ret; + return ret; } static void xlator_fini_rec (xlator_t *xl) { - xlator_list_t *trav = NULL; + xlator_list_t *trav = NULL; + xlator_t *old_THIS = NULL; - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return; - } + GF_VALIDATE_OR_GOTO ("xlator", xl, out); - trav = xl->children; + trav = xl->children; - while (trav) { - if (!trav->xlator->init_succeeded) { - break; - } + while (trav) { + if (!trav->xlator->init_succeeded) { + break; + } - xlator_fini_rec (trav->xlator); - gf_log (trav->xlator->name, GF_LOG_DEBUG, "fini done"); - trav = trav->next; - } + xlator_fini_rec (trav->xlator); + gf_log (trav->xlator->name, GF_LOG_DEBUG, "fini done"); + trav = trav->next; + } - if (xl->init_succeeded) { - if (xl->fini) { - xl->fini (xl); - } else { - gf_log (xl->name, GF_LOG_DEBUG, "No fini() found"); - } - xl->init_succeeded = 0; - } + if (xl->init_succeeded) { + if (xl->fini) { + old_THIS = THIS; + THIS = xl; + + xl->fini (xl); + + if (xl->local_pool) + mem_pool_destroy (xl->local_pool); + + THIS = old_THIS; + } else { + gf_log (xl->name, GF_LOG_DEBUG, "No fini() found"); + } + xl->init_succeeded = 0; + } + +out: + return; } @@ -924,18 +477,17 @@ xlator_mem_acct_init (xlator_t *xl, int num_types) int i = 0; int ret = 0; - if (!gf_mem_acct_is_enabled()) - return 0; - if (!xl) return -1; + if (!xl->ctx->mem_acct_enable) + return 0; + xl->mem_acct.num_types = num_types; - xl->mem_acct.rec = calloc(num_types, sizeof(struct mem_acct_rec)); + xl->mem_acct.rec = CALLOC(num_types, sizeof(struct mem_acct_rec)); if (!xl->mem_acct.rec) { - gf_log("xlator", GF_LOG_ERROR, "Out of Memory"); return -1; } @@ -946,47 +498,72 @@ xlator_mem_acct_init (xlator_t *xl, int num_types) } } - gf_log(xl->name, GF_LOG_DEBUG, "Allocated mem_acct_rec for %d types", - num_types); - return 0; } + void xlator_tree_fini (xlator_t *xl) { - xlator_t *top = NULL; + xlator_t *top = NULL; - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return; - } + GF_VALIDATE_OR_GOTO ("xlator", xl, out); + + top = xl; + xlator_fini_rec (top); + +out: + return; +} - top = xl; - xlator_fini_rec (top); +int +xlator_list_destroy (xlator_list_t *list) +{ + xlator_list_t *next = NULL; + + while (list) { + next = list->next; + GF_FREE (list); + list = next; + } + + return 0; } int xlator_tree_free (xlator_t *tree) { - xlator_t *trav = tree, *prev = tree; - - if (!tree) { - gf_log ("parser", GF_LOG_ERROR, "Translator tree not found"); - return -1; - } - - while (prev) { - trav = prev->next; - dict_destroy (prev->options); - GF_FREE (prev->name); - GF_FREE (prev->type); - GF_FREE (prev); - prev = trav; - } - - return 0; + volume_opt_list_t *vol_opt = NULL; + volume_opt_list_t *tmp = NULL; + xlator_t *trav = tree; + xlator_t *prev = tree; + + if (!tree) { + gf_log ("parser", GF_LOG_ERROR, "Translator tree not found"); + return -1; + } + + 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); + } + GF_FREE (prev); + prev = trav; + } + + return 0; } @@ -1001,67 +578,138 @@ loc_wipe (loc_t *loc) GF_FREE ((char *)loc->path); loc->path = NULL; } - + if (loc->parent) { inode_unref (loc->parent); loc->parent = NULL; } -} + memset (loc, 0, sizeof (*loc)); +} int -loc_copy (loc_t *dst, loc_t *src) +loc_path (loc_t *loc, const char *bname) { - int ret = -1; + int ret = 0; - dst->ino = src->ino; + if (loc->path) + goto out; - if (src->inode) - dst->inode = inode_ref (src->inode); + ret = -1; - if (src->parent) - dst->parent = inode_ref (src->parent); + if (bname && !strlen (bname)) + bname = NULL; - dst->path = gf_strdup (src->path); + if (!bname) + goto inode_path; - if (!dst->path) - goto out; + if (loc->parent && !uuid_is_null (loc->parent->gfid)) { + ret = inode_path (loc->parent, bname, (char**)&loc->path); + } else if (!uuid_is_null (loc->pargfid)) { + ret = gf_asprintf ((char**)&loc->path, INODE_PATH_FMT"/%s", + uuid_utoa (loc->pargfid), bname); + } - dst->name = strrchr (dst->path, '/'); - if (dst->name) - dst->name++; + if (loc->path) + goto out; - ret = 0; +inode_path: + if (loc->inode && !uuid_is_null (loc->inode->gfid)) { + ret = inode_path (loc->inode, NULL, (char **)&loc->path); + } else if (!uuid_is_null (loc->gfid)) { + ret = gf_asprintf ((char**)&loc->path, INODE_PATH_FMT, + uuid_utoa (loc->gfid)); + } out: - return ret; + return ret; } +void +loc_gfid (loc_t *loc, uuid_t gfid) +{ + if (!gfid) + goto out; + uuid_clear (gfid); + + if (!loc) + goto out; + else if (!uuid_is_null (loc->gfid)) + uuid_copy (gfid, loc->gfid); + else if (loc->inode && (!uuid_is_null (loc->inode->gfid))) + uuid_copy (gfid, loc->inode->gfid); +out: + return; +} + +char* +loc_gfid_utoa (loc_t *loc) +{ + uuid_t gfid; + loc_gfid (loc, gfid); + return uuid_utoa (gfid); +} int -xlator_list_destroy (xlator_list_t *list) +loc_copy (loc_t *dst, loc_t *src) { - xlator_list_t *next = NULL; + int ret = -1; - while (list) { - next = list->next; - GF_FREE (list); - list = next; + GF_VALIDATE_OR_GOTO ("xlator", dst, err); + GF_VALIDATE_OR_GOTO ("xlator", src, err); + + uuid_copy (dst->gfid, src->gfid); + uuid_copy (dst->pargfid, src->pargfid); + uuid_copy (dst->gfid, src->gfid); + + if (src->inode) + dst->inode = inode_ref (src->inode); + + if (src->parent) + dst->parent = inode_ref (src->parent); + + if (src->path) { + dst->path = gf_strdup (src->path); + + if (!dst->path) + goto out; + + if (src->name) + dst->name = strrchr (dst->path, '/'); + if (dst->name) + dst->name++; } - return 0; + ret = 0; +out: + if (ret == -1) + loc_wipe (dst); + +err: + return ret; } +gf_boolean_t +loc_is_root (loc_t *loc) +{ + if (loc && __is_root_gfid (loc->gfid)) { + return _gf_true; + } else if (loc && loc->inode && __is_root_gfid (loc->inode->gfid)) { + return _gf_true; + } + return _gf_false; +} int xlator_destroy (xlator_t *xl) { + volume_opt_list_t *vol_opt = NULL; + volume_opt_list_t *tmp = NULL; + if (!xl) return 0; - if (xl->name) - GF_FREE (xl->name); - if (xl->type) - GF_FREE (xl->type); + GF_FREE (xl->name); + GF_FREE (xl->type); if (xl->dlhandle) dlclose (xl->dlhandle); if (xl->options) @@ -1071,7 +719,120 @@ xlator_destroy (xlator_t *xl) 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); + } + GF_FREE (xl); return 0; } + + +int +is_gf_log_command (xlator_t *this, const char *name, char *value) +{ + xlator_t *trav = NULL; + char key[1024] = {0,}; + int ret = -1; + int log_level = -1; + gf_boolean_t syslog_flag = 0; + glusterfs_ctx_t *ctx = NULL; + + if (!strcmp ("trusted.glusterfs.syslog", name)) { + ret = gf_string2boolean (value, &syslog_flag); + if (ret) { + ret = EOPNOTSUPP; + goto out; + } + if (syslog_flag) + gf_log_enable_syslog (); + else + gf_log_disable_syslog (); + + goto out; + } + + if (fnmatch ("trusted.glusterfs*set-log-level", name, FNM_NOESCAPE)) + goto out; + + log_level = glusterd_check_log_level (value); + if (log_level == -1) { + ret = EOPNOTSUPP; + goto out; + } + + /* Some crude way to change the log-level of process */ + if (!strcmp (name, "trusted.glusterfs.set-log-level")) { + /* */ + gf_log ("glusterfs", gf_log_get_loglevel(), + "setting log level to %d (old-value=%d)", + log_level, gf_log_get_loglevel()); + gf_log_set_loglevel (log_level); + ret = 0; + goto out; + } + + if (!strcmp (name, "trusted.glusterfs.fuse.set-log-level")) { + /* */ + gf_log (this->name, gf_log_get_xl_loglevel (this), + "setting log level to %d (old-value=%d)", + log_level, gf_log_get_xl_loglevel (this)); + gf_log_set_xl_loglevel (this, log_level); + ret = 0; + goto out; + } + + ctx = this->ctx; + if (!ctx) + goto out; + if (!ctx->active) + goto out; + trav = ctx->active->top; + + while (trav) { + snprintf (key, 1024, "trusted.glusterfs.%s.set-log-level", + trav->name); + if (fnmatch (name, key, FNM_NOESCAPE) == 0) { + gf_log (trav->name, gf_log_get_xl_loglevel (trav), + "setting log level to %d (old-value=%d)", + log_level, gf_log_get_xl_loglevel (trav)); + gf_log_set_xl_loglevel (trav, log_level); + ret = 0; + } + trav = trav->next; + } +out: + return ret; +} + + +int +glusterd_check_log_level (const char *value) +{ + int log_level = -1; + + if (!strcasecmp (value, "CRITICAL")) { + log_level = GF_LOG_CRITICAL; + } else if (!strcasecmp (value, "ERROR")) { + log_level = GF_LOG_ERROR; + } else if (!strcasecmp (value, "WARNING")) { + log_level = GF_LOG_WARNING; + } else if (!strcasecmp (value, "INFO")) { + log_level = GF_LOG_INFO; + } else if (!strcasecmp (value, "DEBUG")) { + log_level = GF_LOG_DEBUG; + } else if (!strcasecmp (value, "TRACE")) { + log_level = GF_LOG_TRACE; + } else if (!strcasecmp (value, "NONE")) { + log_level = GF_LOG_NONE; + } + + if (log_level == -1) + gf_log (THIS->name, GF_LOG_ERROR, "Invalid log-level. possible values " + "are DEBUG|WARNING|ERROR|CRITICAL|NONE|TRACE"); + + return log_level; +} + |
