diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-volgen.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 3523 |
1 files changed, 2918 insertions, 605 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index d5c5d5bdb..f42d596ba 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -1,22 +1,12 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> - This file is part of GlusterFS. - - GlusterFS is GF_FREE software; you can redistribute it and/or modify - it under the terms of the GNU Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ + Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + 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 #define _CONFIG_H @@ -24,6 +14,13 @@ #endif #include <fnmatch.h> +#include <sys/wait.h> +#include <dlfcn.h> + +#if (HAVE_LIB_XML) +#include <libxml/encoding.h> +#include <libxml/xmlwriter.h> +#endif #include "xlator.h" #include "glusterd.h" @@ -31,161 +28,18 @@ #include "logging.h" #include "dict.h" #include "graph-utils.h" +#include "glusterd-store.h" +#include "glusterd-hooks.h" #include "trie.h" #include "glusterd-mem-types.h" -#include "cli1.h" +#include "cli1-xdr.h" #include "glusterd-volgen.h" #include "glusterd-op-sm.h" +#include "glusterd-utils.h" +#include "run.h" +#include "options.h" - -/* dispatch table for VOLUME SET - * ----------------------------- - * - * Format of entries: - * - * First field is the <key>, for the purpose of looking it up - * in volume dictionary. Each <key> is of the format "<domain>.<specifier>". - * - * Second field is <voltype>. - * - * Third field is <option>, if its unset, it's assumed to be - * the same as <specifier>. - * - * Fourth field is <value>. In this context they are used to specify - * a default. That is, even the volume dict doesn't have a value, - * we procced as if the default value were set for it. - * - * There are two type of entries: basic and special. - * - * - Basic entries are the ones where the <option> does _not_ start with - * the bang! character ('!'). - * - * In their case, <option> is understood as an option for an xlator of - * type <voltype>. Their effect is to copy over the volinfo->dict[<key>] - * value to all graph nodes of type <voltype> (if such a value is set). - * - * You are free to add entries of this type, they will become functional - * just by being present in the table. - * - * - Special entries where the <option> starts with the bang!. - * - * They are not applied to all graphs during generation, and you cannot - * extend them in a trivial way which could be just picked up. Better - * not touch them unless you know what you do. - * - * "NODOC" entries are not part of the public interface and are subject - * to change at any time. - * - * Another kind of grouping for options, according to visibility: - * - * - Exported: one which is used in the code. These are characterized by - * being used a macro as <key> (of the format VKEY_..., defined in - * glusterd-volgen.h - * - * - Non-exported: the rest; these have string literal <keys>. - * - * Adhering to this policy, option name changes shall be one-liners. - * - */ -typedef enum { DOC, NO_DOC, GLOBAL_DOC, GLOBAL_NO_DOC } option_type_t; - - -struct volopt_map_entry { - char *key; - char *voltype; - char *option; - char *value; - option_type_t type; - uint32_t flags; -}; - -static struct volopt_map_entry glusterd_volopt_map[] = { - - {"cluster.lookup-unhashed", "cluster/distribute", NULL, NULL, NO_DOC, 0 }, - {"cluster.min-free-disk", "cluster/distribute", NULL, NULL, NO_DOC, 0 }, - - {"cluster.entry-change-log", "cluster/replicate", NULL, NULL, NO_DOC, 0 }, - {"cluster.read-subvolume", "cluster/replicate", NULL, NULL, NO_DOC, 0 }, - {"cluster.background-self-heal-count", "cluster/replicate", NULL, NULL, NO_DOC, 0 }, - {"cluster.metadata-self-heal", "cluster/replicate", NULL, NULL, NO_DOC, 0 }, - {"cluster.data-self-heal", "cluster/replicate", NULL, NULL, NO_DOC, 0 }, - {"cluster.entry-self-heal", "cluster/replicate", NULL, NULL, NO_DOC, 0 }, - {"cluster.strict-readdir", "cluster/replicate", NULL, NULL, NO_DOC, 0 }, - {"cluster.self-heal-window-size", "cluster/replicate", "data-self-heal-window-size", NULL, DOC, 0}, - {"cluster.data-change-log", "cluster/replicate", NULL, NULL, NO_DOC, 0 }, - {"cluster.metadata-change-log", "cluster/replicate", NULL, NULL, NO_DOC, 0 }, - {"cluster.data-self-heal-algorithm", "cluster/replicate", "data-self-heal-algorithm", NULL,DOC, 0}, - - {"cluster.stripe-block-size", "cluster/stripe", "block-size", NULL, DOC, 0}, - - {VKEY_DIAG_LAT_MEASUREMENT, "debug/io-stats", "latency-measurement", "off", NO_DOC, 0 }, - {"diagnostics.dump-fd-stats", "debug/io-stats", NULL, NULL, NO_DOC, 0 }, - {VKEY_DIAG_CNT_FOP_HITS, "debug/io-stats", "count-fop-hits", "off", NO_DOC, 0 }, - {"diagnostics.brick-log-level", "debug/io-stats", "!log-level", NULL, DOC, 0}, - {"diagnostics.client-log-level", "debug/io-stats", "!log-level", NULL, DOC, 0}, - - {"performance.cache-max-file-size", "performance/io-cache", "max-file-size", NULL, DOC, 0}, - {"performance.cache-min-file-size", "performance/io-cache", "min-file-size", NULL, DOC, 0}, - {"performance.cache-refresh-timeout", "performance/io-cache", "cache-timeout", NULL, DOC, 0}, - {"performance.cache-priority", "performance/io-cache", "priority", NULL, DOC, 0}, - {"performance.cache-size", "performance/io-cache", NULL, NULL, NO_DOC, 0 }, - {"performance.cache-size", "performance/quick-read", NULL, NULL, NO_DOC, 0 }, - {"performance.flush-behind", "performance/write-behind", "flush-behind", NULL, DOC, 0}, - - {"performance.io-thread-count", "performance/io-threads", "thread-count", DOC, 0}, - - {"performance.disk-usage-limit", "performance/quota", NULL, NULL, NO_DOC, 0 }, - {"performance.min-free-disk-limit", "performance/quota", NULL, NULL, NO_DOC, 0 }, - - {"performance.write-behind-window-size", "performance/write-behind", "cache-size", NULL, DOC}, - - {"network.frame-timeout", "protocol/client", NULL, NULL, NO_DOC, 0 }, - {"network.ping-timeout", "protocol/client", NULL, NULL, NO_DOC, 0 }, - {"network.inode-lru-limit", "protocol/server", NULL, NULL, NO_DOC, 0 }, - - {"auth.allow", "protocol/server", "!server-auth", "*", DOC, 0}, - {"auth.reject", "protocol/server", "!server-auth", NULL, DOC, 0}, - - {"transport.keepalive", "protocol/server", "transport.socket.keepalive", NULL, NO_DOC, 0}, - {"server.allow-insecure", "protocol/server", "rpc-auth-allow-insecure", NULL, NO_DOC, 0}, - - {"performance.write-behind", "performance/write-behind", "!perf", "on", NO_DOC, 0}, - {"performance.read-ahead", "performance/read-ahead", "!perf", "on", NO_DOC, 0}, - {"performance.io-cache", "performance/io-cache", "!perf", "on", NO_DOC, 0}, - {"performance.quick-read", "performance/quick-read", "!perf", "on", NO_DOC, 0}, - {VKEY_PERF_STAT_PREFETCH, "performance/stat-prefetch", "!perf", "on", NO_DOC, 0}, - - {VKEY_MARKER_XTIME, "features/marker", "xtime", "off", NO_DOC, OPT_FLAG_FORCE}, - {VKEY_MARKER_XTIME, "features/marker", "!xtime", "off", NO_DOC, OPT_FLAG_FORCE}, - - {"nfs.enable-ino32", "nfs/server", "nfs.enable-ino32", NULL, GLOBAL_DOC, 0}, - {"nfs.mem-factor", "nfs/server", "nfs.mem-factor", NULL, GLOBAL_DOC, 0}, - {"nfs.export-dirs", "nfs/server", "nfs3.export-dirs", NULL, GLOBAL_DOC, 0}, - {"nfs.export-volumes", "nfs/server", "nfs3.export-volumes", NULL, GLOBAL_DOC, 0}, - {"nfs.addr-namelookup", "nfs/server", "rpc-auth.addr.namelookup", NULL, GLOBAL_DOC, 0}, - {"nfs.dynamic-volumes", "nfs/server", "nfs.dynamic-volumes", NULL, GLOBAL_DOC, 0}, - {"nfs.register-with-portmap", "nfs/server", "rpc.register-with-portmap", NULL, GLOBAL_DOC, 0}, - {"nfs.port", "nfs/server", "nfs.port", NULL, GLOBAL_DOC, 0}, - - {"nfs.rpc-auth-unix", "nfs/server", "!nfs.rpc-auth-auth-unix", NULL, DOC, 0}, - {"nfs.rpc-auth-null", "nfs/server", "!nfs.rpc-auth-auth-null", NULL, DOC, 0}, - {"nfs.rpc-auth-allow", "nfs/server", "!nfs.rpc-auth.addr.allow", NULL, DOC, 0}, - {"nfs.rpc-auth-reject", "nfs/server", "!nfs.rpc-auth.addr.reject", NULL, DOC, 0}, - {"nfs.ports-insecure", "nfs/server", "!nfs.auth.ports.insecure", NULL, DOC, 0}, - - {"nfs.trusted-sync", "nfs/server", "!nfs-trusted-sync", NULL, DOC, 0}, - {"nfs.trusted-write", "nfs/server", "!nfs-trusted-write", NULL, DOC, 0}, - {"nfs.volume-access", "nfs/server", "!nfs-volume-access", NULL, DOC, 0}, - {"nfs.export-dir", "nfs/server", "!nfs-export-dir", NULL, DOC, 0}, - {"nfs.disable", "nfs/server", "!nfs-disable", NULL, DOC, 0}, - - {VKEY_FEATURES_QUOTA, "features/marker", "quota", "off", NO_DOC, OPT_FLAG_FORCE}, - {VKEY_FEATURES_LIMIT_USAGE, "features/quota", "limit-set", NULL, NO_DOC, 0}, - {"features.quota-timeout", "features/quota", "timeout", "0", NO_DOC, 0}, - {NULL, } -}; - - +extern struct volopt_map_entry glusterd_volopt_map[]; /********************************************* * @@ -194,7 +48,20 @@ static struct volopt_map_entry glusterd_volopt_map[] = { *********************************************/ +struct volgen_graph { + char **errstr; + glusterfs_graph_t graph; +}; +typedef struct volgen_graph volgen_graph_t; + +static void +set_graph_errstr (volgen_graph_t *graph, const char *str) +{ + if (!graph->errstr) + return; + *graph->errstr = gf_strdup (str); +} static xlator_t * xlator_instantiate_va (const char *type, const char *format, va_list arg) @@ -222,20 +89,20 @@ xlator_instantiate_va (const char *type, const char *format, va_list arg) xl->name = volname; INIT_LIST_HEAD (&xl->volume_options); + xl->ctx = THIS->ctx; + return xl; error: gf_log ("", GF_LOG_ERROR, "creating xlator of type %s failed", type); - if (volname) - GF_FREE (volname); + GF_FREE (volname); if (xl) xlator_destroy (xl); return NULL; } -#ifdef __not_used_as_of_now_ static xlator_t * xlator_instantiate (const char *type, const char *format, ...) { @@ -248,7 +115,6 @@ xlator_instantiate (const char *type, const char *format, ...) return xl; } -#endif static int volgen_xlator_link (xlator_t *pxl, xlator_t *cxl) @@ -266,13 +132,13 @@ volgen_xlator_link (xlator_t *pxl, xlator_t *cxl) } static int -volgen_graph_link (glusterfs_graph_t *graph, xlator_t *xl) +volgen_graph_link (volgen_graph_t *graph, xlator_t *xl) { int ret = 0; /* no need to care about graph->top here */ - if (graph->first) - ret = volgen_xlator_link (xl, graph->first); + if (graph->graph.first) + ret = volgen_xlator_link (xl, graph->graph.first); if (ret == -1) { gf_log ("", GF_LOG_ERROR, "failed to add graph entry %s", xl->name); @@ -284,7 +150,7 @@ volgen_graph_link (glusterfs_graph_t *graph, xlator_t *xl) } static xlator_t * -volgen_graph_add_as (glusterfs_graph_t *graph, const char *type, +volgen_graph_add_as (volgen_graph_t *graph, const char *type, const char *format, ...) { va_list arg; @@ -302,13 +168,13 @@ volgen_graph_add_as (glusterfs_graph_t *graph, const char *type, return NULL; } else - glusterfs_graph_set_first (graph, xl); + glusterfs_graph_set_first (&graph->graph, xl); return xl; } static xlator_t * -volgen_graph_add_nolink (glusterfs_graph_t *graph, const char *type, +volgen_graph_add_nolink (volgen_graph_t *graph, const char *type, const char *format, ...) { va_list arg; @@ -321,13 +187,13 @@ volgen_graph_add_nolink (glusterfs_graph_t *graph, const char *type, if (!xl) return NULL; - glusterfs_graph_set_first (graph, xl); + glusterfs_graph_set_first (&graph->graph, xl); return xl; } static xlator_t * -volgen_graph_add (glusterfs_graph_t *graph, char *type, char *volname) +volgen_graph_add (volgen_graph_t *graph, char *type, char *volname) { char *shorttype = NULL; @@ -359,10 +225,17 @@ xlator_set_option (xlator_t *xl, char *key, char *value) return dict_set_dynstr (xl->options, key, dval); } +static int +xlator_get_option (xlator_t *xl, char *key, char **value) +{ + GF_ASSERT (xl); + return dict_get_str (xl->options, key, value); +} + static inline xlator_t * -first_of (glusterfs_graph_t *graph) +first_of (volgen_graph_t *graph) { - return (xlator_t *)graph->first; + return (xlator_t *)graph->graph.first; } @@ -490,10 +363,9 @@ volopt_trie_section (int lvl, char **patt, char *word, char **hint, int hints) GF_ASSERT (hints <= 2); nodevec.cnt = hints; ret = trie_measure_vec (trie, word, &nodevec); - if (ret || !nodevec.nodes[0]) - trie_destroy (trie); + if (!ret && nodevec.nodes[0]) + ret = process_nodevec (&nodevec, hint); - ret = process_nodevec (&nodevec, hint); trie_destroy (trie); return ret; @@ -544,8 +416,7 @@ volopt_trie (char *key, char **hint) } out: - if (patt[0]) - GF_FREE (patt[0]); + GF_FREE (patt[0]); if (ret) *hint = NULL; @@ -562,12 +433,12 @@ volopt_trie (char *key, char **hint) **************************/ -typedef int (*volgen_opthandler_t) (glusterfs_graph_t *graph, +typedef int (*volgen_opthandler_t) (volgen_graph_t *graph, struct volopt_map_entry *vme, void *param); struct opthandler_data { - glusterfs_graph_t *graph; + volgen_graph_t *graph; volgen_opthandler_t handler; struct volopt_map_entry *vme; gf_boolean_t found; @@ -577,26 +448,21 @@ struct opthandler_data { void *param; }; -#define pattern_match_options 0 - - -static void -process_option (dict_t *dict, char *key, data_t *value, void *param) +static int +process_option (char *key, data_t *value, void *param) { struct opthandler_data *odt = param; struct volopt_map_entry vme = {0,}; if (odt->rv) - return; -#if pattern_match_options - if (fnmatch (odt->vme->key, key, 0) != 0) - return; -#endif + return 0; odt->found = _gf_true; vme.key = key; vme.voltype = odt->vme->voltype; vme.option = odt->vme->option; + vme.op_version = odt->vme->op_version; + if (!vme.option) { vme.option = strrchr (key, '.'); if (vme.option) @@ -610,10 +476,11 @@ process_option (dict_t *dict, char *key, data_t *value, void *param) vme.value = value->data; odt->rv = odt->handler (odt->graph, &vme, odt->param); + return 0; } static int -volgen_graph_set_options_generic (glusterfs_graph_t *graph, dict_t *dict, +volgen_graph_set_options_generic (volgen_graph_t *graph, dict_t *dict, void *param, volgen_opthandler_t handler) { struct volopt_map_entry *vme = NULL; @@ -630,14 +497,10 @@ volgen_graph_set_options_generic (glusterfs_graph_t *graph, dict_t *dict, odt.found = _gf_false; odt.data_t_fake = _gf_false; -#if pattern_match_options - dict_foreach (dict, process_option, &odt); -#else data = dict_get (dict, vme->key); if (data) - process_option (dict, vme->key, data, &odt); -#endif + process_option (vme->key, data, &odt); if (odt.rv) return odt.rv; @@ -651,8 +514,7 @@ volgen_graph_set_options_generic (glusterfs_graph_t *graph, dict_t *dict, * in this context */ odt.data_t_fake = _gf_true; - process_option (NULL, vme->key, (data_t *)vme->value, - &odt); + process_option (vme->key, (data_t *)vme->value, &odt); if (odt.rv) return odt.rv; } @@ -662,36 +524,46 @@ volgen_graph_set_options_generic (glusterfs_graph_t *graph, dict_t *dict, } static int -basic_option_handler (glusterfs_graph_t *graph, struct volopt_map_entry *vme, - void *param) +no_filter_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, + void *param) { xlator_t *trav; int ret = 0; - if (vme->option[0] == '!') - return 0; - for (trav = first_of (graph); trav; trav = trav->next) { if (strcmp (trav->type, vme->voltype) != 0) continue; ret = xlator_set_option (trav, vme->option, vme->value); if (ret) - return -1; + break; } + return ret; +} - return 0; +static int +basic_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, + void *param) +{ + int ret = 0; + + if (vme->option[0] == '!') + goto out; + + ret = no_filter_option_handler (graph, vme, param); +out: + return ret; } static int -volgen_graph_set_options (glusterfs_graph_t *graph, dict_t *dict) +volgen_graph_set_options (volgen_graph_t *graph, dict_t *dict) { return volgen_graph_set_options_generic (graph, dict, NULL, &basic_option_handler); } static int -optget_option_handler (glusterfs_graph_t *graph, struct volopt_map_entry *vme, +optget_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, void *param) { struct volopt_map_entry *vme2 = param; @@ -702,6 +574,108 @@ optget_option_handler (glusterfs_graph_t *graph, struct volopt_map_entry *vme, return 0; } +static glusterd_server_xlator_t +get_server_xlator (char *xlator) +{ + glusterd_server_xlator_t subvol = GF_XLATOR_NONE; + + if (strcmp (xlator, "posix") == 0) + subvol = GF_XLATOR_POSIX; + if (strcmp (xlator, "acl") == 0) + subvol = GF_XLATOR_ACL; + if (strcmp (xlator, "locks") == 0) + subvol = GF_XLATOR_LOCKS; + if (strcmp (xlator, "io-threads") == 0) + subvol = GF_XLATOR_IOT; + if (strcmp (xlator, "index") == 0) + subvol = GF_XLATOR_INDEX; + if (strcmp (xlator, "marker") == 0) + subvol = GF_XLATOR_MARKER; + if (strcmp (xlator, "io-stats") == 0) + subvol = GF_XLATOR_IO_STATS; + if (strcmp (xlator, "bd") == 0) + subvol = GF_XLATOR_BD; + + return subvol; +} + +static glusterd_client_xlator_t +get_client_xlator (char *xlator) +{ + glusterd_client_xlator_t subvol = GF_CLNT_XLATOR_NONE; + + if (strcmp (xlator, "client") == 0) + subvol = GF_CLNT_XLATOR_FUSE; + + return subvol; +} + +static int +debugxl_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, + void *param) +{ + char *volname = NULL; + gf_boolean_t enabled = _gf_false; + + volname = param; + + if (strcmp (vme->option, "!debug") != 0) + return 0; + + if (!strcmp (vme->key , "debug.trace") || + !strcmp (vme->key, "debug.error-gen")) { + if (get_server_xlator (vme->value) == GF_XLATOR_NONE && + get_client_xlator (vme->value) == GF_CLNT_XLATOR_NONE) + return 0; + else + goto add_graph; + } + + if (gf_string2boolean (vme->value, &enabled) == -1) + return -1; + if (!enabled) + return 0; + +add_graph: + if (volgen_graph_add (graph, vme->voltype, volname)) + return 0; + else + return -1; +} + +int +check_and_add_debug_xl (volgen_graph_t *graph, dict_t *set_dict, char *volname, + char *xlname) +{ + int ret = 0; + char *value_str = NULL; + + ret = dict_get_str (set_dict, "debug.trace", &value_str); + if (!ret) { + if (strcmp (xlname, value_str) == 0) { + ret = volgen_graph_set_options_generic (graph, set_dict, volname, + &debugxl_option_handler); + if (ret) + goto out; + } + } + + ret = dict_get_str (set_dict, "debug.error-gen", &value_str); + if (!ret) { + if (strcmp (xlname, value_str) == 0) { + ret = volgen_graph_set_options_generic (graph, set_dict, volname, + &debugxl_option_handler); + if (ret) + goto out; + } + } + + ret = 0; + +out: + return ret; +} + /* This getter considers defaults also. */ static int volgen_dict_get (dict_t *dict, char *key, char **value) @@ -765,7 +739,7 @@ int glusterd_volinfo_get_boolean (glusterd_volinfo_t *volinfo, char *key) { char *val = NULL; - gf_boolean_t boo = _gf_false; + gf_boolean_t enabled = _gf_false; int ret = 0; ret = glusterd_volinfo_get (volinfo, key, &val); @@ -773,14 +747,14 @@ glusterd_volinfo_get_boolean (glusterd_volinfo_t *volinfo, char *key) return -1; if (val) - ret = gf_string2boolean (val, &boo); + ret = gf_string2boolean (val, &enabled); if (ret) { gf_log ("", GF_LOG_ERROR, "value for %s option is not valid", key); return -1; } - return boo; + return enabled; } gf_boolean_t @@ -790,20 +764,7 @@ glusterd_check_voloption_flags (char *key, int32_t flags) struct volopt_map_entry *vmep = NULL; int ret = 0; - if (!strchr (key, '.')) { - ret = option_complete (key, &completion); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); - return _gf_false; - } - - if (!completion) { - gf_log ("", GF_LOG_ERROR, "option %s does not exist", - key); - return _gf_false; - } - } - + COMPLETE_OPTION(key, completion, ret); for (vmep = glusterd_volopt_map; vmep->key; vmep++) { if (strcmp (vmep->key, key) == 0) { if (vmep->flags & flags) @@ -823,20 +784,7 @@ glusterd_check_globaloption (char *key) struct volopt_map_entry *vmep = NULL; int ret = 0; - if (!strchr (key, '.')) { - ret = option_complete (key, &completion); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); - return _gf_false; - } - - if (!completion) { - gf_log ("", GF_LOG_ERROR, "option %s does not exist", - key); - return _gf_false; - } - } - + COMPLETE_OPTION(key, completion, ret); for (vmep = glusterd_volopt_map; vmep->key; vmep++) { if (strcmp (vmep->key, key) == 0) { if ((vmep->type == GLOBAL_DOC) || @@ -857,20 +805,7 @@ glusterd_check_localoption (char *key) struct volopt_map_entry *vmep = NULL; int ret = 0; - if (!strchr (key, '.')) { - ret = option_complete (key, &completion); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); - return _gf_false; - } - - if (!completion) { - gf_log ("", GF_LOG_ERROR, "option %s does not exist", - key); - return _gf_false; - } - } - + COMPLETE_OPTION(key, completion, ret); for (vmep = glusterd_volopt_map; vmep->key; vmep++) { if (strcmp (vmep->key, key) == 0) { if ((vmep->type == DOC) || @@ -891,20 +826,7 @@ glusterd_check_voloption (char *key) struct volopt_map_entry *vmep = NULL; int ret = 0; - if (!strchr (key, '.')) { - ret = option_complete (key, &completion); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); - return _gf_false; - } - - if (!completion) { - gf_log ("", GF_LOG_ERROR, "option %s does not exist", - key); - return _gf_false; - } - } - + COMPLETE_OPTION(key, completion, ret); for (vmep = glusterd_volopt_map; vmep->key; vmep++) { if (strcmp (vmep->key, key) == 0) { if ((vmep->type == DOC) || @@ -922,20 +844,20 @@ glusterd_check_voloption (char *key) int glusterd_check_option_exists (char *key, char **completion) { - dict_t *dict = NULL; struct volopt_map_entry vme = {0,}; struct volopt_map_entry *vmep = NULL; int ret = 0; + xlator_t *this = THIS; (void)vme; (void)vmep; - (void)dict; if (!strchr (key, '.')) { if (completion) { ret = option_complete (key, completion); if (ret) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); + gf_log (this->name, GF_LOG_ERROR, + "Out of memory"); return -1; } @@ -948,80 +870,154 @@ glusterd_check_option_exists (char *key, char **completion) return 0; } -#if !pattern_match_options for (vmep = glusterd_volopt_map; vmep->key; vmep++) { if (strcmp (vmep->key, key) == 0) { ret = 1; break; } } -#else - vme.key = key; - /* We are getting a bit anal here to avoid typing - * fnmatch one more time. Orthogonality foremost! - * The internal logic of looking up in the volopt_map table - * should be coded exactly once. - * - * [[Ha-ha-ha, so now if I ever change the internals then I'll - * have to update the fnmatch in this comment also :P ]] - */ - dict = get_new_dict (); - if (!dict || dict_set_str (dict, key, "")) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); + if (ret || !completion) + return ret; - return -1; + trie: + ret = volopt_trie (key, completion); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Some error occurred during keyword hinting"); } - ret = volgen_graph_set_options_generic (NULL, dict, &vme, - &optget_option_handler); - dict_destroy (dict); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); + return ret; +} - return -1; +char* +glusterd_get_trans_type_rb (gf_transport_type ttype) +{ + char *trans_type = NULL; + + switch (ttype) { + case GF_TRANSPORT_RDMA: + gf_asprintf (&trans_type, "rdma"); + break; + case GF_TRANSPORT_TCP: + case GF_TRANSPORT_BOTH_TCP_RDMA: + gf_asprintf (&trans_type, "tcp"); + break; + default: + gf_log (THIS->name, GF_LOG_ERROR, "Unknown " + "transport type"); } - ret = !!vme.value; -#endif + return trans_type; +} - if (ret || !completion) - return ret; +static int +_xl_link_children (xlator_t *parent, xlator_t *children, size_t child_count) +{ + xlator_t *trav = NULL; + size_t seek = 0; + int ret = -1; - trie: - ret = volopt_trie (key, completion); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Some error occured during keyword hinting"); + if (child_count == 0) + goto out; + seek = child_count; + for (trav = children; --seek; trav = trav->next); + for (; child_count--; trav = trav->prev) { + ret = volgen_xlator_link (parent, trav); + if (ret) + goto out; } - + ret = 0; +out: return ret; } static int -volgen_graph_merge_sub (glusterfs_graph_t *dgraph, glusterfs_graph_t *sgraph) +volgen_graph_merge_sub (volgen_graph_t *dgraph, volgen_graph_t *sgraph, + size_t child_count) { xlator_t *trav = NULL; + int ret = 0; - GF_ASSERT (dgraph->first); + GF_ASSERT (dgraph->graph.first); - if (volgen_xlator_link (first_of (dgraph), first_of (sgraph)) == -1) - return -1; + ret = _xl_link_children (first_of (dgraph), first_of (sgraph), + child_count); + if (ret) + goto out; for (trav = first_of (dgraph); trav->next; trav = trav->next); - trav->next = sgraph->first; + trav->next = first_of (sgraph); trav->next->prev = trav; - dgraph->xl_count += sgraph->xl_count; + dgraph->graph.xl_count += sgraph->graph.xl_count; - return 0; +out: + return ret; +} + +static void +volgen_apply_filters (char *orig_volfile) +{ + DIR *filterdir = NULL; + struct dirent entry = {0,}; + struct dirent *next = NULL; + char *filterpath = NULL; + struct stat statbuf = {0,}; + + filterdir = opendir(FILTERDIR); + if (!filterdir) { + return; + } + + while ((readdir_r(filterdir,&entry,&next) == 0) && next) { + if (!strncmp(entry.d_name,".",sizeof(entry.d_name))) { + continue; + } + if (!strncmp(entry.d_name,"..",sizeof(entry.d_name))) { + continue; + } + /* + * d_type isn't guaranteed to be present/valid on all systems, + * so do an explicit stat instead. + */ + if (gf_asprintf(&filterpath,"%s/%.*s",FILTERDIR, + sizeof(entry.d_name), entry.d_name) == (-1)) { + continue; + } + /* Deliberately use stat instead of lstat to allow symlinks. */ + if (stat(filterpath,&statbuf) == (-1)) { + goto free_fp; + } + if (!S_ISREG(statbuf.st_mode)) { + goto free_fp; + } + /* + * We could check the mode in statbuf directly, or just skip + * this entirely and check for EPERM after exec fails, but this + * is cleaner. + */ + if (access(filterpath,X_OK) != 0) { + goto free_fp; + } + if (runcmd(filterpath,orig_volfile,NULL)) { + gf_log("",GF_LOG_ERROR,"failed to run filter %.*s", + (int)sizeof(entry.d_name), entry.d_name); + } +free_fp: + GF_FREE(filterpath); + } } static int -volgen_write_volfile (glusterfs_graph_t *graph, char *filename) +volgen_write_volfile (volgen_graph_t *graph, char *filename) { - char *ftmp = NULL; - FILE *f = NULL; + char *ftmp = NULL; + FILE *f = NULL; + int fd = 0; + xlator_t *this = NULL; + + this = THIS; if (gf_asprintf (&ftmp, "%s.tmp", filename) == -1) { ftmp = NULL; @@ -1029,15 +1025,35 @@ volgen_write_volfile (glusterfs_graph_t *graph, char *filename) goto error; } + fd = creat (ftmp, S_IRUSR | S_IWUSR); + if (fd < 0) { + gf_log (this->name, GF_LOG_ERROR, "%s", + strerror (errno)); + goto error; + } + + close (fd); + f = fopen (ftmp, "w"); if (!f) goto error; - if (glusterfs_graph_print_file (f, graph) == -1) + if (glusterfs_graph_print_file (f, &graph->graph) == -1) goto error; - if (fclose (f) == -1) + if (fclose (f) != 0) { + gf_log (THIS->name, GF_LOG_ERROR, "fclose on the file %s " + "failed (%s)", ftmp, strerror (errno)); + /* + * Even though fclose has failed here, we have to set f to NULL. + * Otherwise when the code path goes to error, there again we + * try to close it which might cause undefined behavior such as + * process crash. + */ + f = NULL; goto error; + } + f = NULL; if (rename (ftmp, filename) == -1) @@ -1045,22 +1061,24 @@ volgen_write_volfile (glusterfs_graph_t *graph, char *filename) GF_FREE (ftmp); + volgen_apply_filters(filename); + return 0; error: - if (ftmp) - GF_FREE (ftmp); + GF_FREE (ftmp); if (f) fclose (f); - gf_log ("", GF_LOG_ERROR, "failed to create volfile %s", filename); + gf_log (this->name, GF_LOG_ERROR, + "failed to create volfile %s", filename); return -1; } static void -volgen_graph_free (glusterfs_graph_t *graph) +volgen_graph_free (volgen_graph_t *graph) { xlator_t *trav = NULL; xlator_t *trav_old = NULL; @@ -1077,9 +1095,9 @@ volgen_graph_free (glusterfs_graph_t *graph) } static int -build_graph_generic (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, +build_graph_generic (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, dict_t *mod_dict, void *param, - int (*builder) (glusterfs_graph_t *graph, + int (*builder) (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, dict_t *set_dict, void *param)) { @@ -1090,10 +1108,11 @@ build_graph_generic (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, set_dict = dict_copy (volinfo->dict, NULL); if (!set_dict) return -1; - dict_copy (mod_dict, set_dict); - /* XXX dict_copy swallows errors */ - } else + dict_copy (mod_dict, set_dict); + /* XXX dict_copy swallows errors */ + } else { set_dict = volinfo->dict; + } ret = builder (graph, volinfo, set_dict, param); if (!ret) @@ -1105,10 +1124,24 @@ build_graph_generic (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, return ret; } +static gf_transport_type +transport_str_to_type (char *tt) +{ + gf_transport_type type = GF_TRANSPORT_TCP; + + if (!strcmp ("tcp", tt)) + type = GF_TRANSPORT_TCP; + else if (!strcmp ("rdma", tt)) + type = GF_TRANSPORT_RDMA; + else if (!strcmp ("tcp,rdma", tt)) + type = GF_TRANSPORT_BOTH_TCP_RDMA; + return type; +} + static void -get_vol_transport_type (glusterd_volinfo_t *volinfo, char *tt) +transport_type_to_str (gf_transport_type type, char *tt) { - switch (volinfo->transport_type) { + switch (type) { case GF_TRANSPORT_RDMA: strcpy (tt, "rdma"); break; @@ -1121,8 +1154,56 @@ get_vol_transport_type (glusterd_volinfo_t *volinfo, char *tt) } } +static void +get_vol_transport_type (glusterd_volinfo_t *volinfo, char *tt) +{ + transport_type_to_str (volinfo->transport_type, tt); +} + +static void +get_vol_nfs_transport_type (glusterd_volinfo_t *volinfo, char *tt) +{ + if (volinfo->nfs_transport_type == GF_TRANSPORT_BOTH_TCP_RDMA) { + gf_log ("", GF_LOG_ERROR, "%s:nfs transport cannot be both" + " tcp and rdma", volinfo->volname); + GF_ASSERT (0); + } + transport_type_to_str (volinfo->nfs_transport_type, tt); +} + +/* gets the volinfo, dict, a character array for filling in + * the transport type and a boolean option which says whether + * the transport type is required for nfs or not. If its not + * for nfs, then it is considered as the client transport + * and client transport type is filled in the character array + */ +static void +get_transport_type (glusterd_volinfo_t *volinfo, dict_t *set_dict, + char *transt, gf_boolean_t is_nfs) +{ + int ret = -1; + char *tt = NULL; + char *key = NULL; + typedef void (*transport_type) (glusterd_volinfo_t *volinfo, char *tt); + transport_type get_transport; + + if (is_nfs == _gf_false) { + key = "client-transport-type"; + get_transport = get_vol_transport_type; + } else { + key = "nfs.transport-type"; + get_transport = get_vol_nfs_transport_type; + } + + ret = dict_get_str (set_dict, key, &tt); + if (ret) + get_transport (volinfo, transt); + if (!ret) + strcpy (transt, tt); +} + static int -server_auth_option_handler (glusterfs_graph_t *graph, +server_auth_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, void *param) { xlator_t *xl = NULL; @@ -1154,14 +1235,15 @@ server_auth_option_handler (glusterfs_graph_t *graph, } static int -loglevel_option_handler (glusterfs_graph_t *graph, +loglevel_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, void *param) { char *role = param; struct volopt_map_entry vme2 = {0,}; - if (strcmp (vme->option, "!log-level") != 0 || - !strstr (vme->key, role)) + if ( (strcmp (vme->option, "!client-log-level") != 0 && + strcmp (vme->option, "!brick-log-level") != 0) + || !strstr (vme->key, role)) return 0; memcpy (&vme2, vme, sizeof (vme2)); @@ -1171,11 +1253,11 @@ loglevel_option_handler (glusterfs_graph_t *graph, } static int -server_check_marker_off (struct volopt_map_entry *vme, +server_check_marker_off (volgen_graph_t *graph, struct volopt_map_entry *vme, glusterd_volinfo_t *volinfo) { - gf_boolean_t bool = _gf_false; - int ret = 0; + gf_boolean_t enabled = _gf_false; + int ret = 0; GF_ASSERT (volinfo); GF_ASSERT (vme); @@ -1183,8 +1265,8 @@ server_check_marker_off (struct volopt_map_entry *vme, if (strcmp (vme->option, "!xtime") != 0) return 0; - ret = gf_string2boolean (vme->value, &bool); - if (ret || bool) + ret = gf_string2boolean (vme->value, &enabled); + if (ret || enabled) goto out; ret = glusterd_volinfo_get_boolean (volinfo, VKEY_MARKER_XTIME); @@ -1195,13 +1277,16 @@ server_check_marker_off (struct volopt_map_entry *vme, } if (ret) { - bool = _gf_false; - ret = glusterd_check_gsync_running (volinfo, &bool); + enabled = _gf_false; + ret = glusterd_check_gsync_running (volinfo, &enabled); - if (bool) { - gf_log ("", GF_LOG_WARNING, "Gsync sessions active" + if (enabled) { + gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" "for the volume %s, cannot disable marker " ,volinfo->volname); + set_graph_errstr (graph, + VKEY_MARKER_XTIME" cannot be disabled " + "while "GEOREP" sessions exist"); ret = -1; goto out; } @@ -1221,7 +1306,98 @@ server_check_marker_off (struct volopt_map_entry *vme, } static int -server_spec_option_handler (glusterfs_graph_t *graph, +sys_loglevel_option_handler (volgen_graph_t *graph, + struct volopt_map_entry *vme, + void *param) +{ + char *role = NULL; + struct volopt_map_entry vme2 = {0,}; + + role = (char *) param; + + if (strcmp (vme->option, "!sys-log-level") != 0 || + !strstr (vme->key, role)) + return 0; + + memcpy (&vme2, vme, sizeof (vme2)); + vme2.option = "sys-log-level"; + + return basic_option_handler (graph, &vme2, NULL); +} + +static int +logger_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, + void *param) +{ + char *role = NULL; + struct volopt_map_entry vme2 = {0,}; + + role = (char *) param; + + if (strcmp (vme->option, "!logger") != 0 || + !strstr (vme->key, role)) + return 0; + + memcpy (&vme2, vme, sizeof (vme2)); + vme2.option = "logger"; + + return basic_option_handler (graph, &vme2, NULL); +} + +static int +log_format_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, + void *param) +{ + char *role = NULL; + struct volopt_map_entry vme2 = {0,}; + + role = (char *) param; + + if (strcmp (vme->option, "!log-format") != 0 || + !strstr (vme->key, role)) + return 0; + + memcpy (&vme2, vme, sizeof (vme2)); + vme2.option = "log-format"; + + return basic_option_handler (graph, &vme2, NULL); +} + +static int +volgen_graph_set_xl_options (volgen_graph_t *graph, dict_t *dict) +{ + int32_t ret = -1; + char *xlator = NULL; + char xlator_match[1024] = {0,}; /* for posix* -> *posix* */ + char *loglevel = NULL; + xlator_t *trav = NULL; + + ret = dict_get_str (dict, "xlator", &xlator); + if (ret) + goto out; + + ret = dict_get_str (dict, "loglevel", &loglevel); + if (ret) + goto out; + + snprintf (xlator_match, 1024, "*%s", xlator); + + for (trav = first_of (graph); trav; trav = trav->next) { + if (fnmatch(xlator_match, trav->type, FNM_NOESCAPE) == 0) { + gf_log ("glusterd", GF_LOG_DEBUG, "Setting log level for xlator: %s", + trav->type); + ret = xlator_set_option (trav, "log-level", loglevel); + if (ret) + break; + } + } + + out: + return ret; +} + +static int +server_spec_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, void *param) { int ret = 0; @@ -1231,35 +1407,408 @@ server_spec_option_handler (glusterfs_graph_t *graph, ret = server_auth_option_handler (graph, vme, NULL); if (!ret) - ret = server_check_marker_off (vme, volinfo); + ret = server_check_marker_off (graph, vme, volinfo); if (!ret) ret = loglevel_option_handler (graph, vme, "brick"); + if (!ret) + ret = sys_loglevel_option_handler (graph, vme, "brick"); + + if (!ret) + ret = logger_option_handler (graph, vme, "brick"); + + if (!ret) + ret = log_format_option_handler (graph, vme, "brick"); + + return ret; +} + +static int +server_spec_extended_option_handler (volgen_graph_t *graph, + struct volopt_map_entry *vme, void *param) +{ + int ret = 0; + dict_t *dict = NULL; + + GF_ASSERT (param); + dict = (dict_t *)param; + + ret = server_auth_option_handler (graph, vme, NULL); + if (!ret) + ret = volgen_graph_set_xl_options (graph, dict); + return ret; } static void get_vol_tstamp_file (char *filename, glusterd_volinfo_t *volinfo); +xlator_t * +add_one_peer (volgen_graph_t *graph, glusterd_brickinfo_t *peer, + char *volname, uint16_t index) +{ + xlator_t *kid; + + kid = volgen_graph_add_nolink (graph, "protocol/client", + "%s-client-%u", volname, + index++); + if (!kid) { + return NULL; + } + + /* TBD: figure out where to get the proper transport list */ + if (xlator_set_option(kid,"transport-type","socket")) { + return NULL; + } + if (xlator_set_option(kid,"remote-host",peer->hostname)) { + return NULL; + } + if (xlator_set_option(kid,"remote-subvolume",peer->path)) { + return NULL; + } + /* TBD: deal with RDMA, SSL */ + + return kid; +} + +void +assign_groups (glusterd_volinfo_t *volinfo) +{ + glusterd_brickinfo_t *brickinfo = NULL; + uint16_t group_num = 0; + int in_group = 0; + uuid_t tmp_uuid; + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (in_group == 0) { + uuid_generate(tmp_uuid); + } + brickinfo->group = group_num; + uuid_copy(brickinfo->nsr_uuid,tmp_uuid); + if (++in_group >= volinfo->replica_count) { + in_group = 0; + ++group_num; + } + } +} + +int +add_nsr_stuff (volgen_graph_t *graph, char *volname, + glusterd_brickinfo_t *brickinfo, glusterd_volinfo_t *volinfo, + char *changelog_basepath) +{ + xlator_t *me; + xlator_t *kid; + glusterd_brickinfo_t *peer; + uint16_t index = 0; + //uint32_t i=0; + char *leader_opt; + uint32_t replica_group_size = 1; + char dst[NSR_MAX_PATH_SIZE]; + char local_path[NSR_MAX_PATH_SIZE]; + char local_name[NSR_MAX_PATH_SIZE]; + char hosts[NSR_MAX_PATH_SIZE * NSR_MAX_REPLICA_GROUP_SIZE]; + char remote_names[NSR_MAX_REPLICA_GROUP_SIZE * NSR_MAX_PATH_SIZE]; + char filepath[PATH_MAX] = {0,}; + char lp[PATH_MAX] = {0,}; + xlator_t *xl = NULL; + char s[256]; + char transt[16] = {0,}; + char auth[256]; + char c_d[NSR_MAX_PATH_SIZE]; + char *username = NULL, *password = NULL; + gf_boolean_t enable_recon = _gf_false; + static uint32_t nsr_port = 27000; + + if (glusterd_volinfo_get_boolean(volinfo,"cluster.nsr.recon") > 0) { + enable_recon = _gf_true; + } + + volgen_graph_t ng = {0,}; + char path[PATH_MAX] = {0,}; + char *ptr = NULL, *this = NULL, *that = NULL; + glusterd_conf_t *priv = NULL; + + + priv = THIS->private; + remote_names[0] = '\0'; + that = gf_strdup (brickinfo->hostname); + this = gf_strdup (brickinfo->path); + ptr = strchr (this, '/'); + while (ptr) { + *ptr = '-'; + ptr = strchr (this, '/'); + } + GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); + snprintf (dst, PATH_MAX, + "%s/%s/%s:%s", + path, + GLUSTERD_BRICK_INFO_DIR, + that, + this); + + /* Create the NSR xlator, but defer linkage for now. */ + me = xlator_instantiate ("cluster/nsr", "%s-nsr", volname); + if (!me || volgen_xlator_link(me,first_of(graph))) { + return -1; + } + + strcpy(local_name, brickinfo->hostname); + strcpy(local_path, brickinfo->hostname); + strcat(local_name, ":"); + strcat(local_name, brickinfo->path); + strcpy(hosts, brickinfo->hostname); + + peer = list_prev (brickinfo, &volinfo->bricks, + glusterd_brickinfo_t, brick_list); + /* Check leader status while we have this pointer in hand. */ + leader_opt = (!peer || (peer->group != brickinfo->group)) ? "yes" + : "no"; + if (xlator_set_option(me,"vol-name",volname)) + return -1; + if (xlator_set_option(me,"my-name",local_name)) + return -1; + if (xlator_set_option(me,"leader",leader_opt)) + return -1; + if (xlator_set_option(me,"subvol-uuid", + uuid_utoa(brickinfo->nsr_uuid))) { + return -1; + } + +#define FILL_REMOTE_NAMES { \ + strcat(remote_names, \ + peer->hostname); \ + strcat(remote_names, \ + ":"); \ + strcat(remote_names, \ + peer->path); \ + strcat(remote_names, \ + ","); \ + strcat(hosts, ","); \ + strcat(hosts, \ + peer->hostname); \ + replica_group_size++; \ +} + + /* Now get on with the show. */ + while (peer) { + if (peer->group != brickinfo->group) { + break; + } + gf_log ("glusterd", GF_LOG_INFO, + "%s:%s needs client for %s:%s", + brickinfo->hostname, brickinfo->path, + peer->hostname, peer->path); + kid = add_one_peer (graph, peer, volname, index++); + if (!kid || volgen_xlator_link(me,kid)) { + return -1; + } + FILL_REMOTE_NAMES; + peer = list_prev (peer, &volinfo->bricks, + glusterd_brickinfo_t, brick_list); + } + + peer = list_next (brickinfo, &volinfo->bricks, + glusterd_brickinfo_t, brick_list); + while (peer) { + if (peer->group != brickinfo->group) { + break; + } + gf_log ("glusterd", GF_LOG_INFO, + "%s:%s needs client for %s:%s", + brickinfo->hostname, brickinfo->path, + peer->hostname, peer->path); + kid = add_one_peer (graph, peer, volname, index++); + if (!kid || volgen_xlator_link(me,kid)) { + return -1; + } + FILL_REMOTE_NAMES; + peer = list_next (peer, &volinfo->bricks, + glusterd_brickinfo_t, brick_list); + } + + // to remove the final "," + if (strlen(remote_names)) { + remote_names[strlen(remote_names) - 1] = '\0'; + } + if (xlator_set_option(me,"etcd-servers",hosts)) + return -1; + + // Finish linkage to client file + glusterfs_graph_set_first(&graph->graph,me); + + if (enable_recon == _gf_false) + return 0; + + /* Now fill in the various files required for reconciliation */ + snprintf (filepath, PATH_MAX, + "%s-nsr-recon.vol", + dst); + gf_log ("glusterd", GF_LOG_INFO, + "writing nsr recon volfile in %s\n", + filepath); +#if 0 + strcpy(lp, local_name); +#else + strcpy(lp, brickinfo->path); +#endif + strcat(lp,"/recon"); + bzero(&ng, sizeof(ng)); + xl = volgen_graph_add_as (&ng, "cluster/nsr_recon",lp); + if (!xl) + return -1; + sprintf(s,"%d",replica_group_size); + if (xlator_set_option(xl, "replica-group-size", s) == -1) + return -1; + if (xlator_set_option(xl, "local-member", local_name) == -1) + return -1; + if (xlator_set_option(xl, "replica-group-members", remote_names) == -1) + return -1; + if (xlator_set_option(xl,"vol-name",volname)) + return -1; + if (xlator_set_option(xl,"changelog-dir",changelog_basepath)) + return -1; + if (xlator_set_option(xl,"base-dir",brickinfo->path)) + return -1; + + xl = volgen_graph_add (&ng, "protocol/server", lp); + if (!xl) + return -1; + get_vol_transport_type (volinfo, transt); + if(xlator_set_option (xl, "transport-type", transt) == -1) + return -1; + sprintf(s,"%d",nsr_port); + if(xlator_set_option (xl, "transport.socket.listen-port", s) == -1) + return -1; + strcpy(auth, "auth.addr."); + strcat(auth, lp); + strcat(auth, ".allow"); + if(xlator_set_option (xl, auth, "*") == -1) + return -1; + if(xlator_set_option (xl, "rpc-auth.auth-null", "off") == -1) + return -1; + if(xlator_set_option (xl, "rpc-auth.auth-unix", "off") == -1) + return -1; + if(xlator_set_option (xl, "rpc-auth.auth-glusterfs", "off") == -1) + return -1; + if(volgen_write_volfile(&ng, filepath) == -1) + return -1; + + bzero(&ng, sizeof(ng)); + kid = volgen_graph_add_nolink (&ng, "protocol/client", + "%s-client-%u", lp, 0); + if (!kid) + return -1; + if (xlator_set_option(kid,"remote-host",brickinfo->hostname)) + return -1; +#if 0 + strcpy(lp, brickinfo->path); + strcat(lp,"/recon"); +#endif + if (xlator_set_option(kid,"remote-subvolume",lp)) + return -1; + if(xlator_set_option (kid, "transport-type", transt) == -1) + return -1; + sprintf(s,"%d",nsr_port++); + if(xlator_set_option (kid, "remote-port", s) == -1) + return -1; + snprintf (c_d, PATH_MAX, + "%s/%s/con:%s:%s", + path, + GLUSTERD_BRICK_INFO_DIR, + that, this); + if (volgen_write_volfile(&ng, c_d)) + return -1; + + bzero(&ng, sizeof(ng)); + kid = volgen_graph_add_nolink (&ng, "protocol/client", + "%s-client-%u", lp, 0); + if (!kid) + return -1; + if (xlator_set_option(kid,"remote-host",brickinfo->hostname)) + return -1; + if (xlator_set_option(kid,"remote-subvolume",brickinfo->path)) + return -1; + if(xlator_set_option (kid, "transport-type", transt) == -1) + return -1; + username = glusterd_auth_get_username (volinfo); + password = glusterd_auth_get_password (volinfo); + if(xlator_set_option (kid, "username", username) == -1) + return -1; + if(xlator_set_option (kid, "password", password) == -1) + return -1; + snprintf (c_d, PATH_MAX, + "%s/%s/data:%s:%s", + path, + GLUSTERD_BRICK_INFO_DIR, that, + this); + if (volgen_write_volfile(&ng, c_d)) + return -1; + + return 0; + +} + static int -server_graph_builder (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, +server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, dict_t *set_dict, void *param) { - char *volname = NULL; - char *path = NULL; - int pump = 0; - xlator_t *xl = NULL; - xlator_t *txl = NULL; - xlator_t *rbxl = NULL; - char transt[16] = {0,}; - char volume_id[64] = {0,}; - char tstamp_file[PATH_MAX] = {0,}; - int ret = 0; - - path = param; + char *volname = NULL; + char *path = NULL; + int pump = 0; + xlator_t *xl = NULL; + xlator_t *txl = NULL; + xlator_t *rbxl = NULL; + char transt[16] = {0,}; + char *ptranst = NULL; + char volume_id[64] = {0,}; + char tstamp_file[PATH_MAX] = {0,}; + int ret = 0; + char *xlator = NULL; + char *loglevel = NULL; + char *username = NULL; + char *password = NULL; + char index_basepath[PATH_MAX] = {0}; + char key[1024] = {0}; + glusterd_brickinfo_t *brickinfo = NULL; + char changelog_basepath[PATH_MAX] = {0,}; + gf_boolean_t quota_enabled = _gf_true; + gf_boolean_t pgfid_feat = _gf_false; + char *value = NULL; + + brickinfo = param; + path = brickinfo->path; volname = volinfo->volname; get_vol_transport_type (volinfo, transt); + ret = dict_get_str (set_dict, "xlator", &xlator); + + /* got a cli log level request */ + if (!ret) { + ret = dict_get_str (set_dict, "loglevel", &loglevel); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "could not get both" + " translator name and loglevel for log level request"); + goto out; + } + } + + ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_QUOTA, &value); + if (value) { + ret = gf_string2boolean (value, "a_enabled); + if (ret) + goto out; + } + + ret = glusterd_volinfo_get (volinfo, + "update-link-count-parent", + &value); + if (value) { + ret = gf_string2boolean (value, &pgfid_feat); + if (ret) + goto out; + } + xl = volgen_graph_add (graph, "storage/posix", volname); if (!xl) return -1; @@ -1268,23 +1817,102 @@ server_graph_builder (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, if (ret) return -1; + ret = xlator_set_option (xl, "volume-id", + uuid_utoa (volinfo->volume_id)); + if (ret) + return -1; + + if (quota_enabled || pgfid_feat) + xlator_set_option (xl, "update-link-count-parent", + "on"); + + ret = check_and_add_debug_xl (graph, set_dict, volname, + "posix"); + if (ret) + return -1; +#ifdef HAVE_BD_XLATOR + if (*brickinfo->vg != '\0') { + /* Now add BD v2 xlator if volume is BD type */ + xl = volgen_graph_add (graph, "storage/bd", volname); + if (!xl) + return -1; + + ret = xlator_set_option (xl, "device", "vg"); + if (ret) + return -1; + ret = xlator_set_option (xl, "export", brickinfo->vg); + if (ret) + return -1; + + ret = check_and_add_debug_xl (graph, set_dict, volname, "bd"); + if (ret) + return -1; + + } +#endif + + xl = volgen_graph_add (graph, "features/changelog", volname); + if (!xl) + return -1; + + ret = xlator_set_option (xl, "changelog-brick", path); + if (ret) + return -1; + + snprintf (changelog_basepath, sizeof (changelog_basepath), + "%s/%s", path, ".glusterfs/changelogs"); + ret = xlator_set_option (xl, "changelog-dir", changelog_basepath); + if (ret) + return -1; + + if (glusterd_volinfo_get_boolean(volinfo,"cluster.nsr") > 0) { + ret = xlator_set_option (xl, "encoding", "ascii"); + if (ret) + return -1; + } + + ret = check_and_add_debug_xl (graph, set_dict, volname, "changelog"); + if (ret) + return -1; + + xl = volgen_graph_add (graph, "features/access-control", volname); if (!xl) return -1; + ret = check_and_add_debug_xl (graph, set_dict, volname, "acl"); + if (ret) + return -1; + xl = volgen_graph_add (graph, "features/locks", volname); if (!xl) return -1; + ret = check_and_add_debug_xl (graph, set_dict, volname, "locks"); + if (ret) + return -1; + xl = volgen_graph_add (graph, "performance/io-threads", volname); if (!xl) return -1; + ret = check_and_add_debug_xl (graph, set_dict, volname, "io-threads"); + if (ret) + return -1; + + xl = volgen_graph_add (graph, "features/barrier", volname); + if (!xl) + return -1; + ret = dict_get_int32 (volinfo->dict, "enable-pump", &pump); if (ret == -ENOENT) ret = pump = 0; if (ret) return -1; + + username = glusterd_auth_get_username (volinfo); + password = glusterd_auth_get_password (volinfo); + if (pump) { txl = first_of (graph); @@ -1292,9 +1920,28 @@ server_graph_builder (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, "%s-replace-brick", volname); if (!rbxl) return -1; - ret = xlator_set_option (rbxl, "transport-type", transt); + + ptranst = glusterd_get_trans_type_rb (volinfo->transport_type); + if (NULL == ptranst) + return -1; + + if (username) { + ret = xlator_set_option (rbxl, "username", username); + if (ret) + return -1; + } + + if (password) { + ret = xlator_set_option (rbxl, "password", password); + if (ret) + return -1; + } + + ret = xlator_set_option (rbxl, "transport-type", ptranst); + GF_FREE (ptranst); if (ret) return -1; + xl = volgen_graph_add_nolink (graph, "cluster/pump", "%s-pump", volname); if (!xl) @@ -1307,9 +1954,35 @@ server_graph_builder (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, return -1; } + /* TBD: conditionalize on NSR being enabled */ + if (glusterd_volinfo_get_boolean(volinfo,"cluster.nsr") > 0) { + ret = add_nsr_stuff (graph, volname, brickinfo, volinfo, + changelog_basepath); + if (ret) { + return -1; + } + } + else { + xl = volgen_graph_add (graph, "features/index", volname); + if (!xl) + return -1; + } + + snprintf (index_basepath, sizeof (index_basepath), "%s/%s", + path, ".glusterfs/indices"); + ret = xlator_set_option (xl, "index-base", index_basepath); + if (ret) + return -1; + + ret = check_and_add_debug_xl (graph, set_dict, volname, + "index"); + if (ret) + return -1; + xl = volgen_graph_add (graph, "features/marker", volname); if (!xl) return -1; + uuid_unparse (volinfo->volume_id, volume_id); ret = xlator_set_option (xl, "volume-uuid", volume_id); if (ret) @@ -1319,6 +1992,66 @@ server_graph_builder (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, if (ret) return -1; + ret = check_and_add_debug_xl (graph, set_dict, volname, "marker"); + if (ret) + return -1; + + xl = volgen_graph_add (graph, "features/quota", volname); + if (!xl) + return -1; + ret = xlator_set_option (xl, "volume-uuid", volname); + if (ret) + return -1; + + ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_QUOTA, &value); + if (value) { + ret = xlator_set_option (xl, "server-quota", value); + if (ret) + return -1; + } + + if (dict_get_str_boolean (set_dict, "features.read-only", 0) && + dict_get_str_boolean (set_dict, "features.worm",0)) { + gf_log (THIS->name, GF_LOG_ERROR, + "read-only and worm cannot be set together"); + ret = -1; + goto out; + } + + /* Check for read-only volume option, and add it to the graph */ + if (dict_get_str_boolean (set_dict, "features.read-only", 0) + || volinfo -> is_snap_volume) { + xl = volgen_graph_add (graph, "features/read-only", volname); + if (!xl) { + ret = -1; + goto out; + } + } + + /* Check for worm volume option, and add it to the graph */ + if (dict_get_str_boolean (set_dict, "features.worm", 0)) { + xl = volgen_graph_add (graph, "features/worm", volname); + if (!xl) { + ret = -1; + goto out; + } + } + + /* Check for compress volume option, and add it to the graph on server side */ + ret = dict_get_str_boolean (set_dict, "network.compression", 0); + if (ret == -1) + goto out; + if (ret) { + xl = volgen_graph_add (graph, "features/cdc", volname); + if (!xl) { + ret = -1; + goto out; + } + ret = xlator_set_option (xl, "mode", "server"); + if (ret) + goto out; + } + xl = volgen_graph_add_as (graph, "debug/io-stats", path); if (!xl) return -1; @@ -1330,24 +2063,86 @@ server_graph_builder (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, if (ret) return -1; - ret = volgen_graph_set_options_generic (graph, set_dict, volinfo, - &server_spec_option_handler); + /*In the case of running multiple glusterds on a single machine, + * we should ensure that bricks don't listen on all IPs on that + * machine and break the IP based separation being brought about.*/ + if (dict_get (THIS->options, "transport.socket.bind-address")) { + ret = xlator_set_option (xl, "transport.socket.bind-address", + brickinfo->hostname); + if (ret) + return -1; + } + + if (username) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "auth.login.%s.allow", path); + + ret = xlator_set_option (xl, key, username); + if (ret) + return -1; + } + + if (password) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "auth.login.%s.password", + username); + + ret = xlator_set_option (xl, key, password); + if (ret) + return -1; + } + ret = volgen_graph_set_options_generic (graph, set_dict, + (xlator && loglevel) ? (void *)set_dict : volinfo, + (xlator && loglevel) ? &server_spec_extended_option_handler : + &server_spec_option_handler); + + out: return ret; } /* builds a graph for server role , with option overrides in mod_dict */ static int -build_server_graph (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, - dict_t *mod_dict, char *path) +build_server_graph (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, + dict_t *mod_dict, glusterd_brickinfo_t *brickinfo) { - return build_graph_generic (graph, volinfo, mod_dict, path, + return build_graph_generic (graph, volinfo, mod_dict, brickinfo, &server_graph_builder); } static int -perfxl_option_handler (glusterfs_graph_t *graph, struct volopt_map_entry *vme, +perfxl_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, + void *param) +{ + gf_boolean_t enabled = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + + GF_ASSERT (param); + volinfo = param; + + if (strcmp (vme->option, "!perf") != 0) + return 0; + + if (gf_string2boolean (vme->value, &enabled) == -1) + return -1; + if (!enabled) + return 0; + + /* Check op-version before adding the 'open-behind' xlator in the graph + */ + if (!strcmp (vme->key, "performance.open-behind") && + (vme->op_version > volinfo->client_op_version)) + return 0; + + if (volgen_graph_add (graph, vme->voltype, volinfo->volname)) + return 0; + else + return -1; +} + +static int +nfsperfxl_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, void *param) { char *volname = NULL; @@ -1355,7 +2150,7 @@ perfxl_option_handler (glusterfs_graph_t *graph, struct volopt_map_entry *vme, volname = param; - if (strcmp (vme->option, "!perf") != 0) + if (strcmp (vme->option, "!nfsperf") != 0) return 0; if (gf_string2boolean (vme->value, &enabled) == -1) @@ -1369,179 +2164,999 @@ perfxl_option_handler (glusterfs_graph_t *graph, struct volopt_map_entry *vme, return -1; } +#if (HAVE_LIB_XML) static int -client_graph_builder (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, - dict_t *set_dict, void *param) +end_sethelp_xml_doc (xmlTextWriterPtr writer) { - int dist_count = 0; + int ret = -1; + + ret = xmlTextWriterEndElement(writer); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "Could not end an " + "xmlElemetnt"); + ret = -1; + goto out; + } + ret = xmlTextWriterEndDocument (writer); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "Could not end an " + "xmlDocument"); + ret = -1; + goto out; + } + ret = 0; + out: + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + +} + +static int +init_sethelp_xml_doc (xmlTextWriterPtr *writer, xmlBufferPtr *buf) +{ + int ret; + + *buf = xmlBufferCreateSize (8192); + if (buf == NULL) { + gf_log ("glusterd", GF_LOG_ERROR, "Error creating the xml " + "buffer"); + ret = -1; + goto out; + } + + xmlBufferSetAllocationScheme (*buf,XML_BUFFER_ALLOC_DOUBLEIT); + + *writer = xmlNewTextWriterMemory(*buf, 0); + if (writer == NULL) { + gf_log ("glusterd", GF_LOG_ERROR, " Error creating the xml " + "writer"); + ret = -1; + goto out; + } + + ret = xmlTextWriterStartDocument(*writer, "1.0", "UTF-8", "yes"); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "Error While starting the " + "xmlDoc"); + goto out; + } + + ret = xmlTextWriterStartElement(*writer, (xmlChar *)"options"); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "Could not create an " + "xmlElemetnt"); + ret = -1; + goto out; + } + + + ret = 0; + + out: + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + +} + +static int +xml_add_volset_element (xmlTextWriterPtr writer, const char *name, + const char *def_val, const char *dscrpt) +{ + + int ret = -1; + + GF_ASSERT (name); + + ret = xmlTextWriterStartElement(writer, (xmlChar *) "option"); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "Could not create an " + "xmlElemetnt"); + ret = -1; + goto out; + } + + ret = xmlTextWriterWriteFormatElement(writer, (xmlChar*)"defaultValue", + "%s", def_val); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "Could not create an " + "xmlElemetnt"); + ret = -1; + goto out; + } + + ret = xmlTextWriterWriteFormatElement(writer, (xmlChar *)"description", + "%s", dscrpt ); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "Could not create an " + "xmlElemetnt"); + ret = -1; + goto out; + } + + ret = xmlTextWriterWriteFormatElement(writer, (xmlChar *) "name", "%s", + name); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "Could not create an " + "xmlElemetnt"); + ret = -1; + goto out; + } + + ret = xmlTextWriterEndElement(writer); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, "Could not end an " + "xmlElemetnt"); + ret = -1; + goto out; + } + + ret = 0; + out: + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + +} + +#endif + +static int +_get_xlator_opt_key_from_vme ( struct volopt_map_entry *vme, char **key) +{ + int ret = 0; + + GF_ASSERT (vme); + GF_ASSERT (key); + + + if (!strcmp (vme->key, AUTH_ALLOW_MAP_KEY)) + *key = gf_strdup (AUTH_ALLOW_OPT_KEY); + else if (!strcmp (vme->key, AUTH_REJECT_MAP_KEY)) + *key = gf_strdup (AUTH_REJECT_OPT_KEY); + else if (!strcmp (vme->key, NFS_DISABLE_MAP_KEY)) + *key = gf_strdup (NFS_DISABLE_OPT_KEY); + else { + if (vme->option) { + if (vme->option[0] == '!') { + *key = vme->option + 1; + if (!*key[0]) + ret = -1; + } else { + *key = vme->option; + } + } else { + *key = strchr (vme->key, '.'); + if (*key) { + (*key) ++; + if (!*key[0]) + ret = -1; + } else { + ret = -1; + } + } + } + if (ret) + gf_log ("glusterd", GF_LOG_ERROR, "Wrong entry found in " + "glusterd_volopt_map entry %s", vme->key); + else + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +static void +_free_xlator_opt_key (char *key) +{ + GF_ASSERT (key); + + if (!strcmp (key, AUTH_ALLOW_OPT_KEY) || + !strcmp (key, AUTH_REJECT_OPT_KEY) || + !strcmp (key, NFS_DISABLE_OPT_KEY)) + GF_FREE (key); + + return; +} + +int +glusterd_get_volopt_content (dict_t * ctx, gf_boolean_t xml_out) +{ + void *dl_handle = NULL; + volume_opt_list_t vol_opt_handle = {{0},}; + char *key = NULL; + struct volopt_map_entry *vme = NULL; + int ret = -1; + char *def_val = NULL; + char *descr = NULL; + char output_string[51200] = {0, }; + char *output = NULL; + char tmp_str[2048] = {0, }; +#if (HAVE_LIB_XML) + xmlTextWriterPtr writer = NULL; + xmlBufferPtr buf = NULL; + + if (xml_out) { + ret = init_sethelp_xml_doc (&writer, &buf); + if (ret) /*logging done in init_xml_lib*/ + goto out; + } +#endif + + INIT_LIST_HEAD (&vol_opt_handle.list); + + for (vme = &glusterd_volopt_map[0]; vme->key; vme++) { + + if ((vme->type == NO_DOC) || (vme->type == GLOBAL_NO_DOC)) + continue; + + if (vme->description) { + descr = vme->description; + def_val = vme->value; + } else { + if (_get_xlator_opt_key_from_vme (vme, &key)) { + gf_log ("glusterd", GF_LOG_DEBUG, "Failed to " + "get %s key from volume option entry", + vme->key); + goto out; /*Some error while geting key*/ + } + + ret = xlator_volopt_dynload (vme->voltype, + &dl_handle, + &vol_opt_handle); + + if (ret) { + gf_log ("glusterd", GF_LOG_DEBUG, + "xlator_volopt_dynload error(%d)", ret); + ret = 0; + goto cont; + } + + ret = xlator_option_info_list (&vol_opt_handle, key, + &def_val, &descr); + if (ret) { /*Swallow Error i.e if option not found*/ + gf_log ("glusterd", GF_LOG_DEBUG, + "Failed to get option for %s key", key); + ret = 0; + goto cont; + } + } + + if (xml_out) { +#if (HAVE_LIB_XML) + if (xml_add_volset_element (writer,vme->key, + def_val, descr)) { + ret = -1; + goto cont; + } +#else + gf_log ("glusterd", GF_LOG_ERROR, "Libxml not present"); +#endif + } else { + snprintf (tmp_str, sizeof (tmp_str), "Option: %s\nDefault " + "Value: %s\nDescription: %s\n\n", + vme->key, def_val, descr); + strcat (output_string, tmp_str); + } +cont: + if (dl_handle) { + dlclose (dl_handle); + dl_handle = NULL; + vol_opt_handle.given_opt = NULL; + } + if (key) { + _free_xlator_opt_key (key); + key = NULL; + } + if (ret) + goto out; + } + +#if (HAVE_LIB_XML) + if ((xml_out) && + (ret = end_sethelp_xml_doc (writer))) + goto out; +#else + if (xml_out) + gf_log ("glusterd", GF_LOG_ERROR, "Libxml not present"); +#endif + + if (!xml_out) + output = gf_strdup (output_string); + else +#if (HAVE_LIB_XML) + output = gf_strdup ((char *)buf->content); +#else + gf_log ("glusterd", GF_LOG_ERROR, "Libxml not present"); +#endif + + if (NULL == output) { + ret = -1; + goto out; + } + + ret = dict_set_dynstr (ctx, "help-str", output); +out: + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + +} + +static int +volgen_graph_build_clients (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, + dict_t *set_dict, void *param) +{ + int i = 0; + int ret = -1; + uint32_t client_type = GF_CLIENT_OTHER; char transt[16] = {0,}; - char *tt = NULL; char *volname = NULL; - dict_t *dict = NULL; - glusterd_brickinfo_t *brick = NULL; - char *replicate_args[] = {"cluster/replicate", - "%s-replicate-%d"}; - char *stripe_args[] = {"cluster/stripe", - "%s-stripe-%d"}; - char **cluster_args = NULL; - int i = 0; - int j = 0; - int ret = 0; + char *str = NULL; + glusterd_brickinfo_t *brick = NULL; xlator_t *xl = NULL; - xlator_t *txl = NULL; - xlator_t *trav = NULL; + char *ssl_str = NULL; + gf_boolean_t ssl_bool; volname = volinfo->volname; - dict = volinfo->dict; - GF_ASSERT (dict); if (volinfo->brick_count == 0) { gf_log ("", GF_LOG_ERROR, "volume inconsistency: brick count is 0"); - - return -1; + goto out; } - if (volinfo->sub_count && volinfo->sub_count < volinfo->brick_count && - volinfo->brick_count % volinfo->sub_count != 0) { + + if ((volinfo->dist_leaf_count < volinfo->brick_count) && + ((volinfo->brick_count % volinfo->dist_leaf_count) != 0)) { gf_log ("", GF_LOG_ERROR, "volume inconsistency: " "total number of bricks (%d) is not divisible with " "number of bricks per cluster (%d) in a multi-cluster " "setup", - volinfo->brick_count, volinfo->sub_count); - return -1; + volinfo->brick_count, volinfo->dist_leaf_count); + goto out; } - ret = dict_get_str (set_dict, "client-transport-type", &tt); - if (ret) - get_vol_transport_type (volinfo, transt); - if (!ret) - strcpy (transt, tt); + get_transport_type (volinfo, set_dict, transt, _gf_false); + + if (!strcmp (transt, "tcp,rdma")) + strcpy (transt, "tcp"); i = 0; + ret = -1; list_for_each_entry (brick, &volinfo->bricks, brick_list) { + ret = -1; xl = volgen_graph_add_nolink (graph, "protocol/client", - "%s-client-%d", volname, i); + "%s", brick->brick_id); if (!xl) - return -1; + goto out; ret = xlator_set_option (xl, "remote-host", brick->hostname); if (ret) - return -1; + goto out; ret = xlator_set_option (xl, "remote-subvolume", brick->path); if (ret) - return -1; + goto out; ret = xlator_set_option (xl, "transport-type", transt); if (ret) - return -1; + goto out; + + ret = dict_get_uint32 (set_dict, "trusted-client", + &client_type); + + if (!ret && client_type == GF_CLIENT_TRUSTED) { + str = NULL; + str = glusterd_auth_get_username (volinfo); + if (str) { + ret = xlator_set_option (xl, "username", + str); + if (ret) + goto out; + } + + str = glusterd_auth_get_password (volinfo); + if (str) { + ret = xlator_set_option (xl, "password", + str); + if (ret) + goto out; + } + } + + if (dict_get_str(set_dict,"client.ssl",&ssl_str) == 0) { + if (gf_string2boolean(ssl_str,&ssl_bool) == 0) { + if (ssl_bool) { + ret = xlator_set_option(xl, + "transport.socket.ssl-enabled", + "true"); + if (ret) { + goto out; + } + } + } + } i++; } + if (i != volinfo->brick_count) { gf_log ("", GF_LOG_ERROR, "volume inconsistency: actual number of bricks (%d) " "differs from brick count (%d)", i, volinfo->brick_count); - return -1; + ret = -1; + goto out; } + ret = 0; +out: + return ret; +} + +static int +volgen_graph_build_clusters (volgen_graph_t *graph, + glusterd_volinfo_t *volinfo, char *xl_type, + char *xl_namefmt, size_t child_count, + size_t sub_count) +{ + int i = 0; + int j = 0; + xlator_t *txl = NULL; + xlator_t *xl = NULL; + xlator_t *trav = NULL; + char *volname = NULL; + int ret = -1; + + if (child_count == 0) + goto out; + volname = volinfo->volname; + txl = first_of (graph); + for (trav = txl; --child_count; trav = trav->next); + for (;; trav = trav->prev) { + if ((i % sub_count) == 0) { + xl = volgen_graph_add_nolink (graph, xl_type, + xl_namefmt, volname, j); + if (!xl) { + ret = -1; + goto out; + } + j++; + } - if (volinfo->sub_count > 1) { - switch (volinfo->type) { - case GF_CLUSTER_TYPE_REPLICATE: - cluster_args = replicate_args; + ret = volgen_xlator_link (xl, trav); + if (ret) + goto out; + + if (trav == txl) break; - case GF_CLUSTER_TYPE_STRIPE: - cluster_args = stripe_args; + + i++; + } + + ret = j; +out: + return ret; +} + +gf_boolean_t +_xl_is_client_decommissioned (xlator_t *xl, glusterd_volinfo_t *volinfo) +{ + int ret = 0; + gf_boolean_t decommissioned = _gf_false; + char *hostname = NULL; + char *path = NULL; + + GF_ASSERT (!strcmp (xl->type, "protocol/client")); + ret = xlator_get_option (xl, "remote-host", &hostname); + if (ret) { + GF_ASSERT (0); + gf_log ("glusterd", GF_LOG_ERROR, "Failed to get remote-host " + "from client %s", xl->name); + goto out; + } + ret = xlator_get_option (xl, "remote-subvolume", &path); + if (ret) { + GF_ASSERT (0); + gf_log ("glusterd", GF_LOG_ERROR, "Failed to get remote-host " + "from client %s", xl->name); + goto out; + } + + decommissioned = glusterd_is_brick_decommissioned (volinfo, hostname, + path); +out: + return decommissioned; +} + +gf_boolean_t +_xl_has_decommissioned_clients (xlator_t *xl, glusterd_volinfo_t *volinfo) +{ + xlator_list_t *xl_child = NULL; + gf_boolean_t decommissioned = _gf_false; + xlator_t *cxl = NULL; + + if (!xl) + goto out; + + if (!strcmp (xl->type, "protocol/client")) { + decommissioned = _xl_is_client_decommissioned (xl, volinfo); + goto out; + } + + xl_child = xl->children; + while (xl_child) { + cxl = xl_child->xlator; + /* this can go into 2 depths if the volume type + is stripe-replicate */ + decommissioned = _xl_has_decommissioned_clients (cxl, volinfo); + if (decommissioned) break; - default: - gf_log ("", GF_LOG_ERROR, "volume inconsistency: " - "unrecognized clustering type"); - return -1; - } - i = 0; - j = 0; - txl = first_of (graph); - for (trav = txl; trav->next; trav = trav->next); - for (;; trav = trav->prev) { - if (i % volinfo->sub_count == 0) { - xl = volgen_graph_add_nolink (graph, - cluster_args[0], - cluster_args[1], - volname, j); - if (!xl) - return -1; - j++; - } + xl_child = xl_child->next; + } +out: + return decommissioned; +} - ret = volgen_xlator_link (xl, trav); - if (ret) - return -1; +static int +_graph_get_decommissioned_children (xlator_t *dht, glusterd_volinfo_t *volinfo, + char **children) +{ + int ret = -1; + xlator_list_t *xl_child = NULL; + xlator_t *cxl = NULL; + gf_boolean_t comma = _gf_false; + + *children = NULL; + xl_child = dht->children; + while (xl_child) { + cxl = xl_child->xlator; + if (_xl_has_decommissioned_clients (cxl, volinfo)) { + if (!*children) { + *children = GF_CALLOC (16 * GF_UNIT_KB, 1, + gf_common_mt_char); + if (!*children) + goto out; + } - if (trav == txl) - break; - i++; + if (comma) + strcat (*children, ","); + strcat (*children, cxl->name); + comma = _gf_true; } + + xl_child = xl_child->next; } + ret = 0; +out: + return ret; +} + +static int +volgen_graph_build_dht_cluster (volgen_graph_t *graph, + glusterd_volinfo_t *volinfo, size_t child_count, + gf_boolean_t is_quotad) +{ + int32_t clusters = 0; + int ret = -1; + char *decommissioned_children = NULL; + xlator_t *dht = NULL; + char *voltype = "cluster/distribute"; + char *name_fmt = NULL; + + /* NUFA and Switch section */ + if (dict_get_str_boolean (volinfo->dict, "cluster.nufa", 0) && + dict_get_str_boolean (volinfo->dict, "cluster.switch", 0)) { + gf_log (THIS->name, GF_LOG_ERROR, + "nufa and switch cannot be set together"); + ret = -1; + goto out; + } + + /* Check for NUFA volume option, and change the voltype */ + if (dict_get_str_boolean (volinfo->dict, "cluster.nufa", 0)) + voltype = "cluster/nufa"; + + /* Check for switch volume option, and change the voltype */ + if (dict_get_str_boolean (volinfo->dict, "cluster.switch", 0)) + voltype = "cluster/switch"; - if (volinfo->sub_count) - dist_count = volinfo->brick_count / volinfo->sub_count; + if (is_quotad) + name_fmt = "%s"; else - dist_count = volinfo->brick_count; - if (dist_count > 1) { - xl = volgen_graph_add_nolink (graph, "cluster/distribute", - "%s-dht", volname); - if (!xl) - return -1; + name_fmt = "%s-dht"; + + clusters = volgen_graph_build_clusters (graph, volinfo, + voltype, + name_fmt, + child_count, + child_count); + if (clusters < 0) + goto out; - trav = xl; - for (i = 0; i < dist_count; i++) - trav = trav->next; - for (; trav != xl; trav = trav->prev) { - ret = volgen_xlator_link (xl, trav); - if (ret) - return -1; + dht = first_of (graph); + ret = _graph_get_decommissioned_children (dht, volinfo, + &decommissioned_children); + if (ret) + goto out; + if (decommissioned_children) { + ret = xlator_set_option (dht, "decommissioned-bricks", + decommissioned_children); + if (ret) + goto out; + } + ret = 0; +out: + GF_FREE (decommissioned_children); + return ret; +} + +static int +volume_volgen_graph_build_clusters (volgen_graph_t *graph, + glusterd_volinfo_t *volinfo, + gf_boolean_t is_quotad) +{ + char *replicate_type = "cluster/replicate"; + char *replicate_fmt = "%s-replicate-%d"; + char *stripe_args[] = {"cluster/stripe", + "%s-stripe-%d"}; + int rclusters = 0; + int clusters = 0; + int dist_count = 0; + int ret = -1; + + if (!volinfo->dist_leaf_count) + goto out; + + if (volinfo->dist_leaf_count == 1) + goto build_distribute; + + if (glusterd_volinfo_get_boolean(volinfo,"cluster.nsr") > 0) { + replicate_type = "cluster/nsrc"; + } + + /* All other cases, it will have one or the other cluster type */ + switch (volinfo->type) { + case GF_CLUSTER_TYPE_REPLICATE: + clusters = volgen_graph_build_clusters (graph, volinfo, + replicate_type, + replicate_fmt, + volinfo->brick_count, + volinfo->replica_count); + if (clusters < 0) + goto out; + break; + case GF_CLUSTER_TYPE_STRIPE: + clusters = volgen_graph_build_clusters (graph, volinfo, + stripe_args[0], + stripe_args[1], + volinfo->brick_count, + volinfo->stripe_count); + if (clusters < 0) + goto out; + break; + case GF_CLUSTER_TYPE_STRIPE_REPLICATE: + /* Replicate after the clients, then stripe */ + if (volinfo->replica_count == 0) + goto out; + clusters = volgen_graph_build_clusters (graph, volinfo, + replicate_type, + replicate_fmt, + volinfo->brick_count, + volinfo->replica_count); + if (clusters < 0) + goto out; + + rclusters = volinfo->brick_count / volinfo->replica_count; + GF_ASSERT (rclusters == clusters); + clusters = volgen_graph_build_clusters (graph, volinfo, + stripe_args[0], + stripe_args[1], + rclusters, + volinfo->stripe_count); + if (clusters < 0) + goto out; + break; + default: + gf_log ("", GF_LOG_ERROR, "volume inconsistency: " + "unrecognized clustering type"); + goto out; + } + +build_distribute: + dist_count = volinfo->brick_count / volinfo->dist_leaf_count; + if (!dist_count) { + ret = -1; + goto out; + } + + ret = volgen_graph_build_dht_cluster (graph, volinfo, + dist_count, is_quotad); + if (ret) + goto out; + + ret = 0; +out: + return ret; +} + +static int client_graph_set_perf_options(volgen_graph_t *graph, + glusterd_volinfo_t *volinfo, + dict_t *set_dict) +{ + data_t *tmp_data = NULL; + char *volname = NULL; + + /* + * Logic to make sure NFS doesn't have performance translators by + * default for a volume + */ + volname = volinfo->volname; + tmp_data = dict_get (set_dict, "nfs-volume-file"); + if (!tmp_data) + return volgen_graph_set_options_generic(graph, set_dict, + volinfo, + &perfxl_option_handler); + else + return volgen_graph_set_options_generic(graph, set_dict, + volname, + &nfsperfxl_option_handler); +} + +static int +client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, + dict_t *set_dict, void *param) +{ + int ret = 0; + xlator_t *xl = NULL; + char *volname = NULL; + glusterd_conf_t *conf = THIS->private; + char *tmp = NULL; + gf_boolean_t var = _gf_false; + gf_boolean_t ob = _gf_false; + xlator_t *this = THIS; + + GF_ASSERT (this); + GF_ASSERT (conf); + + volname = volinfo->volname; + ret = volgen_graph_build_clients (graph, volinfo, set_dict, param); + if (ret) + goto out; + + ret = volume_volgen_graph_build_clusters (graph, volinfo, _gf_false); + if (ret == -1) + goto out; + + /* Check for compress volume option, and add it to the graph on client side */ + ret = dict_get_str_boolean (set_dict, "network.compression", 0); + if (ret == -1) + goto out; + if (ret) { + xl = volgen_graph_add (graph, "features/cdc", volname); + if (!xl) { + ret = -1; + goto out; } + ret = xlator_set_option (xl, "mode", "client"); + if (ret) + goto out; } - ret = glusterd_volinfo_get_boolean (volinfo, VKEY_FEATURES_QUOTA); + ret = glusterd_volinfo_get_boolean (volinfo, "features.encryption"); if (ret == -1) - return -1; + goto out; if (ret) { - xl = volgen_graph_add (graph, "features/quota", volname); + xl = volgen_graph_add (graph, "encryption/crypt", volname); - if (!xl) - return -1; + if (!xl) { + ret = -1; + goto out; + } + } + + if (conf->op_version == GD_OP_VERSION_MIN) { + ret = glusterd_volinfo_get_boolean (volinfo, + VKEY_FEATURES_QUOTA); + if (ret == -1) + goto out; + if (ret) { + xl = volgen_graph_add (graph, "features/quota", + volname); + if (!xl) { + ret = -1; + goto out; + } + } + } + + + ret = glusterd_volinfo_get_boolean (volinfo, "features.file-snapshot"); + if (ret == -1) + goto out; + if (ret) { + xl = volgen_graph_add (graph, "features/qemu-block", volname); + + if (!xl) { + ret = -1; + goto out; + } + } + + /* Do not allow changing read-after-open option if root-squash is + enabled. + */ + ret = dict_get_str (set_dict, "performance.read-after-open", &tmp); + if (!ret) { + ret = dict_get_str (volinfo->dict, "server.root-squash", &tmp); + if (!ret) { + ob = _gf_false; + ret = gf_string2boolean (tmp, &ob); + if (!ret && ob) { + gf_log (this->name, GF_LOG_WARNING, + "root-squash is enabled. Please turn it" + " off to change read-after-open " + "option"); + ret = -1; + goto out; + } + } + } + + /* open behind causes problems when root-squash is enabled + (by allowing reads to happen even though the squashed user + does not have permissions to do so) as it fakes open to be + successful and later sends reads on anonymous fds. So when + root-squash is enabled, open-behind's option to read after + open is done is also enabled. + */ + ret = dict_get_str (set_dict, "server.root-squash", &tmp); + if (!ret) { + ret = gf_string2boolean (tmp, &var); + if (ret) + goto out; + + if (var) { + ret = dict_get_str (volinfo->dict, + "performance.read-after-open", + &tmp); + if (!ret) { + ret = gf_string2boolean (tmp, &ob); + /* go ahead with turning read-after-open on + even if string2boolean conversion fails, + OR if read-after-open option is turned off + */ + if (ret || !ob) + ret = dict_set_str (set_dict, + "performance.read-after-open", + "yes"); + } else { + ret = dict_set_str (set_dict, + "performance.read-after-open", + "yes"); + } + } else { + /* When root-squash has to be turned off, open-behind's + read-after-open option should be reset to what was + there before root-squash was turned on. If the option + cannot be found in volinfo's dict, it means that + option was not set before turning on root-squash. + */ + ob = _gf_false; + ret = dict_get_str (volinfo->dict, + "performance.read-after-open", + &tmp); + if (!ret) { + ret = gf_string2boolean (tmp, &ob); + + if (!ret && ob) { + ret = dict_set_str (set_dict, + "performance.read-after-open", + "yes"); + } + } + /* consider operation is failure only if read-after-open + option is enabled and could not set into set_dict + */ + if (!ob) + ret = 0; + } + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "setting " + "open behind option as part of root " + "squash failed"); + goto out; + } } - ret = volgen_graph_set_options_generic (graph, set_dict, volname, - &perfxl_option_handler); + ret = client_graph_set_perf_options(graph, volinfo, set_dict); + if (ret) + goto out; + + /* add debug translators depending on the options */ + ret = check_and_add_debug_xl (graph, set_dict, volname, + "client"); if (ret) return -1; + ret = -1; xl = volgen_graph_add_as (graph, "debug/io-stats", volname); if (!xl) - return -1; + goto out; ret = volgen_graph_set_options_generic (graph, set_dict, "client", &loglevel_option_handler); + if (ret) + gf_log (this->name, GF_LOG_WARNING, "changing client log level" + " failed"); + + ret = volgen_graph_set_options_generic (graph, set_dict, "client", + &sys_loglevel_option_handler); + if (ret) + gf_log (this->name, GF_LOG_WARNING, "changing client syslog " + "level failed"); + + ret = volgen_graph_set_options_generic (graph, set_dict, "client", + &logger_option_handler); + + if (ret) + gf_log (this->name, GF_LOG_WARNING, "changing client logger" + " failed"); + + ret = volgen_graph_set_options_generic (graph, set_dict, "client", + &log_format_option_handler); + if (ret) + gf_log (this->name, GF_LOG_WARNING, "changing client log format" + " failed"); + +out: return ret; } /* builds a graph for client role , with option overrides in mod_dict */ static int -build_client_graph (glusterfs_graph_t *graph, glusterd_volinfo_t *volinfo, +build_client_graph (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, dict_t *mod_dict) { return build_graph_generic (graph, volinfo, mod_dict, NULL, &client_graph_builder); } +char *gd_shd_options[] = { + "!self-heal-daemon", + "!heal-timeout", + NULL +}; + +char* +gd_get_matching_option (char **options, char *option) +{ + while (*options && strcmp (*options, option)) + options++; + return *options; +} + static int -nfs_option_handler (glusterfs_graph_t *graph, - struct volopt_map_entry *vme, void *param) +shd_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, + void *param) +{ + int ret = 0; + struct volopt_map_entry new_vme = {0}; + char *shd_option = NULL; + + shd_option = gd_get_matching_option (gd_shd_options, vme->option); + if ((vme->option[0] == '!') && !shd_option) + goto out; + new_vme = *vme; + if (shd_option) { + new_vme.option = shd_option + 1;//option with out '!' + } + + ret = no_filter_option_handler (graph, &new_vme, param); +out: + return ret; +} + +static int +nfs_option_handler (volgen_graph_t *graph, + struct volopt_map_entry *vme, void *param) { xlator_t *xl = NULL; char *aa = NULL; @@ -1556,10 +3171,10 @@ nfs_option_handler (glusterfs_graph_t *graph, ret = xlator_set_option (xl, vme->key, vme->value); }*/ - if ( !volinfo || !volinfo->volname) + if (!volinfo || (volinfo->volname[0] == '\0')) return 0; - if (! strcmp (vme->option, "!nfs.rpc-auth-addr-allow")) { + if (! strcmp (vme->option, "!rpc-auth.addr.*.allow")) { ret = gf_asprintf (&aa, "rpc-auth.addr.%s.allow", volinfo->volname); @@ -1572,7 +3187,7 @@ nfs_option_handler (glusterfs_graph_t *graph, return -1; } - if (! strcmp (vme->option, "!nfs.rpc-auth-addr-reject")) { + if (! strcmp (vme->option, "!rpc-auth.addr.*.reject")) { ret = gf_asprintf (&aa, "rpc-auth.addr.%s.reject", volinfo->volname); @@ -1585,8 +3200,8 @@ nfs_option_handler (glusterfs_graph_t *graph, return -1; } - if (! strcmp (vme->option, "!nfs.rpc-auth-auth-unix")) { - ret = gf_asprintf (&aa, "rpc-auth.auth.unix.%s", + if (! strcmp (vme->option, "!rpc-auth.auth-unix.*")) { + ret = gf_asprintf (&aa, "rpc-auth.auth-unix.%s", volinfo->volname); if (ret != -1) { @@ -1597,8 +3212,8 @@ nfs_option_handler (glusterfs_graph_t *graph, if (ret) return -1; } - if (! strcmp (vme->option, "!nfs.rpc-auth-auth-null")) { - ret = gf_asprintf (&aa, "rpc-auth.auth.null.%s", + if (! strcmp (vme->option, "!rpc-auth.auth-null.*")) { + ret = gf_asprintf (&aa, "rpc-auth.auth-null.%s", volinfo->volname); if (ret != -1) { @@ -1610,7 +3225,7 @@ nfs_option_handler (glusterfs_graph_t *graph, return -1; } - if (! strcmp (vme->option, "!nfs-trusted-sync")) { + if (! strcmp (vme->option, "!nfs3.*.trusted-sync")) { ret = gf_asprintf (&aa, "nfs3.%s.trusted-sync", volinfo->volname); @@ -1623,7 +3238,7 @@ nfs_option_handler (glusterfs_graph_t *graph, return -1; } - if (! strcmp (vme->option, "!nfs-trusted-write")) { + if (! strcmp (vme->option, "!nfs3.*.trusted-write")) { ret = gf_asprintf (&aa, "nfs3.%s.trusted-write", volinfo->volname); @@ -1636,7 +3251,7 @@ nfs_option_handler (glusterfs_graph_t *graph, return -1; } - if (! strcmp (vme->option, "!nfs-volume-access")) { + if (! strcmp (vme->option, "!nfs3.*.volume-access")) { ret = gf_asprintf (&aa, "nfs3.%s.volume-access", volinfo->volname); @@ -1649,11 +3264,15 @@ nfs_option_handler (glusterfs_graph_t *graph, return -1; } - if (! strcmp (vme->option, "!nfs-export-dir")) { + if (! strcmp (vme->option, "!nfs3.*.export-dir")) { ret = gf_asprintf (&aa, "nfs3.%s.export-dir", volinfo->volname); if (ret != -1) { + ret = gf_canonicalize_path (vme->value); + if (ret) + return -1; + ret = xlator_set_option (xl, aa, vme->value); GF_FREE (aa); } @@ -1664,7 +3283,7 @@ nfs_option_handler (glusterfs_graph_t *graph, - if (! strcmp (vme->option, "!nfs.ports-insecure")) { + if (! strcmp (vme->option, "!rpc-auth.ports.*.insecure")) { ret = gf_asprintf (&aa, "rpc-auth.ports.%s.insecure", volinfo->volname); @@ -1691,6 +3310,13 @@ nfs_option_handler (glusterfs_graph_t *graph, return -1; } + if ( (strcmp (vme->voltype, "nfs/server") == 0) && + (vme->option && vme->option[0]!='!') ) { + ret = xlator_set_option (xl, vme->option, vme->value); + if (ret) + return -1; + } + /*key = strchr (vme->key, '.') + 1; @@ -1709,22 +3335,154 @@ nfs_option_handler (glusterfs_graph_t *graph, } static int -nfs_spec_option_handler (glusterfs_graph_t *graph, - struct volopt_map_entry *vme, void *param) +volgen_graph_set_iam_shd (volgen_graph_t *graph) { - int ret = 0; + xlator_t *trav; + int ret = 0; - ret = nfs_option_handler (graph, vme, param); - if (!ret) - return basic_option_handler (graph, vme, NULL); + for (trav = first_of (graph); trav; trav = trav->next) { + if (strcmp (trav->type, "cluster/replicate") != 0) + continue; + + ret = xlator_set_option (trav, "iam-self-heal-daemon", "yes"); + if (ret) + break; + } + return ret; +} + +static int +build_shd_graph (volgen_graph_t *graph, dict_t *mod_dict) +{ + volgen_graph_t cgraph = {0}; + glusterd_volinfo_t *voliter = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + dict_t *set_dict = NULL; + int ret = 0; + gf_boolean_t valid_config = _gf_false; + xlator_t *iostxl = NULL; + int rclusters = 0; + int replica_count = 0; + gf_boolean_t graph_check = _gf_false; + + this = THIS; + priv = this->private; + + set_dict = dict_new (); + if (!set_dict) { + ret = -ENOMEM; + goto out; + } + + graph_check = dict_get_str_boolean (mod_dict, "graph-check", 0); + iostxl = volgen_graph_add_as (graph, "debug/io-stats", "glustershd"); + if (!iostxl) { + ret = -1; + goto out; + } + + list_for_each_entry (voliter, &priv->volumes, vol_list) { + if (!graph_check && + (voliter->status != GLUSTERD_STATUS_STARTED)) + continue; + + if (!glusterd_is_volume_replicate (voliter)) + continue; + + replica_count = voliter->replica_count; + + valid_config = _gf_true; + + ret = dict_set_str (set_dict, "cluster.self-heal-daemon", "on"); + if (ret) + goto out; + + ret = dict_set_uint32 (set_dict, "trusted-client", + GF_CLIENT_TRUSTED); + if (ret) + goto out; + + dict_copy (voliter->dict, set_dict); + if (mod_dict) + dict_copy (mod_dict, set_dict); + + memset (&cgraph, 0, sizeof (cgraph)); + ret = volgen_graph_build_clients (&cgraph, voliter, set_dict, + NULL); + if (ret) + goto out; + + rclusters = volgen_graph_build_clusters (&cgraph, voliter, + "cluster/replicate", + "%s-replicate-%d", + voliter->brick_count, + replica_count); + if (rclusters < 0) { + ret = -1; + goto out; + } + + ret = volgen_graph_set_options_generic (&cgraph, set_dict, voliter, + shd_option_handler); + if (ret) + goto out; + + ret = volgen_graph_set_iam_shd (&cgraph); + if (ret) + goto out; + + ret = volgen_graph_merge_sub (graph, &cgraph, rclusters); + if (ret) + goto out; + + ret = volgen_graph_set_options_generic (graph, set_dict, + "client", + &loglevel_option_handler); + + if (ret) + gf_log (this->name, GF_LOG_WARNING, "changing loglevel " + "of self-heal daemon failed"); + + ret = volgen_graph_set_options_generic (graph, set_dict, + "client", + &sys_loglevel_option_handler); + if (ret) + gf_log (this->name, GF_LOG_WARNING, "changing syslog " + "level of self-heal daemon failed"); + + ret = volgen_graph_set_options_generic (graph, set_dict, + "client", + &logger_option_handler); + + if (ret) + gf_log (this->name, GF_LOG_WARNING, "changing logger " + "of self-heal daemon failed"); + + ret = volgen_graph_set_options_generic (graph, set_dict, + "client", + &log_format_option_handler); + if (ret) + gf_log (this->name, GF_LOG_WARNING, "changing log " + "format level of self-heal daemon failed"); + + ret = dict_reset (set_dict); + if (ret) + goto out; + } +out: + if (set_dict) + dict_unref (set_dict); + if (!valid_config) + ret = -EINVAL; return ret; } /* builds a graph for nfs server role, with option overrides in mod_dict */ static int -build_nfs_graph (glusterfs_graph_t *graph, dict_t *mod_dict) +build_nfs_graph (volgen_graph_t *graph, dict_t *mod_dict) { - glusterfs_graph_t cgraph = {{0,},}; + volgen_graph_t cgraph = {0,}; glusterd_volinfo_t *voliter = NULL; xlator_t *this = NULL; glusterd_conf_t *priv = NULL; @@ -1732,6 +3490,9 @@ build_nfs_graph (glusterfs_graph_t *graph, dict_t *mod_dict) xlator_t *nfsxl = NULL; char *skey = NULL; int ret = 0; + char nfs_xprt[16] = {0,}; + char *volname = NULL; + data_t *data = NULL; this = THIS; GF_ASSERT (this); @@ -1744,10 +3505,6 @@ build_nfs_graph (glusterfs_graph_t *graph, dict_t *mod_dict) return -1; } - ret = dict_set_str (set_dict, VKEY_PERF_STAT_PREFETCH, "off"); - if (ret) - goto out; - nfsxl = volgen_graph_add_as (graph, "nfs/server", "nfs-server"); if (!nfsxl) { ret = -1; @@ -1755,7 +3512,15 @@ build_nfs_graph (glusterfs_graph_t *graph, dict_t *mod_dict) } ret = xlator_set_option (nfsxl, "nfs.dynamic-volumes", "on"); if (ret) - goto out;; + goto out; + + ret = xlator_set_option (nfsxl, "nfs.nlm", "on"); + if (ret) + goto out; + + ret = xlator_set_option (nfsxl, "nfs.drc", "on"); + if (ret) + goto out; list_for_each_entry (voliter, &priv->volumes, vol_list) { if (voliter->status != GLUSTERD_STATUS_STARTED) @@ -1788,43 +3553,87 @@ build_nfs_graph (glusterfs_graph_t *graph, dict_t *mod_dict) /* If both RDMA and TCP are the transport_type, use RDMA for NFS client protocols */ - if (voliter->transport_type == GF_TRANSPORT_BOTH_TCP_RDMA) { - ret = dict_set_str (set_dict, "client-transport-type", - "rdma"); - if (ret) - goto out; - } - memset (&cgraph, 0, sizeof (cgraph)); - ret = build_client_graph (&cgraph, voliter, mod_dict); + if (mod_dict) + get_transport_type (voliter, mod_dict, nfs_xprt, _gf_true); + else + get_transport_type (voliter, voliter->dict, nfs_xprt, _gf_true); + + ret = dict_set_str (set_dict, "performance.stat-prefetch", "off"); + if (ret) + goto out; + + ret = dict_set_str (set_dict, "performance.client-io-threads", + "off"); + if (ret) + goto out; + + ret = dict_set_str (set_dict, "client-transport-type", + nfs_xprt); + if (ret) + goto out; + + ret = dict_set_uint32 (set_dict, "trusted-client", + GF_CLIENT_TRUSTED); if (ret) - goto out;; - ret = volgen_graph_merge_sub (graph, &cgraph); + goto out; + + ret = dict_set_str (set_dict, "nfs-volume-file", "yes"); + if (ret) + goto out; + + if (mod_dict && (data = dict_get (mod_dict, "volume-name"))) { + volname = data->data; + if (strcmp (volname, voliter->volname) == 0) + dict_copy (mod_dict, set_dict); + } + + ret = build_client_graph (&cgraph, voliter, set_dict); if (ret) goto out; if (mod_dict) { dict_copy (mod_dict, set_dict); - ret = volgen_graph_set_options_generic (graph, set_dict, voliter, - nfs_spec_option_handler); + ret = volgen_graph_set_options_generic (&cgraph, set_dict, voliter, + basic_option_handler); + } else { + ret = volgen_graph_set_options_generic (&cgraph, voliter->dict, voliter, + basic_option_handler); } - else - ret = volgen_graph_set_options_generic (graph, voliter->dict, voliter, - nfs_spec_option_handler); + if (ret) + goto out; + + ret = volgen_graph_merge_sub (graph, &cgraph, 1); + if (ret) + goto out; + ret = dict_reset (set_dict); + if (ret) + goto out; } + list_for_each_entry (voliter, &priv->volumes, vol_list) { + + if (mod_dict) { + ret = volgen_graph_set_options_generic (graph, mod_dict, voliter, + nfs_option_handler); + } else { + ret = volgen_graph_set_options_generic (graph, voliter->dict, voliter, + nfs_option_handler); + } + if (ret) + gf_log ("glusterd", GF_LOG_WARNING, "Could not set " + "vol-options for the volume %s", voliter->volname); + } out: + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); dict_destroy (set_dict); return ret; } - - - /**************************** * * Volume generation interface @@ -1851,11 +3660,49 @@ get_brick_filepath (char *filename, glusterd_volinfo_t *volinfo, brick); } +gf_boolean_t +glusterd_is_valid_volfpath (char *volname, char *brick) +{ + char volfpath[PATH_MAX] = {0,}; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_volinfo_t *volinfo = NULL; + int32_t ret = 0; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + + ret = glusterd_brickinfo_new_from_brick (brick, &brickinfo); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Failed to create brickinfo" + " for brick %s", brick ); + ret = 0; + goto out; + } + ret = glusterd_volinfo_new (&volinfo); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Failed to create volinfo"); + ret = 0; + goto out; + } + strncpy (volinfo->volname, volname, sizeof (volinfo->volname)); + get_brick_filepath (volfpath, volinfo, brickinfo); + + ret = (strlen (volfpath) < _POSIX_PATH_MAX); + +out: + if (brickinfo) + glusterd_brickinfo_delete (brickinfo); + if (volinfo) + glusterd_volinfo_unref (volinfo); + return ret; +} + static int glusterd_generate_brick_volfile (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo) { - glusterfs_graph_t graph = {{0,},}; + volgen_graph_t graph = {0,}; char filename[PATH_MAX] = {0,}; int ret = -1; @@ -1864,7 +3711,7 @@ glusterd_generate_brick_volfile (glusterd_volinfo_t *volinfo, get_brick_filepath (filename, volinfo, brickinfo); - ret = build_server_graph (&graph, volinfo, NULL, brickinfo->path); + ret = build_server_graph (&graph, volinfo, NULL, brickinfo); if (!ret) ret = volgen_write_volfile (&graph, filename); @@ -1873,6 +3720,101 @@ glusterd_generate_brick_volfile (glusterd_volinfo_t *volinfo, return ret; } +static int +build_quotad_graph (volgen_graph_t *graph, dict_t *mod_dict) +{ + volgen_graph_t cgraph = {0}; + glusterd_volinfo_t *voliter = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + dict_t *set_dict = NULL; + int ret = 0; + xlator_t *quotad_xl = NULL; + char *skey = NULL; + + this = THIS; + priv = this->private; + + set_dict = dict_new (); + if (!set_dict) { + ret = -ENOMEM; + goto out; + } + + quotad_xl = volgen_graph_add_as (graph, "features/quotad", "quotad"); + if (!quotad_xl) { + ret = -1; + goto out; + } + + list_for_each_entry (voliter, &priv->volumes, vol_list) { + if (voliter->status != GLUSTERD_STATUS_STARTED) + continue; + + if (1 != glusterd_is_volume_quota_enabled (voliter)) + continue; + + ret = dict_set_uint32 (set_dict, "trusted-client", + GF_CLIENT_TRUSTED); + if (ret) + goto out; + + dict_copy (voliter->dict, set_dict); + if (mod_dict) + dict_copy (mod_dict, set_dict); + + ret = gf_asprintf(&skey, "%s.volume-id", voliter->volname); + if (ret == -1) { + gf_log("", GF_LOG_ERROR, "Out of memory"); + goto out; + } + ret = xlator_set_option(quotad_xl, skey, voliter->volname); + GF_FREE(skey); + if (ret) + goto out; + + memset (&cgraph, 0, sizeof (cgraph)); + ret = volgen_graph_build_clients (&cgraph, voliter, set_dict, + NULL); + if (ret) + goto out; + + ret = volume_volgen_graph_build_clusters (&cgraph, voliter, + _gf_true); + if (ret) { + ret = -1; + goto out; + } + + if (mod_dict) { + dict_copy (mod_dict, set_dict); + ret = volgen_graph_set_options_generic (&cgraph, set_dict, + voliter, + basic_option_handler); + } else { + ret = volgen_graph_set_options_generic (&cgraph, + voliter->dict, + voliter, + basic_option_handler); + } + if (ret) + goto out; + + ret = volgen_graph_merge_sub (graph, &cgraph, 1); + if (ret) + goto out; + + ret = dict_reset (set_dict); + if (ret) + goto out; + } + +out: + if (set_dict) + dict_unref (set_dict); + return ret; +} + static void get_vol_tstamp_file (char *filename, glusterd_volinfo_t *volinfo) { @@ -1885,7 +3827,7 @@ get_vol_tstamp_file (char *filename, glusterd_volinfo_t *volinfo) PATH_MAX - strlen(filename) - 1); } -static int +int generate_brick_volfiles (glusterd_volinfo_t *volinfo) { glusterd_brickinfo_t *brickinfo = NULL; @@ -1899,7 +3841,7 @@ generate_brick_volfiles (glusterd_volinfo_t *volinfo) get_vol_tstamp_file (tstamp_file, volinfo); if (ret) { - ret = open (tstamp_file, O_WRONLY|O_CREAT|O_EXCL, 0644); + ret = open (tstamp_file, O_WRONLY|O_CREAT|O_EXCL, 0600); if (ret == -1 && errno == EEXIST) { gf_log ("", GF_LOG_DEBUG, "timestamp file exist"); ret = -2; @@ -1922,6 +3864,10 @@ generate_brick_volfiles (glusterd_volinfo_t *volinfo) } } + if (glusterd_volinfo_get_boolean(volinfo,"cluster.nsr") > 0) { + assign_groups(volinfo); + } + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { gf_log ("", GF_LOG_DEBUG, "Found a brick - %s:%s", brickinfo->hostname, @@ -1940,79 +3886,86 @@ out: return ret; } -static void -get_client_filepath (char *filename, glusterd_volinfo_t *volinfo) +static int +generate_single_transport_client_volfile (glusterd_volinfo_t *volinfo, + char *filepath, dict_t *dict) { - char path[PATH_MAX] = {0,}; - glusterd_conf_t *priv = NULL; + volgen_graph_t graph = {0,}; + int ret = -1; - priv = THIS->private; + ret = build_client_graph (&graph, volinfo, dict); + if (!ret) + ret = volgen_write_volfile (&graph, filepath); - GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); + volgen_graph_free (&graph); - snprintf (filename, PATH_MAX, "%s/%s-fuse.vol", - path, volinfo->volname); + return ret; } static void -get_rdma_client_filepath (char *filename, glusterd_volinfo_t *volinfo) +enumerate_transport_reqs (gf_transport_type type, char **types) { - char path[PATH_MAX] = {0,}; - glusterd_conf_t *priv = NULL; - - priv = THIS->private; - - GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); - - snprintf (filename, PATH_MAX, "%s/%s-rdma-fuse.vol", - path, volinfo->volname); + switch (type) { + case GF_TRANSPORT_TCP: + types[0] = "tcp"; + break; + case GF_TRANSPORT_RDMA: + types[0] = "rdma"; + break; + case GF_TRANSPORT_BOTH_TCP_RDMA: + types[0] = "tcp"; + types[1] = "rdma"; + break; + } } -static int -generate_client_volfile (glusterd_volinfo_t *volinfo) +int +generate_client_volfiles (glusterd_volinfo_t *volinfo, + glusterd_client_type_t client_type) { - glusterfs_graph_t graph = {{0,},}; - char filename[PATH_MAX] = {0,}; - int ret = -1; - dict_t *dict = NULL; - - get_client_filepath (filename, volinfo); - - if (volinfo->transport_type == GF_TRANSPORT_BOTH_TCP_RDMA) { - dict = dict_new (); - if (!dict) - goto out; - ret = dict_set_str (dict, "client-transport-type", "tcp"); + char filepath[PATH_MAX] = {0,}; + int ret = -1; + char *types[] = {NULL, NULL, NULL}; + int i = 0; + dict_t *dict = NULL; + gf_transport_type type = GF_TRANSPORT_TCP; + + enumerate_transport_reqs (volinfo->transport_type, types); + dict = dict_new (); + if (!dict) + goto out; + for (i = 0; types[i]; i++) { + memset (filepath, 0, sizeof (filepath)); + ret = dict_set_str (dict, "client-transport-type", types[i]); if (ret) goto out; - } - - ret = build_client_graph (&graph, volinfo, dict); - if (!ret) - ret = volgen_write_volfile (&graph, filename); - - volgen_graph_free (&graph); + type = transport_str_to_type (types[i]); - if (dict) { - /* This means, transport type is both RDMA and TCP */ - - memset (&graph, 0, sizeof (graph)); - get_rdma_client_filepath (filename, volinfo); - - ret = dict_set_str (dict, "client-transport-type", "rdma"); + ret = dict_set_uint32 (dict, "trusted-client", client_type); if (ret) goto out; - ret = build_client_graph (&graph, volinfo, dict); - if (!ret) - ret = volgen_write_volfile (&graph, filename); - - volgen_graph_free (&graph); + if (client_type == GF_CLIENT_TRUSTED) { + glusterd_get_trusted_client_filepath (filepath, + volinfo, + type); + } else { + glusterd_get_client_filepath (filepath, + volinfo, + type); + } - dict_unref (dict); + ret = generate_single_transport_client_volfile (volinfo, + filepath, + dict); + if (ret) + goto out; } - out: + if (dict) + dict_unref (dict); + + gf_log ("", GF_LOG_TRACE, "Returning %d", ret); return ret; } @@ -2024,7 +3977,7 @@ glusterd_create_rb_volfiles (glusterd_volinfo_t *volinfo, ret = glusterd_generate_brick_volfile (volinfo, brickinfo); if (!ret) - ret = generate_client_volfile (volinfo); + ret = generate_client_volfiles (volinfo, GF_CLIENT_TRUSTED); if (!ret) ret = glusterd_fetchspec_notify (THIS); @@ -2034,60 +3987,218 @@ glusterd_create_rb_volfiles (glusterd_volinfo_t *volinfo, int glusterd_create_volfiles_and_notify_services (glusterd_volinfo_t *volinfo) { - int ret = -1; + int ret = -1; + xlator_t *this = NULL; + + this = THIS; ret = generate_brick_volfiles (volinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, + gf_log (this->name, GF_LOG_ERROR, "Could not generate volfiles for bricks"); goto out; } - ret = generate_client_volfile (volinfo); + ret = generate_client_volfiles (volinfo, GF_CLIENT_TRUSTED); if (ret) { - gf_log ("", GF_LOG_ERROR, - "Could not generate volfile for client"); + gf_log (this->name, GF_LOG_ERROR, + "Could not generate trusted client volfiles"); + goto out; + } + + ret = generate_client_volfiles (volinfo, GF_CLIENT_OTHER); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Could not generate client volfiles"); goto out; } - ret = glusterd_fetchspec_notify (THIS); + ret = glusterd_fetchspec_notify (this); out: return ret; } -void -glusterd_get_nfs_filepath (char *filename) +int +glusterd_create_global_volfile (int (*builder) (volgen_graph_t *graph, + dict_t *set_dict), + char *filepath, dict_t *mod_dict) { - char path[PATH_MAX] = {0,}; - glusterd_conf_t *priv = NULL; + volgen_graph_t graph = {0,}; + int ret = -1; - priv = THIS->private; + ret = builder (&graph, mod_dict); + if (!ret) + ret = volgen_write_volfile (&graph, filepath); - GLUSTERD_GET_NFS_DIR (path, priv); + volgen_graph_free (&graph); - snprintf (filename, PATH_MAX, "%s/nfs-server.vol", path); + return ret; } int glusterd_create_nfs_volfile () { - glusterfs_graph_t graph = {{0,},}; - char filename[PATH_MAX] = {0,}; - int ret = -1; + char filepath[PATH_MAX] = {0,}; + glusterd_conf_t *conf = THIS->private; - glusterd_get_nfs_filepath (filename); + glusterd_get_nodesvc_volfile ("nfs", conf->workdir, + filepath, sizeof (filepath)); + return glusterd_create_global_volfile (build_nfs_graph, + filepath, NULL); +} - ret = build_nfs_graph (&graph, NULL); - if (!ret) - ret = volgen_write_volfile (&graph, filename); +int +glusterd_create_shd_volfile () +{ + char filepath[PATH_MAX] = {0,}; + int ret = -1; + glusterd_conf_t *conf = THIS->private; + dict_t *mod_dict = NULL; - volgen_graph_free (&graph); + mod_dict = dict_new (); + if (!mod_dict) + goto out; + + ret = dict_set_uint32 (mod_dict, "cluster.background-self-heal-count", 0); + if (ret) + goto out; + ret = dict_set_str (mod_dict, "cluster.data-self-heal", "on"); + if (ret) + goto out; + + ret = dict_set_str (mod_dict, "cluster.metadata-self-heal", "on"); + if (ret) + goto out; + + ret = dict_set_str (mod_dict, "cluster.entry-self-heal", "on"); + if (ret) + goto out; + + glusterd_get_nodesvc_volfile ("glustershd", conf->workdir, + filepath, sizeof (filepath)); + ret = glusterd_create_global_volfile (build_shd_graph, filepath, + mod_dict); +out: + if (mod_dict) + dict_unref (mod_dict); return ret; } int +glusterd_check_nfs_volfile_identical (gf_boolean_t *identical) +{ + char nfsvol[PATH_MAX] = {0,}; + char tmpnfsvol[PATH_MAX] = {0,}; + glusterd_conf_t *conf = NULL; + xlator_t *this = NULL; + int ret = -1; + int need_unlink = 0; + int tmp_fd = -1; + + this = THIS; + + GF_ASSERT (this); + GF_ASSERT (identical); + conf = this->private; + + glusterd_get_nodesvc_volfile ("nfs", conf->workdir, + nfsvol, sizeof (nfsvol)); + + snprintf (tmpnfsvol, sizeof (tmpnfsvol), "/tmp/gnfs-XXXXXX"); + + tmp_fd = mkstemp (tmpnfsvol); + if (tmp_fd < 0) { + gf_log ("", GF_LOG_WARNING, "Unable to create temp file %s: " + "(%s)", tmpnfsvol, strerror (errno)); + goto out; + } + + need_unlink = 1; + + ret = glusterd_create_global_volfile (build_nfs_graph, + tmpnfsvol, NULL); + if (ret) + goto out; + + ret = glusterd_check_files_identical (nfsvol, tmpnfsvol, + identical); + if (ret) + goto out; + +out: + if (need_unlink) + unlink (tmpnfsvol); + + if (tmp_fd >= 0) + close (tmp_fd); + + return ret; +} + +int +glusterd_check_nfs_topology_identical (gf_boolean_t *identical) +{ + char nfsvol[PATH_MAX] = {0,}; + char tmpnfsvol[PATH_MAX] = {0,}; + glusterd_conf_t *conf = NULL; + xlator_t *this = THIS; + int ret = -1; + int tmpclean = 0; + int tmpfd = -1; + + if ((!identical) || (!this) || (!this->private)) + goto out; + + conf = (glusterd_conf_t *) this->private; + + /* Fetch the original NFS volfile */ + glusterd_get_nodesvc_volfile ("nfs", conf->workdir, + nfsvol, sizeof (nfsvol)); + + /* Create the temporary NFS volfile */ + snprintf (tmpnfsvol, sizeof (tmpnfsvol), "/tmp/gnfs-XXXXXX"); + tmpfd = mkstemp (tmpnfsvol); + if (tmpfd < 0) { + gf_log (this->name, GF_LOG_WARNING, + "Unable to create temp file %s: (%s)", + tmpnfsvol, strerror (errno)); + goto out; + } + + tmpclean = 1; /* SET the flag to unlink() tmpfile */ + + ret = glusterd_create_global_volfile (build_nfs_graph, + tmpnfsvol, NULL); + if (ret) + goto out; + + /* Compare the topology of volfiles */ + ret = glusterd_check_topology_identical (nfsvol, tmpnfsvol, + identical); +out: + if (tmpfd >= 0) + close (tmpfd); + if (tmpclean) + unlink (tmpnfsvol); + return ret; +} + +int +glusterd_create_quotad_volfile () +{ + char filepath[PATH_MAX] = {0,}; + glusterd_conf_t *conf = THIS->private; + + glusterd_get_nodesvc_volfile ("quotad", conf->workdir, + filepath, sizeof (filepath)); + return glusterd_create_global_volfile (build_quotad_graph, + filepath, NULL); +} + + +int glusterd_delete_volfile (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo) { @@ -2106,37 +4217,106 @@ glusterd_delete_volfile (glusterd_volinfo_t *volinfo, } int +validate_shdopts (glusterd_volinfo_t *volinfo, + dict_t *val_dict, + char **op_errstr) +{ + volgen_graph_t graph = {0,}; + int ret = -1; + + graph.errstr = op_errstr; + + if (!glusterd_is_volume_replicate (volinfo)) { + ret = 0; + goto out; + } + ret = dict_set_str (val_dict, "graph-check", "on"); + if (ret) + goto out; + ret = build_shd_graph (&graph, val_dict); + if (!ret) + ret = graph_reconf_validateopt (&graph.graph, op_errstr); + + volgen_graph_free (&graph); + + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); +out: + dict_del (val_dict, "graph-check"); + return ret; +} + +int validate_nfsopts (glusterd_volinfo_t *volinfo, dict_t *val_dict, char **op_errstr) { - glusterfs_graph_t graph = {{0,},}; + volgen_graph_t graph = {0,}; int ret = -1; + char transport_type[16] = {0,}; + char *tt = NULL; + char err_str[4096] = {0,}; + xlator_t *this = THIS; + + GF_ASSERT (this); + + graph.errstr = op_errstr; + + get_vol_transport_type (volinfo, transport_type); + ret = dict_get_str (val_dict, "nfs.transport-type", &tt); + if (!ret) { + if (volinfo->transport_type != GF_TRANSPORT_BOTH_TCP_RDMA) { + snprintf (err_str, sizeof (err_str), "Changing nfs " + "transport type is allowed only for volumes " + "of transport type tcp,rdma"); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + *op_errstr = gf_strdup (err_str); + ret = -1; + goto out; + } + if (strcmp (tt,"tcp") && strcmp (tt,"rdma")) { + snprintf (err_str, sizeof (err_str), "wrong transport " + "type %s", tt); + *op_errstr = gf_strdup (err_str); + ret = -1; + goto out; + } + } + + ret = dict_set_str (val_dict, "volume-name", volinfo->volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to set volume name"); + goto out; + } ret = build_nfs_graph (&graph, val_dict); if (!ret) - ret = graph_reconf_validateopt (&graph, op_errstr); + ret = graph_reconf_validateopt (&graph.graph, op_errstr); volgen_graph_free (&graph); - gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); +out: + if (dict_get (val_dict, "volume-name")) + dict_del (val_dict, "volume-name"); + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } + int validate_clientopts (glusterd_volinfo_t *volinfo, - dict_t *val_dict, - char **op_errstr) + dict_t *val_dict, + char **op_errstr) { - glusterfs_graph_t graph = {{0,},}; - int ret = -1; + volgen_graph_t graph = {0,}; + int ret = -1; GF_ASSERT (volinfo); + graph.errstr = op_errstr; ret = build_client_graph (&graph, volinfo, val_dict); if (!ret) - ret = graph_reconf_validateopt (&graph, op_errstr); + ret = graph_reconf_validateopt (&graph.graph, op_errstr); volgen_graph_free (&graph); @@ -2146,20 +4326,20 @@ validate_clientopts (glusterd_volinfo_t *volinfo, int validate_brickopts (glusterd_volinfo_t *volinfo, - char *brickinfo_path, + glusterd_brickinfo_t *brickinfo, dict_t *val_dict, char **op_errstr) { - glusterfs_graph_t graph = {{0,},}; - int ret = -1; + volgen_graph_t graph = {0,}; + int ret = -1; GF_ASSERT (volinfo); + graph.errstr = op_errstr; - - ret = build_server_graph (&graph, volinfo, val_dict, brickinfo_path); + ret = build_server_graph (&graph, volinfo, val_dict, brickinfo); if (!ret) - ret = graph_reconf_validateopt (&graph, op_errstr); + ret = graph_reconf_validateopt (&graph.graph, op_errstr); volgen_graph_free (&graph); @@ -2179,28 +4359,30 @@ glusterd_validate_brickreconf (glusterd_volinfo_t *volinfo, gf_log ("", GF_LOG_DEBUG, "Validating %s", brickinfo->hostname); - ret = validate_brickopts (volinfo, brickinfo->path, val_dict, + ret = validate_brickopts (volinfo, brickinfo, val_dict, op_errstr); if (ret) goto out; } ret = 0; -out: +out: return ret; } -static void +static int _check_globalopt (dict_t *this, char *key, data_t *value, void *ret_val) { int *ret = NULL; ret = ret_val; if (*ret) - return; + return 0; if (!glusterd_check_globaloption (key)) *ret = 1; + + return 0; } int @@ -2230,23 +4412,34 @@ glusterd_validate_globalopts (glusterd_volinfo_t *volinfo, } ret = validate_nfsopts (volinfo, val_dict, op_errstr); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Could not Validate nfs"); + goto out; + } + ret = validate_shdopts (volinfo, val_dict, op_errstr); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Could not Validate self-heald"); + goto out; + } out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; } -static void +static int _check_localopt (dict_t *this, char *key, data_t *value, void *ret_val) { int *ret = NULL; ret = ret_val; if (*ret) - return; + return 0; if (!glusterd_check_localoption (key)) *ret = 1; + + return 0; } int @@ -2276,9 +4469,129 @@ glusterd_validate_reconfopts (glusterd_volinfo_t *volinfo, dict_t *val_dict, } ret = validate_nfsopts (volinfo, val_dict, op_errstr); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Could not Validate nfs"); + goto out; + } + + + ret = validate_shdopts (volinfo, val_dict, op_errstr); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Could not Validate self-heald"); + goto out; + } out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static struct volopt_map_entry * +_gd_get_vmep (char *key) { + char *completion = NULL; + struct volopt_map_entry *vmep = NULL; + int ret = 0; + + COMPLETE_OPTION ((char *)key, completion, ret); + for (vmep = glusterd_volopt_map; vmep->key; vmep++) { + if (strcmp (vmep->key, key) == 0) + return vmep; + } + + return NULL; +} + +uint32_t +glusterd_get_op_version_for_key (char *key) +{ + struct volopt_map_entry *vmep = NULL; + + GF_ASSERT (key); + + vmep = _gd_get_vmep (key); + if (vmep) + return vmep->op_version; + + return 0; +} + +gf_boolean_t +gd_is_client_option (char *key) +{ + struct volopt_map_entry *vmep = NULL; + + GF_ASSERT (key); + + vmep = _gd_get_vmep (key); + if (vmep && (vmep->flags & OPT_FLAG_CLIENT_OPT)) + return _gf_true; + + return _gf_false; +} + +gf_boolean_t +gd_is_xlator_option (char *key) +{ + struct volopt_map_entry *vmep = NULL; + + GF_ASSERT (key); + + vmep = _gd_get_vmep (key); + if (vmep && (vmep->flags & OPT_FLAG_XLATOR_OPT)) + return _gf_true; + + return _gf_false; +} + +volume_option_type_t +_gd_get_option_type (char *key) +{ + struct volopt_map_entry *vmep = NULL; + void *dl_handle = NULL; + volume_opt_list_t vol_opt_list = {{0},}; + int ret = -1; + volume_option_t *opt = NULL; + char *xlopt_key = NULL; + volume_option_type_t opt_type = GF_OPTION_TYPE_MAX; + + GF_ASSERT (key); + + vmep = _gd_get_vmep (key); + + if (vmep) { + INIT_LIST_HEAD (&vol_opt_list.list); + ret = xlator_volopt_dynload (vmep->voltype, &dl_handle, + &vol_opt_list); + if (ret) + goto out; + + if (_get_xlator_opt_key_from_vme (vmep, &xlopt_key)) + goto out; + + opt = xlator_volume_option_get_list (&vol_opt_list, xlopt_key); + _free_xlator_opt_key (xlopt_key); + + if (opt) + opt_type = opt->type; + } + +out: + if (dl_handle) { + dlclose (dl_handle); + dl_handle = NULL; + } + + return opt_type; +} + +gf_boolean_t +gd_is_boolean_option (char *key) +{ + GF_ASSERT (key); + + if (GF_OPTION_TYPE_BOOL == _gd_get_option_type (key)) + return _gf_true; + + return _gf_false; } |
