summaryrefslogtreecommitdiffstats
path: root/xlators/mgmt/glusterd/src/glusterd-volgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-volgen.c')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.c1646
1 files changed, 1254 insertions, 392 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
index a7856f782..6f3c69e7d 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c
@@ -1,22 +1,12 @@
/*
- Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
+ 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,8 @@
#endif
#include <fnmatch.h>
+#include <sys/wait.h>
+#include <dlfcn.h>
#if (HAVE_LIB_XML)
#include <libxml/encoding.h>
@@ -36,169 +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-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.min-free-inodes", "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.self-heal-daemon", "cluster/replicate", "!self-heal-daemon" , 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", "!brick-log-level", NULL, DOC, 0},
- {"diagnostics.client-log-level", "debug/io-stats", "!client-log-level", NULL, DOC, 0},
- {"diagnostics.brick-sys-log-level", "debug/io-stats", "!sys-log-level", NULL, DOC, 0},
- {"diagnostics.client-sys-log-level", "debug/io-stats", "!sys-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},
- {"performance.client-io-threads", "performance/io-threads", "!perf", "off", 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_NO_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", "!rpc-auth.auth-unix.*", NULL, DOC, 0},
- {"nfs.rpc-auth-null", "nfs/server", "!rpc-auth.auth.null.*", NULL, DOC, 0},
- {"nfs.rpc-auth-allow", "nfs/server", "!rpc-auth.addr.*.allow", NULL, DOC, 0},
- {"nfs.rpc-auth-reject", "nfs/server", "!rpc-auth.addr.*.reject", NULL, DOC, 0},
- {"nfs.ports-insecure", "nfs/server", "!rpc-auth.ports.*.insecure", NULL, DOC, 0},
- {"nfs.transport-type", "nfs/server", "!nfs.transport-type", NULL, DOC, 0},
-
- {"nfs.trusted-sync", "nfs/server", "!nfs3.*.trusted-sync", NULL, DOC, 0},
- {"nfs.trusted-write", "nfs/server", "!nfs3.*.trusted-write", NULL, DOC, 0},
- {"nfs.volume-access", "nfs/server", "!nfs3.*.volume-access", NULL, DOC, 0},
- {"nfs.export-dir", "nfs/server", "!nfs3.*.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", DOC, 0},
- {"server.statedump-path", "protocol/server", "statedump-path", NULL, NO_DOC, 0},
- {NULL, }
-};
-
-
+extern struct volopt_map_entry glusterd_volopt_map[];
/*********************************************
*
@@ -248,13 +89,14 @@ 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);
@@ -577,8 +419,7 @@ volopt_trie (char *key, char **hint)
}
out:
- if (patt[0])
- GF_FREE (patt[0]);
+ GF_FREE (patt[0]);
if (ret)
*hint = NULL;
@@ -610,26 +451,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)
@@ -643,6 +479,7 @@ 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
@@ -663,14 +500,10 @@ volgen_graph_set_options_generic (volgen_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;
@@ -684,8 +517,7 @@ volgen_graph_set_options_generic (volgen_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;
}
@@ -745,6 +577,108 @@ optget_option_handler (volgen_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)
@@ -913,20 +847,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;
}
@@ -939,42 +873,12 @@ 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");
-
- return -1;
- }
-
- 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 -1;
- }
-
- ret = !!vme.value;
-#endif
if (ret || !completion)
return ret;
@@ -982,7 +886,7 @@ glusterd_check_option_exists (char *key, char **completion)
trie:
ret = volopt_trie (key, completion);
if (ret) {
- gf_log ("", GF_LOG_ERROR,
+ gf_log (this->name, GF_LOG_ERROR,
"Some error occurred during keyword hinting");
}
@@ -1055,11 +959,68 @@ 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 (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;
@@ -1067,6 +1028,15 @@ volgen_write_volfile (volgen_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;
@@ -1074,8 +1044,19 @@ volgen_write_volfile (volgen_graph_t *graph, char *filename)
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)
@@ -1083,16 +1064,18 @@ volgen_write_volfile (volgen_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;
}
@@ -1423,21 +1406,28 @@ static int
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 *ptranst = NULL;
- char volume_id[64] = {0,};
- char tstamp_file[PATH_MAX] = {0,};
- int ret = 0;
- char *xlator = NULL;
- char *loglevel = NULL;
-
- 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,};
+
+ brickinfo = param;
+ path = brickinfo->path;
volname = volinfo->volname;
get_vol_transport_type (volinfo, transt);
@@ -1466,23 +1456,82 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
if (ret)
return -1;
+ 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;
+
+ 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;
+
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);
@@ -1495,6 +1544,18 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
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)
@@ -1512,9 +1573,25 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
return -1;
}
+ 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)
@@ -1524,6 +1601,49 @@ server_graph_builder (volgen_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;
+
+ 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 */
+ if (dict_get_str_boolean (set_dict, "features.compress", 0)) {
+ xl = volgen_graph_add (graph, "features/cdc", volname);
+ if (!xl) {
+ ret = -1;
+ goto out;
+ }
+ ret = dict_set_str (set_dict, "compress.mode", "server");
+ if (ret)
+ goto out;
+ }
+
xl = volgen_graph_add_as (graph, "debug/io-stats", path);
if (!xl)
return -1;
@@ -1535,6 +1655,35 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
if (ret)
return -1;
+ /*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 :
@@ -1548,9 +1697,9 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
/* builds a graph for server role , with option overrides in mod_dict */
static int
build_server_graph (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
- dict_t *mod_dict, char *path)
+ 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);
}
@@ -1558,12 +1707,42 @@ static int
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;
gf_boolean_t enabled = _gf_false;
volname = param;
- if (strcmp (vme->option, "!perf") != 0)
+ if (strcmp (vme->option, "!nfsperf") != 0)
return 0;
if (gf_string2boolean (vme->value, &enabled) == -1)
@@ -1634,8 +1813,7 @@ init_sethelp_xml_doc (xmlTextWriterPtr *writer, xmlBufferPtr *buf)
goto out;
}
- ret = xmlTextWriterStartElement(*writer,
- (xmlChar *)"volumeOptionsDefaults");
+ ret = xmlTextWriterStartElement(*writer, (xmlChar *)"options");
if (ret < 0) {
gf_log ("glusterd", GF_LOG_ERROR, "Could not create an "
"xmlElemetnt");
@@ -1661,7 +1839,7 @@ xml_add_volset_element (xmlTextWriterPtr writer, const char *name,
GF_ASSERT (name);
- ret = xmlTextWriterStartElement(writer, (xmlChar *) "volumeOption");
+ ret = xmlTextWriterStartElement(writer, (xmlChar *) "option");
if (ret < 0) {
gf_log ("glusterd", GF_LOG_ERROR, "Could not create an "
"xmlElemetnt");
@@ -1714,7 +1892,7 @@ xml_add_volset_element (xmlTextWriterPtr writer, const char *name,
#endif
static int
-get_key_from_volopt ( struct volopt_map_entry *vme, char **key)
+_get_xlator_opt_key_from_vme ( struct volopt_map_entry *vme, char **key)
{
int ret = 0;
@@ -1722,25 +1900,32 @@ get_key_from_volopt ( struct volopt_map_entry *vme, char **key)
GF_ASSERT (key);
- if (vme->option) {
- if (vme->option[0] == '!') {
- *key = vme->option + 1;
- if (!*key[0])
- ret = -1;
+ 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 = vme->option;
- }
- } else {
- *key = strchr (vme->key, '.');
- if (*key) {
- (*key) ++;
- if (!*key[0])
+ *key = strchr (vme->key, '.');
+ if (*key) {
+ (*key) ++;
+ if (!*key[0])
+ ret = -1;
+ } else {
ret = -1;
- } else {
- ret = -1;
+ }
}
}
-
if (ret)
gf_log ("glusterd", GF_LOG_ERROR, "Wrong entry found in "
"glusterd_volopt_map entry %s", vme->key);
@@ -1750,23 +1935,32 @@ get_key_from_volopt ( struct volopt_map_entry *vme, char **key)
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 (gf_boolean_t xml_out)
+glusterd_get_volopt_content (dict_t * ctx, gf_boolean_t xml_out)
{
-
- char *xlator_type = NULL;
void *dl_handle = NULL;
- volume_opt_list_t vol_opt_handle = {{0},};
+ 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[8192] = {0, };
+ char output_string[25600] = {0, };
char *output = NULL;
- char tmp_str[1024] = {0, };
- dict_t *ctx = NULL;
+ char tmp_str[2048] = {0, };
#if (HAVE_LIB_XML)
xmlTextWriterPtr writer = NULL;
xmlBufferPtr buf = NULL;
@@ -1778,51 +1972,73 @@ glusterd_get_volopt_content (gf_boolean_t xml_out)
}
#endif
- ctx = glusterd_op_get_ctx ();
-
- if (!ctx) {
- /*extract the vol-set-help output only in host glusterd*/
- ret = 0;
- goto out;
- }
-
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) )
+ if ((vme->type == NO_DOC) || (vme->type == GLOBAL_NO_DOC))
continue;
- if (get_key_from_volopt (vme, &key))
- goto out; /*Some error while getin key*/
+ 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*/
+ }
- if (!xlator_type || strcmp (vme->voltype, xlator_type)){
ret = xlator_volopt_dynload (vme->voltype,
- &dl_handle,
- &vol_opt_handle);
- if (ret)
- continue;
- }
+ &dl_handle,
+ &vol_opt_handle);
- ret = xlator_option_info_list (&vol_opt_handle, key,
- &def_val, &descr);
- if (ret) /*Swallow Error i.e if option not found*/
- continue;
+ 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))
- goto out;
+ def_val, descr)) {
+ ret = -1;
+ goto cont;
+ }
#else
gf_log ("glusterd", GF_LOG_ERROR, "Libxml not present");
#endif
} else {
- snprintf (tmp_str, 1024, "Option: %s\nDefault "
+ 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)
@@ -1849,7 +2065,7 @@ glusterd_get_volopt_content (gf_boolean_t xml_out)
}
ret = dict_set_dynstr (ctx, "help-str", output);
- out:
+out:
gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret);
return ret;
@@ -1861,10 +2077,14 @@ volgen_graph_build_clients (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
{
int i = 0;
int ret = -1;
+ uint32_t client_type = GF_CLIENT_OTHER;
char transt[16] = {0,};
char *volname = NULL;
- glusterd_brickinfo_t *brick = NULL;
- xlator_t *xl = NULL;
+ char *str = NULL;
+ glusterd_brickinfo_t *brick = NULL;
+ xlator_t *xl = NULL;
+ char *ssl_str = NULL;
+ gf_boolean_t ssl_bool;
volname = volinfo->volname;
@@ -1907,8 +2127,45 @@ volgen_graph_build_clients (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
ret = xlator_set_option (xl, "transport-type", transt);
if (ret)
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) "
@@ -1959,6 +2216,7 @@ volgen_graph_build_clusters (volgen_graph_t *graph,
if (trav == txl)
break;
+
i++;
}
@@ -2069,13 +2327,33 @@ volgen_graph_build_dht_cluster (volgen_graph_t *graph,
int ret = -1;
char *decommissioned_children = NULL;
xlator_t *dht = NULL;
+ char *voltype = "cluster/distribute";
+
+ /* 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";
- GF_ASSERT (child_count > 1);
clusters = volgen_graph_build_clusters (graph, volinfo,
- "cluster/distribute", "%s-dht",
- child_count, child_count);
+ voltype,
+ "%s-dht",
+ child_count,
+ child_count);
if (clusters < 0)
goto out;
+
dht = first_of (graph);
ret = _graph_get_decommissioned_children (dht, volinfo,
&decommissioned_children);
@@ -2089,8 +2367,7 @@ volgen_graph_build_dht_cluster (volgen_graph_t *graph,
}
ret = 0;
out:
- if (decommissioned_children)
- GF_FREE (decommissioned_children);
+ GF_FREE (decommissioned_children);
return ret;
}
@@ -2163,24 +2440,51 @@ volume_volgen_graph_build_clusters (volgen_graph_t *graph,
build_distribute:
dist_count = volinfo->brick_count / volinfo->dist_leaf_count;
- if (dist_count > 1) {
- ret = volgen_graph_build_dht_cluster (graph, volinfo,
- dist_count);
- if (ret)
- goto out;
+ if (!dist_count) {
+ ret = -1;
+ goto out;
}
+
+ ret = volgen_graph_build_dht_cluster (graph, volinfo,
+ dist_count);
+ if (ret == -1)
+ 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,
+ volname,
+ &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;
+ int ret = 0;
+ xlator_t *xl = NULL;
+ char *volname = NULL;
volname = volinfo->volname;
ret = volgen_graph_build_clients (graph, volinfo, set_dict, param);
@@ -2188,9 +2492,34 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
goto out;
ret = volume_volgen_graph_build_clusters (graph, volinfo);
- if (ret)
+ if (ret == -1)
goto out;
+ /* Check for compress volume option, and add it to the graph on client side */
+ if (dict_get_str_boolean (set_dict, "features.compress", 0)) {
+ xl = volgen_graph_add (graph, "features/cdc", volname);
+ if (!xl) {
+ ret = -1;
+ goto out;
+ }
+ ret = dict_set_str (set_dict, "compress.mode", "client");
+ if (ret)
+ goto out;
+
+ }
+
+ ret = glusterd_volinfo_get_boolean (volinfo, "features.encryption");
+ if (ret == -1)
+ goto out;
+ if (ret) {
+ xl = volgen_graph_add (graph, "encryption/crypt", volname);
+
+ if (!xl) {
+ ret = -1;
+ goto out;
+ }
+ }
+
ret = glusterd_volinfo_get_boolean (volinfo, VKEY_FEATURES_QUOTA);
if (ret == -1)
goto out;
@@ -2203,11 +2532,29 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
}
}
- ret = volgen_graph_set_options_generic (graph, set_dict, volname,
- &perfxl_option_handler);
+
+ 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;
+ }
+ }
+
+ 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)
@@ -2216,9 +2563,15 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
ret = volgen_graph_set_options_generic (graph, set_dict, "client",
&loglevel_option_handler);
- if (!ret)
- 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 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");
out:
return ret;
}
@@ -2233,20 +2586,35 @@ build_client_graph (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
&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
shd_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme,
- void *param)
+ void *param)
{
int ret = 0;
struct volopt_map_entry new_vme = {0};
- int shd = 0;
+ char *shd_option = NULL;
- shd = !strcmp (vme->option, "!self-heal-daemon");
- if ((vme->option[0] == '!') && !shd)
+ shd_option = gd_get_matching_option (gd_shd_options, vme->option);
+ if ((vme->option[0] == '!') && !shd_option)
goto out;
new_vme = *vme;
- if (shd)
- new_vme.option = "self-heal-daemon";
+ if (shd_option) {
+ new_vme.option = shd_option + 1;//option with out '!'
+ }
ret = no_filter_option_handler (graph, &new_vme, param);
out:
@@ -2270,7 +2638,7 @@ nfs_option_handler (volgen_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, "!rpc-auth.addr.*.allow")) {
@@ -2300,7 +2668,7 @@ nfs_option_handler (volgen_graph_t *graph,
}
if (! strcmp (vme->option, "!rpc-auth.auth-unix.*")) {
- ret = gf_asprintf (&aa, "rpc-auth.auth.unix.%s",
+ ret = gf_asprintf (&aa, "rpc-auth.auth-unix.%s",
volinfo->volname);
if (ret != -1) {
@@ -2311,8 +2679,8 @@ nfs_option_handler (volgen_graph_t *graph,
if (ret)
return -1;
}
- if (! strcmp (vme->option, "!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) {
@@ -2368,6 +2736,10 @@ nfs_option_handler (volgen_graph_t *graph,
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);
}
@@ -2430,6 +2802,23 @@ nfs_option_handler (volgen_graph_t *graph,
}
static int
+volgen_graph_set_iam_shd (volgen_graph_t *graph)
+{
+ xlator_t *trav;
+ int ret = 0;
+
+ 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};
@@ -2440,8 +2829,9 @@ build_shd_graph (volgen_graph_t *graph, dict_t *mod_dict)
int ret = 0;
gf_boolean_t valid_config = _gf_false;
xlator_t *iostxl = NULL;
- int rclusters = 0;
+ int rclusters = 0;
int replica_count = 0;
+ gf_boolean_t graph_check = _gf_false;
this = THIS;
priv = this->private;
@@ -2452,6 +2842,7 @@ build_shd_graph (volgen_graph_t *graph, dict_t *mod_dict)
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;
@@ -2459,7 +2850,8 @@ build_shd_graph (volgen_graph_t *graph, dict_t *mod_dict)
}
list_for_each_entry (voliter, &priv->volumes, vol_list) {
- if (voliter->status != GLUSTERD_STATUS_STARTED)
+ if (!graph_check &&
+ (voliter->status != GLUSTERD_STATUS_STARTED))
continue;
if (!glusterd_is_volume_replicate (voliter))
@@ -2473,6 +2865,11 @@ build_shd_graph (volgen_graph_t *graph, dict_t *mod_dict)
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);
@@ -2498,10 +2895,29 @@ build_shd_graph (volgen_graph_t *graph, dict_t *mod_dict)
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 = dict_reset (set_dict);
if (ret)
goto out;
@@ -2527,6 +2943,8 @@ build_nfs_graph (volgen_graph_t *graph, dict_t *mod_dict)
char *skey = NULL;
int ret = 0;
char nfs_xprt[16] = {0,};
+ char *volname = NULL;
+ data_t *data = NULL;
this = THIS;
GF_ASSERT (this);
@@ -2548,6 +2966,14 @@ build_nfs_graph (volgen_graph_t *graph, dict_t *mod_dict)
if (ret)
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)
continue;
@@ -2585,16 +3011,35 @@ build_nfs_graph (volgen_graph_t *graph, dict_t *mod_dict)
else
get_transport_type (voliter, voliter->dict, nfs_xprt, _gf_true);
- ret = dict_set_str (set_dict, VKEY_PERF_STAT_PREFETCH, "off");
+ 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");
+ 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 = 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;
@@ -2677,16 +3122,21 @@ glusterd_is_valid_volfpath (char *volname, char *brick)
glusterd_brickinfo_t *brickinfo = NULL;
glusterd_volinfo_t *volinfo = NULL;
int32_t ret = 0;
+ xlator_t *this = NULL;
- ret = glusterd_brickinfo_from_brick (brick, &brickinfo);
+ this = THIS;
+ GF_ASSERT (this);
+
+ ret = glusterd_brickinfo_new_from_brick (brick, &brickinfo);
if (ret) {
- gf_log ("", GF_LOG_WARNING, "brick path validation failed");
+ 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 ("", GF_LOG_WARNING, "brick path validation failed");
+ gf_log (this->name, GF_LOG_WARNING, "Failed to create volinfo");
ret = 0;
goto out;
}
@@ -2716,7 +3166,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);
@@ -2725,8 +3175,6 @@ glusterd_generate_brick_volfile (glusterd_volinfo_t *volinfo,
return ret;
}
-
-
static void
get_vol_tstamp_file (char *filename, glusterd_volinfo_t *volinfo)
{
@@ -2753,7 +3201,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;
@@ -2810,25 +3258,6 @@ generate_single_transport_client_volfile (glusterd_volinfo_t *volinfo,
return ret;
}
-void
-get_client_filepath (char *filepath, glusterd_volinfo_t *volinfo, gf_transport_type type)
-{
- char path[PATH_MAX] = {0,};
- glusterd_conf_t *priv = NULL;
-
- priv = THIS->private;
-
- GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv);
-
- if ((volinfo->transport_type == GF_TRANSPORT_BOTH_TCP_RDMA) &&
- (type == GF_TRANSPORT_RDMA))
- snprintf (filepath, PATH_MAX, "%s/%s.rdma-fuse.vol",
- path, volinfo->volname);
- else
- snprintf (filepath, PATH_MAX, "%s/%s-fuse.vol",
- path, volinfo->volname);
-}
-
static void
enumerate_transport_reqs (gf_transport_type type, char **types)
{
@@ -2846,8 +3275,9 @@ enumerate_transport_reqs (gf_transport_type type, char **types)
}
}
-static int
-generate_client_volfiles (glusterd_volinfo_t *volinfo)
+int
+generate_client_volfiles (glusterd_volinfo_t *volinfo,
+ glusterd_client_type_t client_type)
{
char filepath[PATH_MAX] = {0,};
int ret = -1;
@@ -2866,7 +3296,21 @@ generate_client_volfiles (glusterd_volinfo_t *volinfo)
if (ret)
goto out;
type = transport_str_to_type (types[i]);
- get_client_filepath (filepath, volinfo, type);
+
+ ret = dict_set_uint32 (dict, "trusted-client", client_type);
+ if (ret)
+ goto out;
+
+ if (client_type == GF_CLIENT_TRUSTED) {
+ glusterd_get_trusted_client_filepath (filepath,
+ volinfo,
+ type);
+ } else {
+ glusterd_get_client_filepath (filepath,
+ volinfo,
+ type);
+ }
+
ret = generate_single_transport_client_volfile (volinfo,
filepath,
dict);
@@ -2887,7 +3331,7 @@ glusterd_create_rb_volfiles (glusterd_volinfo_t *volinfo,
ret = glusterd_generate_brick_volfile (volinfo, brickinfo);
if (!ret)
- ret = generate_client_volfiles (volinfo);
+ ret = generate_client_volfiles (volinfo, GF_CLIENT_TRUSTED);
if (!ret)
ret = glusterd_fetchspec_notify (THIS);
@@ -2897,23 +3341,33 @@ 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_volfiles (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 = glusterd_fetchspec_notify (THIS);
+ 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);
out:
return ret;
@@ -2968,6 +3422,14 @@ glusterd_create_shd_volfile ()
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,
@@ -2979,6 +3441,106 @@ out:
}
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_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_delete_volfile (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo)
{
@@ -2997,6 +3559,35 @@ 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)
@@ -3006,6 +3597,9 @@ validate_nfsopts (glusterd_volinfo_t *volinfo,
char transport_type[16] = {0,};
char *tt = NULL;
char err_str[4096] = {0,};
+ xlator_t *this = THIS;
+
+ GF_ASSERT (this);
graph.errstr = op_errstr;
@@ -3016,7 +3610,7 @@ validate_nfsopts (glusterd_volinfo_t *volinfo,
snprintf (err_str, sizeof (err_str), "Changing nfs "
"transport type is allowed only for volumes "
"of transport type tcp,rdma");
- gf_log ("", GF_LOG_ERROR, "%s", err_str);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
*op_errstr = gf_strdup (err_str);
ret = -1;
goto out;
@@ -3030,6 +3624,12 @@ validate_nfsopts (glusterd_volinfo_t *volinfo,
}
}
+ 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.graph, op_errstr);
@@ -3037,17 +3637,20 @@ validate_nfsopts (glusterd_volinfo_t *volinfo,
volgen_graph_free (&graph);
out:
- gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret);
+ 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)
{
volgen_graph_t graph = {0,};
- int ret = -1;
+ int ret = -1;
GF_ASSERT (volinfo);
@@ -3065,18 +3668,18 @@ 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)
{
volgen_graph_t graph = {0,};
- int ret = -1;
+ 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.graph, op_errstr);
@@ -3098,28 +3701,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
@@ -3149,23 +3754,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
@@ -3195,9 +3811,255 @@ 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;
+}
+
+/* This function will restore origin volume to it's snap.
+ * The restore operation will simply replace the Gluster origin
+ * volume with the snap volume.
+ * TODO: Multi-volume delete to be done.
+ * Cleanup in case of restore failure is pending.
+ *
+ * @param orig_vol volinfo of origin volume
+ * @param snap_vol volinfo of snapshot volume
+ *
+ * @return 0 on success and negative value on error
+ */
+int
+gd_restore_snap_volume (dict_t *rsp_dict,
+ glusterd_volinfo_t *orig_vol,
+ glusterd_volinfo_t *snap_vol)
+{
+ int ret = -1;
+ glusterd_volinfo_t *new_volinfo = NULL;
+ glusterd_snap_t *snap = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ glusterd_volinfo_t *temp_volinfo = NULL;
+ glusterd_volinfo_t *voliter = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ GF_ASSERT (rsp_dict);
+ conf = this->private;
+ GF_ASSERT (conf);
+
+ GF_VALIDATE_OR_GOTO (this->name, orig_vol, out);
+ GF_VALIDATE_OR_GOTO (this->name, snap_vol, out);
+ snap = snap_vol->snapshot;
+ GF_VALIDATE_OR_GOTO (this->name, snap, out);
+
+ /* Snap volume must be stoped before performing the
+ * restore operation.
+ */
+ ret = glusterd_stop_volume (snap_vol);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to stop "
+ "snap volume");
+ goto out;
+ }
+
+ /* Create a new volinfo for the restored volume */
+ ret = glusterd_volinfo_dup (snap_vol, &new_volinfo, _gf_true);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to create volinfo");
+ goto out;
+ }
+
+ /* Following entries need to be derived from origin volume. */
+ strcpy (new_volinfo->volname, orig_vol->volname);
+ uuid_copy (new_volinfo->volume_id, orig_vol->volume_id);
+ new_volinfo->snap_count = orig_vol->snap_count;
+ new_volinfo->snap_max_hard_limit = orig_vol->snap_max_hard_limit;
+ new_volinfo->is_volume_restored = _gf_true;
+
+ /* Bump the version of the restored volume, so that nodes *
+ * which are done can sync during handshake */
+ new_volinfo->version = orig_vol->version;
+
+ list_for_each_entry_safe (voliter, temp_volinfo,
+ &orig_vol->snap_volumes, snapvol_list) {
+ list_add_tail (&voliter->snapvol_list,
+ &new_volinfo->snap_volumes);
+ }
+ /* Copy the snap vol info to the new_volinfo.*/
+ ret = glusterd_snap_volinfo_restore (rsp_dict, new_volinfo, snap_vol);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to restore snap");
+ (void)glusterd_volinfo_delete (new_volinfo);
+ goto out;
+ }
+
+ /* If the orig_vol is already restored then we should delete
+ * the backend LVMs */
+ if (orig_vol->is_volume_restored) {
+ ret = glusterd_lvm_snapshot_remove (rsp_dict, orig_vol);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to remove "
+ "LVM backend");
+ (void)glusterd_volinfo_delete (new_volinfo);
+ goto out;
+ }
+ }
+
+ /* Once the new_volinfo is completely constructed then delete
+ * the orinal volinfo
+ */
+ ret = glusterd_volinfo_delete (orig_vol);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to delete volinfo");
+ (void)glusterd_volinfo_delete (new_volinfo);
+ goto out;
+ }
+
+ /* New volinfo always shows the status as created. Therefore
+ * set the status to stop. */
+ glusterd_set_volume_status (new_volinfo, GLUSTERD_STATUS_STOPPED);
+
+ list_add_tail (&new_volinfo->vol_list, &conf->volumes);
+
+ /* Now delete the snap entry. As a first step delete the snap
+ * volume information stored in store. */
+ ret = glusterd_snap_remove (rsp_dict, snap, _gf_false, _gf_true);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "Failed to delete "
+ "snap %s", snap->snapname);
+ goto out;
+ }
+
+ ret = glusterd_store_volinfo (new_volinfo,
+ GLUSTERD_VOLINFO_VER_AC_INCREMENT);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to store volinfo");
+ goto out;
+ }
+
+ ret = 0;
+out:
+
+ return ret;
}