summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs/src/graph.c')
-rw-r--r--libglusterfs/src/graph.c428
1 files changed, 319 insertions, 109 deletions
diff --git a/libglusterfs/src/graph.c b/libglusterfs/src/graph.c
index a2d03fa0b..e76df1ca5 100644
--- a/libglusterfs/src/graph.c
+++ b/libglusterfs/src/graph.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU 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/>.
+ 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
@@ -29,28 +20,23 @@
#include "defaults.h"
-
-
#if 0
static void
_gf_dump_details (int argc, char **argv)
{
extern FILE *gf_log_logfile;
int i = 0;
- char timestr[256];
+ char timestr[64];
time_t utime = 0;
- struct tm *tm = NULL;
pid_t mypid = 0;
struct utsname uname_buf = {{0, }, };
int uname_ret = -1;
- utime = time (NULL);
- tm = localtime (&utime);
mypid = getpid ();
uname_ret = uname (&uname_buf);
- /* Which git? What time? */
- strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm);
+ utime = time (NULL);
+ gf_time_fmt (timestr, sizeof timestr, utime, gf_timefmt_FT);
fprintf (gf_log_logfile,
"========================================"
"========================================\n");
@@ -84,44 +70,6 @@ _gf_dump_details (int argc, char **argv)
#endif
-static int
-_log_if_option_is_invalid (xlator_t *xl, data_pair_t *pair)
-{
- volume_opt_list_t *vol_opt = NULL;
- volume_option_t *opt = NULL;
- int i = 0;
- int index = 0;
- int found = 0;
-
- /* Get the first volume_option */
- list_for_each_entry (vol_opt, &xl->volume_options, list) {
- /* Warn for extra option */
- if (!vol_opt->given_opt)
- break;
-
- opt = vol_opt->given_opt;
- for (index = 0;
- ((index < ZR_OPTION_MAX_ARRAY_SIZE) &&
- (opt[index].key && opt[index].key[0])); index++)
- for (i = 0; (i < ZR_VOLUME_MAX_NUM_KEY) &&
- opt[index].key[i]; i++) {
- if (fnmatch (opt[index].key[i],
- pair->key,
- FNM_NOESCAPE) == 0) {
- found = 1;
- break;
- }
- }
- }
-
- if (!found) {
- gf_log (xl->name, GF_LOG_WARNING,
- "option '%s' is not recognized",
- pair->key);
- }
- return 0;
-}
-
int
glusterfs_xlator_link (xlator_t *pxl, xlator_t *cxl)
@@ -169,7 +117,8 @@ glusterfs_graph_set_first (glusterfs_graph_t *graph, xlator_t *xl)
int
glusterfs_graph_insert (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx,
- const char *type, const char *name)
+ const char *type, const char *name,
+ gf_boolean_t autoload)
{
xlator_t *ixl = NULL;
@@ -195,6 +144,8 @@ glusterfs_graph_insert (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx,
if (!ixl->name)
goto err;
+ ixl->is_autoloaded = autoload;
+
if (xlator_set_type (ixl, type) == -1) {
gf_log ("glusterfs", GF_LOG_ERROR,
"%s (%s) initialization failed",
@@ -213,23 +164,37 @@ err:
return -1;
}
-
int
-glusterfs_graph_readonly (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
+glusterfs_graph_acl (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
{
int ret = 0;
cmd_args_t *cmd_args = NULL;
cmd_args = &ctx->cmd_args;
- if (!cmd_args->read_only)
+ if (!cmd_args->acl)
return 0;
- ret = glusterfs_graph_insert (graph, ctx, "features/read-only",
- "readonly-autoload");
+ ret = glusterfs_graph_insert (graph, ctx, "system/posix-acl",
+ "posix-acl-autoload", 1);
return ret;
}
+int
+glusterfs_graph_worm (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
+{
+ int ret = 0;
+ cmd_args_t *cmd_args = NULL;
+
+ cmd_args = &ctx->cmd_args;
+
+ if (!cmd_args->worm)
+ return 0;
+
+ ret = glusterfs_graph_insert (graph, ctx, "features/worm",
+ "worm-autoload", 1);
+ return ret;
+}
int
glusterfs_graph_mac_compat (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
@@ -243,11 +208,26 @@ glusterfs_graph_mac_compat (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
return 0;
ret = glusterfs_graph_insert (graph, ctx, "features/mac-compat",
- "mac-compat-autoload");
+ "mac-compat-autoload", 1);
return ret;
}
+int
+glusterfs_graph_gfid_access (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
+{
+ int ret = 0;
+ cmd_args_t *cmd_args = NULL;
+
+ cmd_args = &ctx->cmd_args;
+
+ if (!cmd_args->aux_gfid_mount)
+ return 0;
+
+ ret = glusterfs_graph_insert (graph, ctx, "features/gfid-access",
+ "gfid-access-autoload", 1);
+ return ret;
+}
static void
gf_add_cmdline_options (glusterfs_graph_t *graph, cmd_args_t *cmd_args)
@@ -267,7 +247,7 @@ gf_add_cmdline_options (glusterfs_graph_t *graph, cmd_args_t *cmd_args)
cmd_option->key,
cmd_option->value);
if (ret == 0) {
- gf_log (trav->name, GF_LOG_WARNING,
+ gf_log (trav->name, GF_LOG_INFO,
"adding option '%s' for "
"volume '%s' with value '%s'",
cmd_option->key, trav->name,
@@ -289,9 +269,9 @@ gf_add_cmdline_options (glusterfs_graph_t *graph, cmd_args_t *cmd_args)
int
glusterfs_graph_validate_options (glusterfs_graph_t *graph)
{
- volume_opt_list_t *vol_opt = NULL;
xlator_t *trav = NULL;
int ret = -1;
+ char *errstr = NULL;
trav = graph->first;
@@ -299,14 +279,10 @@ glusterfs_graph_validate_options (glusterfs_graph_t *graph)
if (list_empty (&trav->volume_options))
continue;
- vol_opt = list_entry (trav->volume_options.next,
- volume_opt_list_t, list);
-
- ret = validate_xlator_volume_options (trav,
- vol_opt->given_opt);
+ ret = xlator_options_validate (trav, trav->options, &errstr);
if (ret) {
gf_log (trav->name, GF_LOG_ERROR,
- "validating translator failed");
+ "validation failed: %s", errstr);
return ret;
}
trav = trav->next;
@@ -338,35 +314,46 @@ glusterfs_graph_init (glusterfs_graph_t *graph)
}
-int
-glusterfs_graph_unknown_options (glusterfs_graph_t *graph)
+static int
+_log_if_unknown_option (dict_t *dict, char *key, data_t *value, void *data)
{
- data_pair_t *pair = NULL;
- xlator_t *trav = NULL;
+ volume_option_t *found = NULL;
+ xlator_t *xl = NULL;
- trav = graph->first;
+ xl = data;
- /* Validate again phase */
- while (trav) {
- pair = trav->options->members_list;
- while (pair) {
- _log_if_option_is_invalid (trav, pair);
- pair = pair->next;
- }
- trav = trav->next;
+ found = xlator_volume_option_get (xl, key);
+
+ if (!found) {
+ gf_log (xl->name, GF_LOG_WARNING,
+ "option '%s' is not recognized", key);
}
return 0;
}
+static void
+_xlator_check_unknown_options (xlator_t *xl, void *data)
+{
+ dict_foreach (xl->options, _log_if_unknown_option, xl);
+}
+
+
+int
+glusterfs_graph_unknown_options (glusterfs_graph_t *graph)
+{
+ xlator_foreach (graph->first, _xlator_check_unknown_options, NULL);
+ return 0;
+}
+
+
void
fill_uuid (char *uuid, int size)
{
char hostname[256] = {0,};
struct timeval tv = {0,};
- struct tm now = {0, };
- char now_str[32];
+ char now_str[64];
if (gettimeofday (&tv, NULL) == -1) {
gf_log ("graph", GF_LOG_ERROR,
@@ -380,8 +367,7 @@ fill_uuid (char *uuid, int size)
strerror (errno));
}
- localtime_r (&tv.tv_sec, &now);
- strftime (now_str, 32, "%Y/%m/%d-%H:%M:%S", &now);
+ gf_time_fmt (now_str, sizeof now_str, tv.tv_sec, gf_timefmt_Ymd_T);
snprintf (uuid, size, "%s-%d-%s:%"GF_PRI_SUSECONDS,
hostname, getpid(), now_str, tv.tv_usec);
@@ -446,18 +432,37 @@ glusterfs_graph_prepare (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
/* XXX: attach to -n volname */
ret = glusterfs_graph_settop (graph, ctx);
- if (ret)
+ if (ret) {
+ gf_log ("graph", GF_LOG_ERROR, "glusterfs graph settop failed");
return -1;
+ }
- /* XXX: RO VOLUME */
- ret = glusterfs_graph_readonly (graph, ctx);
- if (ret)
+ /* XXX: WORM VOLUME */
+ ret = glusterfs_graph_worm (graph, ctx);
+ if (ret) {
+ gf_log ("graph", GF_LOG_ERROR, "glusterfs graph worm failed");
return -1;
+ }
+ ret = glusterfs_graph_acl (graph, ctx);
+ if (ret) {
+ gf_log ("graph", GF_LOG_ERROR, "glusterfs graph ACL failed");
+ return -1;
+ }
/* XXX: MAC COMPAT */
ret = glusterfs_graph_mac_compat (graph, ctx);
- if (ret)
+ if (ret) {
+ gf_log ("graph", GF_LOG_ERROR, "glusterfs graph mac compat failed");
+ return -1;
+ }
+
+ /* XXX: gfid-access */
+ ret = glusterfs_graph_gfid_access (graph, ctx);
+ if (ret) {
+ gf_log ("graph", GF_LOG_ERROR,
+ "glusterfs graph 'gfid-access' failed");
return -1;
+ }
/* XXX: this->ctx setting */
for (trav = graph->first; trav; trav = trav->next) {
@@ -469,6 +474,8 @@ glusterfs_graph_prepare (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
fill_uuid (graph->graph_uuid, 128);
+ graph->id = ctx->graph_id++;
+
/* XXX: --xlator-option additions */
gf_add_cmdline_options (graph, &ctx->cmd_args);
@@ -484,17 +491,23 @@ glusterfs_graph_activate (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
/* XXX: all xlator options validation */
ret = glusterfs_graph_validate_options (graph);
- if (ret)
+ if (ret) {
+ gf_log ("graph", GF_LOG_ERROR, "validate options failed");
return ret;
+ }
/* XXX: perform init () */
ret = glusterfs_graph_init (graph);
- if (ret)
+ if (ret) {
+ gf_log ("graph", GF_LOG_ERROR, "init failed");
return ret;
+ }
ret = glusterfs_graph_unknown_options (graph);
- if (ret)
+ if (ret) {
+ gf_log ("graph", GF_LOG_ERROR, "unknown options failed");
return ret;
+ }
/* XXX: log full graph (_gf_dump_details) */
@@ -502,32 +515,224 @@ glusterfs_graph_activate (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx)
ctx->active = graph;
/* XXX: attach to master and set active pointer */
- if (ctx->master)
+ if (ctx->master) {
ret = xlator_notify (ctx->master, GF_EVENT_GRAPH_NEW, graph);
- if (ret)
- return ret;
+ if (ret) {
+ gf_log ("graph", GF_LOG_ERROR,
+ "graph new notification failed");
+ return ret;
+ }
+ ((xlator_t *)ctx->master)->next = graph->top;
+ }
/* XXX: perform parent up */
ret = glusterfs_graph_parent_up (graph);
- if (ret)
+ if (ret) {
+ gf_log ("graph", GF_LOG_ERROR, "parent up notification failed");
return ret;
-
+ }
return 0;
}
+
+int
+xlator_equal_rec (xlator_t *xl1, xlator_t *xl2)
+{
+ xlator_list_t *trav1 = NULL;
+ xlator_list_t *trav2 = NULL;
+ int ret = 0;
+
+ if (xl1 == NULL || xl2 == NULL) {
+ gf_log ("xlator", GF_LOG_DEBUG, "invalid argument");
+ return -1;
+ }
+
+ trav1 = xl1->children;
+ trav2 = xl2->children;
+
+ while (trav1 && trav2) {
+ ret = xlator_equal_rec (trav1->xlator, trav2->xlator);
+ if (ret) {
+ gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG,
+ "xlators children not equal");
+ goto out;
+ }
+
+ trav1 = trav1->next;
+ trav2 = trav2->next;
+ }
+
+ if (trav1 || trav2) {
+ ret = -1;
+ goto out;
+ }
+
+ if (strcmp (xl1->name, xl2->name)) {
+ ret = -1;
+ goto out;
+ }
+
+ /* type could have changed even if xlator names match,
+ e.g cluster/distrubte and cluster/nufa share the same
+ xlator name
+ */
+ if (strcmp (xl1->type, xl2->type)) {
+ ret = -1;
+ goto out;
+ }
+out :
+ return ret;
+}
+
+
+gf_boolean_t
+is_graph_topology_equal (glusterfs_graph_t *graph1, glusterfs_graph_t *graph2)
+{
+ xlator_t *trav1 = NULL;
+ xlator_t *trav2 = NULL;
+ gf_boolean_t ret = _gf_true;
+
+ trav1 = graph1->first;
+ trav2 = graph2->first;
+
+ ret = xlator_equal_rec (trav1, trav2);
+
+ if (ret) {
+ gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG,
+ "graphs are not equal");
+ ret = _gf_false;
+ goto out;
+ }
+
+ ret = _gf_true;
+ gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG,
+ "graphs are equal");
+
+out:
+ return ret;
+}
+
+
+/* Function has 3types of return value 0, -ve , 1
+ * return 0 =======> reconfiguration of options has succeeded
+ * return 1 =======> the graph has to be reconstructed and all the xlators should be inited
+ * return -1(or -ve) =======> Some Internal Error occurred during the operation
+ */
+int
+glusterfs_volfile_reconfigure (int oldvollen, FILE *newvolfile_fp,
+ glusterfs_ctx_t *ctx, const char *oldvolfile)
+{
+ glusterfs_graph_t *oldvolfile_graph = NULL;
+ glusterfs_graph_t *newvolfile_graph = NULL;
+ FILE *oldvolfile_fp = NULL;
+ gf_boolean_t active_graph_found = _gf_true;
+
+ int ret = -1;
+
+ if (!oldvollen) {
+ ret = 1; // Has to call INIT for the whole graph
+ goto out;
+ }
+
+ if (!ctx) {
+ gf_log ("glusterfsd-mgmt", GF_LOG_ERROR,
+ "ctx is NULL");
+ goto out;
+ }
+
+ oldvolfile_graph = ctx->active;
+ if (!oldvolfile_graph) {
+ active_graph_found = _gf_false;
+ gf_log ("glusterfsd-mgmt", GF_LOG_ERROR,
+ "glusterfs_ctx->active is NULL");
+
+ oldvolfile_fp = tmpfile ();
+ if (!oldvolfile_fp) {
+ gf_log ("glusterfsd-mgmt", GF_LOG_ERROR, "Unable to "
+ "create temporary volfile: (%s)",
+ strerror (errno));
+ goto out;
+ }
+
+ fwrite (oldvolfile, oldvollen, 1, oldvolfile_fp);
+ fflush (oldvolfile_fp);
+ if (ferror (oldvolfile_fp)) {
+ goto out;
+ }
+
+ oldvolfile_graph = glusterfs_graph_construct (oldvolfile_fp);
+ if (!oldvolfile_graph)
+ goto out;
+ }
+
+ newvolfile_graph = glusterfs_graph_construct (newvolfile_fp);
+ if (!newvolfile_graph) {
+ goto out;
+ }
+
+ if (!is_graph_topology_equal (oldvolfile_graph,
+ newvolfile_graph)) {
+
+ ret = 1;
+ gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG,
+ "Graph topology not equal(should call INIT)");
+ goto out;
+ }
+
+ gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG,
+ "Only options have changed in the new "
+ "graph");
+
+ /* */
+ ret = glusterfs_graph_reconfigure (oldvolfile_graph,
+ newvolfile_graph);
+ if (ret) {
+ gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG,
+ "Could not reconfigure new options in old graph");
+ goto out;
+ }
+
+ ret = 0;
+out:
+ if (oldvolfile_fp)
+ fclose (oldvolfile_fp);
+
+ /* Do not simply destroy the old graph here. If the oldgraph
+ is constructed here in this function itself instead of getting
+ it from ctx->active (which happens only of ctx->active is NULL),
+ then destroy the old graph. If some i/o is still happening in
+ the old graph and the old graph is obtained from ctx->active,
+ then destroying the graph will cause problems.
+ */
+ if (!active_graph_found && oldvolfile_graph)
+ glusterfs_graph_destroy (oldvolfile_graph);
+ if (newvolfile_graph)
+ glusterfs_graph_destroy (newvolfile_graph);
+
+ return ret;
+}
+
+
int
glusterfs_graph_reconfigure (glusterfs_graph_t *oldgraph,
glusterfs_graph_t *newgraph)
{
- xlator_t *old_xl = NULL;
- xlator_t *new_xl = NULL;
+ xlator_t *old_xl = NULL;
+ xlator_t *new_xl = NULL;
GF_ASSERT (oldgraph);
GF_ASSERT (newgraph);
old_xl = oldgraph->first;
+ while (old_xl->is_autoloaded) {
+ old_xl = old_xl->children->xlator;
+ }
+
new_xl = newgraph->first;
+ while (new_xl->is_autoloaded) {
+ new_xl = new_xl->children->xlator;
+ }
return xlator_tree_reconfigure (old_xl, new_xl);
}
@@ -535,7 +740,12 @@ glusterfs_graph_reconfigure (glusterfs_graph_t *oldgraph,
int
glusterfs_graph_destroy (glusterfs_graph_t *graph)
{
- return 0;
-}
+ xlator_tree_free (graph->first);
+ if (graph) {
+ list_del_init (&graph->list);
+ GF_FREE (graph);
+ }
+ return 0;
+}