diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-volgen.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 943 |
1 files changed, 550 insertions, 393 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 811ff8494..6f3c69e7d 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -15,6 +15,7 @@ #include <fnmatch.h> #include <sys/wait.h> +#include <dlfcn.h> #if (HAVE_LIB_XML) #include <libxml/encoding.h> @@ -27,6 +28,8 @@ #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" @@ -34,240 +37,9 @@ #include "glusterd-op-sm.h" #include "glusterd-utils.h" #include "run.h" +#include "options.h" -#define AUTH_ALLOW_MAP_KEY "auth.allow" -#define AUTH_REJECT_MAP_KEY "auth.reject" -#define NFS_DISABLE_MAP_KEY "nfs.disable" -#define AUTH_ALLOW_OPT_KEY "auth.addr.*.allow" -#define AUTH_REJECT_OPT_KEY "auth.addr.*.reject" -#define NFS_DISABLE_OPT_KEY "nfs.*.disable" - - -/* 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. - * - * Fifth field is <doctype>, which decides if the option is public and available - * in "set help" or not. "NODOC" entries are not part of the public interface - * and are subject to change at any time. This also decides if an option is - * global (apllies to all volumes) or normal (applies to only specified volume). - * - * Sixth field is <flags>. - * - * Seventh field is <op-version>. - * - * 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. - * - * - * 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. - * - */ - -static struct volopt_map_entry glusterd_volopt_map[] = { - /* DHT xlator options */ - {"cluster.lookup-unhashed", "cluster/distribute", NULL, NULL, DOC, 0, 1}, - {"cluster.min-free-disk", "cluster/distribute", NULL, NULL, DOC, 0, 1}, - {"cluster.min-free-inodes", "cluster/distribute", NULL, NULL, DOC, 0, 1}, - {"cluster.rebalance-stats", "cluster/distribute", NULL, NULL, DOC, 0, 2}, - {"cluster.subvols-per-directory", "cluster/distribute", "directory-layout-spread", NULL, DOC, 0, 2}, - {"cluster.readdir-optimize", "cluster/distribute", NULL, NULL, DOC, 0, 2}, - {"cluster.nufa", "cluster/distribute", "!nufa", NULL, NO_DOC, 0, 2}, - - /* AFR xlator options */ - {"cluster.entry-change-log", "cluster/replicate", NULL, NULL, DOC, 0, 1}, - {"cluster.read-subvolume", "cluster/replicate", NULL, NULL, DOC, 0, 1}, - {"cluster.read-subvolume-index", "cluster/replicate", NULL, NULL, DOC, 0, 2}, - {"cluster.read-hash-mode", "cluster/replicate", NULL, NULL, DOC, 0, 2}, - {"cluster.background-self-heal-count", "cluster/replicate", NULL, NULL, DOC, 0, 1}, - {"cluster.metadata-self-heal", "cluster/replicate", NULL, NULL, DOC, 0, 1}, - {"cluster.data-self-heal", "cluster/replicate", NULL, NULL, DOC, 0, 1}, - {"cluster.entry-self-heal", "cluster/replicate", NULL, NULL, DOC, 0, 1}, - {"cluster.self-heal-daemon", "cluster/replicate", "!self-heal-daemon" , NULL, DOC, 0, 1}, - {"cluster.heal-timeout", "cluster/replicate", "!heal-timeout" , NULL, DOC, 0, 2}, - {"cluster.strict-readdir", "cluster/replicate", NULL, NULL, NO_DOC, 0, 1}, - {"cluster.self-heal-window-size", "cluster/replicate", "data-self-heal-window-size", NULL, DOC, 0, 1}, - {"cluster.data-change-log", "cluster/replicate", NULL, NULL, DOC, 0, 1}, - {"cluster.metadata-change-log", "cluster/replicate", NULL, NULL, DOC, 0, 1}, - {"cluster.data-self-heal-algorithm", "cluster/replicate", "data-self-heal-algorithm", NULL, DOC, 0, 1}, - {"cluster.eager-lock", "cluster/replicate", NULL, NULL, DOC, 0, 1}, - {"cluster.quorum-type", "cluster/replicate", "quorum-type", NULL, DOC, 0, 1}, - {"cluster.quorum-count", "cluster/replicate", "quorum-count", NULL, DOC, 0, 1}, - {"cluster.choose-local", "cluster/replicate", NULL, NULL, DOC, 0, 2}, - {"cluster.self-heal-readdir-size", "cluster/replicate", NULL, NULL, DOC, 0, 2}, - {"cluster.post-op-delay-secs", "cluster/replicate", NULL, NULL, NO_DOC, 0, 2}, - {"cluster.readdir-failover", "cluster/replicate", NULL, NULL, DOC, 0, 2}, - - /* Stripe xlator options */ - {"cluster.stripe-block-size", "cluster/stripe", "block-size", NULL, DOC, 0, 1}, - {"cluster.stripe-coalesce", "cluster/stripe", "coalesce", NULL, DOC, 0, 2}, - - /* IO-stats xlator options */ - {VKEY_DIAG_LAT_MEASUREMENT, "debug/io-stats", "latency-measurement", "off", DOC, 0, 1}, - {"diagnostics.dump-fd-stats", "debug/io-stats", NULL, NULL, DOC, 0, 1}, - {VKEY_DIAG_CNT_FOP_HITS, "debug/io-stats", "count-fop-hits", "off", NO_DOC, 0, 1}, - {"diagnostics.brick-log-level", "debug/io-stats", "!brick-log-level", NULL, DOC, 0, 1}, - {"diagnostics.client-log-level", "debug/io-stats", "!client-log-level", NULL, DOC, 0, 1}, - {"diagnostics.brick-sys-log-level", "debug/io-stats", "!sys-log-level", NULL, DOC, 0, 1}, - {"diagnostics.client-sys-log-level", "debug/io-stats", "!sys-log-level", NULL, DOC, 0, 1}, - - /* IO-cache xlator options */ - {"performance.cache-max-file-size", "performance/io-cache", "max-file-size", NULL, DOC, 0, 1}, - {"performance.cache-min-file-size", "performance/io-cache", "min-file-size", NULL, DOC, 0, 1}, - {"performance.cache-refresh-timeout", "performance/io-cache", "cache-timeout", NULL, DOC, 0, 1}, - {"performance.cache-priority", "performance/io-cache", "priority", NULL, DOC, 0, 1}, - {"performance.cache-size", "performance/io-cache", NULL, NULL, DOC, 0, 1}, - - /* IO-threads xlator options */ - {"performance.io-thread-count", "performance/io-threads", "thread-count", NULL, DOC, 0, 1}, - {"performance.high-prio-threads", "performance/io-threads", NULL, NULL, DOC, 0, 1}, - {"performance.normal-prio-threads", "performance/io-threads", NULL, NULL, DOC, 0, 1}, - {"performance.low-prio-threads", "performance/io-threads", NULL, NULL, DOC, 0, 1}, - {"performance.least-prio-threads", "performance/io-threads", NULL, NULL, DOC, 0, 1}, - {"performance.enable-least-priority", "performance/io-threads", NULL, NULL, DOC, 0, 2}, - {"performance.least-rate-limit", "performance/io-threads", NULL, NULL, DOC, 0, 1}, - - /* Other perf xlators' options */ - {"performance.cache-size", "performance/quick-read", NULL, NULL, DOC, 0, 1}, - - {"performance.flush-behind", "performance/write-behind", "flush-behind", NULL, DOC, 0, 1}, - {"performance.write-behind-window-size", "performance/write-behind", "cache-size", NULL, DOC, 1}, - {"performance.strict-o-direct", "performance/write-behind", "strict-O_DIRECT", NULL, DOC, 2}, - {"performance.strict-write-ordering", "performance/write-behind", "strict-write-ordering", NULL, DOC, 2}, - - {"performance.read-ahead-page-count", "performance/read-ahead", "page-count", NULL, DOC, 1}, - {"performance.md-cache-timeout", "performance/md-cache", "md-cache-timeout", NULL, DOC, 0, 2}, - - /* Client xlator options */ - {"network.frame-timeout", "protocol/client", NULL, NULL, DOC, 0, 1}, - {"network.ping-timeout", "protocol/client", NULL, NULL, DOC, 0, 1}, - {"network.tcp-window-size", "protocol/client", NULL, NULL, DOC, 0, 1}, - {"features.lock-heal", "protocol/client", "lk-heal", NULL, DOC, 0, 1}, - {"features.grace-timeout", "protocol/client", "grace-timeout", NULL, DOC, 0, 1}, - {"client.ssl", "protocol/client", "transport.socket.ssl-enabled", NULL, NO_DOC, 0, 2}, - {"network.remote-dio", "protocol/client", "filter-O_DIRECT", NULL, DOC, 0, 1}, - - /* Server xlator options */ - {"network.tcp-window-size", "protocol/server", NULL, NULL, DOC, 0, 1}, - {"network.inode-lru-limit", "protocol/server", NULL, NULL, DOC, 0, 1}, - {AUTH_ALLOW_MAP_KEY, "protocol/server", "!server-auth", "*", DOC, 0, 1}, - {AUTH_REJECT_MAP_KEY, "protocol/server", "!server-auth", NULL, DOC, 0}, - - {"transport.keepalive", "protocol/server", "transport.socket.keepalive", NULL, NO_DOC, 0, 1}, - {"server.allow-insecure", "protocol/server", "rpc-auth-allow-insecure", NULL, NO_DOC, 0, 1}, - {"server.statedump-path", "protocol/server", "statedump-path", NULL, DOC, 0, 1}, - {"features.lock-heal", "protocol/server", "lk-heal", NULL, NO_DOC, 0, 1}, - {"features.grace-timeout", "protocol/server", "grace-timeout", NULL, NO_DOC, 0, 1}, - {"server.ssl", "protocol/server", "transport.socket.ssl-enabled", NULL, NO_DOC, 0, 2}, - - /* Performance xlators enable/disbable options */ - {"performance.write-behind", "performance/write-behind", "!perf", "on", NO_DOC, 0, 1}, - {"performance.read-ahead", "performance/read-ahead", "!perf", "on", NO_DOC, 0, 1}, - {"performance.io-cache", "performance/io-cache", "!perf", "on", NO_DOC, 0, 1}, - {"performance.quick-read", "performance/quick-read", "!perf", "on", NO_DOC, 0, 1}, - {"performance.stat-prefetch", "performance/md-cache", "!perf", "on", NO_DOC, 0, 1}, - {"performance.client-io-threads", "performance/io-threads", "!perf", "off", NO_DOC, 0, 1}, - - {"performance.nfs.write-behind", "performance/write-behind", "!nfsperf", "off", NO_DOC, 0, 1}, - {"performance.nfs.read-ahead", "performance/read-ahead", "!nfsperf", "off", NO_DOC, 0, 1}, - {"performance.nfs.io-cache", "performance/io-cache", "!nfsperf", "off", NO_DOC, 0, 1}, - {"performance.nfs.quick-read", "performance/quick-read", "!nfsperf", "off", NO_DOC, 0, 1}, - {"performance.nfs.stat-prefetch", "performance/md-cache", "!nfsperf", "off", NO_DOC, 0, 1}, - {"performance.nfs.io-threads", "performance/io-threads", "!nfsperf", "off", NO_DOC, 0, 1}, - {"performance.force-readdirp", "performance/md-cache", "force-readdirp", NULL, DOC, 0, 2}, - - /* Quota xlator options */ - {VKEY_FEATURES_LIMIT_USAGE, "features/quota", "limit-set", NULL, NO_DOC, 0, 1}, - {"features.quota-timeout", "features/quota", "timeout", "0", DOC, 0, 1}, - - /* Marker xlator options */ - {VKEY_MARKER_XTIME, "features/marker", "xtime", "off", NO_DOC, OPT_FLAG_FORCE, 1}, - {VKEY_MARKER_XTIME, "features/marker", "!xtime", "off", NO_DOC, OPT_FLAG_FORCE, 1}, - {VKEY_FEATURES_QUOTA, "features/marker", "quota", "off", NO_DOC, OPT_FLAG_FORCE, 1}, - - /* Debug xlators options */ - {"debug.trace", "debug/trace", "!debug","off", NO_DOC, 0, 1}, - {"debug.log-history", "debug/trace", "log-history", NULL, NO_DOC, 0, 2}, - {"debug.log-file", "debug/trace", "log-file", NULL, NO_DOC, 0, 2}, - {"debug.exclude-ops", "debug/trace", "exclude-ops", NULL, NO_DOC, 0, 2}, - {"debug.include-ops", "debug/trace", "include-ops", NULL, NO_DOC, 0, 2}, - {"debug.error-gen", "debug/error-gen", "!debug","off", NO_DOC, 0, 1}, - - /* NFS xlator options */ - {"nfs.enable-ino32", "nfs/server", "nfs.enable-ino32", NULL, GLOBAL_DOC, 0, 1}, - {"nfs.mem-factor", "nfs/server", "nfs.mem-factor", NULL, GLOBAL_DOC, 0, 1}, - {"nfs.export-dirs", "nfs/server", "nfs3.export-dirs", NULL, GLOBAL_DOC, 0, 1}, - {"nfs.export-volumes", "nfs/server", "nfs3.export-volumes", NULL, GLOBAL_DOC, 0, 1}, - {"nfs.addr-namelookup", "nfs/server", "rpc-auth.addr.namelookup", NULL, GLOBAL_DOC, 0, 1}, - {"nfs.dynamic-volumes", "nfs/server", "nfs.dynamic-volumes", NULL, GLOBAL_DOC, 0, 1}, - {"nfs.register-with-portmap", "nfs/server", "rpc.register-with-portmap", NULL, GLOBAL_DOC, 0, 1}, - {"nfs.port", "nfs/server", "nfs.port", NULL, GLOBAL_DOC, 0, 1}, - {"nfs.rpc-auth-unix", "nfs/server", "!rpc-auth.auth-unix.*", NULL, DOC, 0, 1}, - {"nfs.rpc-auth-null", "nfs/server", "!rpc-auth.auth-null.*", NULL, DOC, 0, 1}, - {"nfs.rpc-auth-allow", "nfs/server", "!rpc-auth.addr.*.allow", NULL, DOC, 0, 1}, - {"nfs.rpc-auth-reject", "nfs/server", "!rpc-auth.addr.*.reject", NULL, DOC, 0, 1}, - {"nfs.ports-insecure", "nfs/server", "!rpc-auth.ports.*.insecure", NULL, DOC, 0, 1}, - {"nfs.transport-type", "nfs/server", "!nfs.transport-type", NULL, DOC, 0, 1}, - {"nfs.trusted-sync", "nfs/server", "!nfs3.*.trusted-sync", NULL, DOC, 0, 1}, - {"nfs.trusted-write", "nfs/server", "!nfs3.*.trusted-write", NULL, DOC, 0, 1}, - {"nfs.volume-access", "nfs/server", "!nfs3.*.volume-access", NULL, DOC, 0, 1}, - {"nfs.export-dir", "nfs/server", "!nfs3.*.export-dir", NULL, DOC, 0, 1}, - {NFS_DISABLE_MAP_KEY, "nfs/server", "!nfs-disable", NULL, DOC, 0, 1}, - {"nfs.nlm", "nfs/server", "nfs.nlm", NULL, GLOBAL_DOC, 0, 1}, - {"nfs.mount-udp", "nfs/server", "nfs.mount-udp", NULL, GLOBAL_DOC, 0, 1}, - {"nfs.server-aux-gids", "nfs/server", "nfs.server-aux-gids", NULL, NO_DOC, 0, 2}, - - /* Other options which don't fit any place above */ - {"features.read-only", "features/read-only", "!read-only", "off", DOC, 0, 2}, - {"features.worm", "features/worm", "!worm", "off", DOC, 0, 2}, - - {"storage.linux-aio", "storage/posix", NULL, NULL, DOC, 0, 2}, - {"storage.owner-uid", "storage/posix", "brick-uid", NULL, DOC, 0, 2}, - {"storage.owner-gid", "storage/posix", "brick-gid", NULL, DOC, 0, 2}, - {"config.memory-accounting", "configuration", "!config", NULL, DOC, 0, 2}, - {"config.transport", "configuration", "!config", NULL, DOC, 0, 2}, - {GLUSTERD_QUORUM_TYPE_KEY, "mgmt/glusterd", NULL, "off", DOC, 0, 2}, - {GLUSTERD_QUORUM_RATIO_KEY, "mgmt/glusterd", NULL, "0", DOC, 0, 2}, - {NULL, } -}; - - +extern struct volopt_map_entry glusterd_volopt_map[]; /********************************************* * @@ -680,7 +452,7 @@ struct opthandler_data { }; static int -process_option (dict_t *dict, char *key, data_t *value, void *param) +process_option (char *key, data_t *value, void *param) { struct opthandler_data *odt = param; struct volopt_map_entry vme = {0,}; @@ -692,6 +464,8 @@ process_option (dict_t *dict, char *key, data_t *value, void *param) 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) @@ -729,7 +503,7 @@ volgen_graph_set_options_generic (volgen_graph_t *graph, dict_t *dict, data = dict_get (dict, vme->key); if (data) - process_option (dict, vme->key, data, &odt); + process_option (vme->key, data, &odt); if (odt.rv) return odt.rv; @@ -743,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; } @@ -823,6 +596,8 @@ get_server_xlator (char *xlator) 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; } @@ -1075,6 +850,7 @@ glusterd_check_option_exists (char *key, char **completion) struct volopt_map_entry vme = {0,}; struct volopt_map_entry *vmep = NULL; int ret = 0; + xlator_t *this = THIS; (void)vme; (void)vmep; @@ -1083,7 +859,8 @@ glusterd_check_option_exists (char *key, char **completion) 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; } @@ -1109,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"); } @@ -1646,10 +1423,11 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, char *password = NULL; char index_basepath[PATH_MAX] = {0}; char key[1024] = {0}; - char *vgname = NULL; - char *vg = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + char changelog_basepath[PATH_MAX] = {0,}; - path = param; + brickinfo = param; + path = brickinfo->path; volname = volinfo->volname; get_vol_transport_type (volinfo, transt); @@ -1665,47 +1443,62 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, } } - if (volinfo->backend == GD_VOL_BK_BD) { - xl = volgen_graph_add (graph, "storage/bd_map", volname); - if (!xl) - return -1; + xl = volgen_graph_add (graph, "storage/posix", volname); + if (!xl) + return -1; - ret = xlator_set_option (xl, "device", "vg"); - if (ret) - return -1; + ret = xlator_set_option (xl, "directory", path); + if (ret) + return -1; - vg = gf_strdup (path); - vgname = strrchr (vg, '/'); - if (strchr(vg, '/') != vgname) { - gf_log ("glusterd", GF_LOG_ERROR, - "invalid vg specified %s", path); - GF_FREE (vg); - goto out; - } - vgname++; - ret = xlator_set_option (xl, "export", vgname); - GF_FREE (vg); - if (ret) - return -1; - } else { - xl = volgen_graph_add (graph, "storage/posix", volname); + ret = xlator_set_option (xl, "volume-id", + uuid_utoa (volinfo->volume_id)); + 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, "directory", path); + ret = xlator_set_option (xl, "device", "vg"); if (ret) return -1; - - ret = xlator_set_option (xl, "volume-id", - uuid_utoa (volinfo->volume_id)); + ret = xlator_set_option (xl, "export", brickinfo->vg); if (ret) return -1; - ret = check_and_add_debug_xl (graph, set_dict, volname, - "posix"); + 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; @@ -1821,7 +1614,8 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, } /* Check for read-only volume option, and add it to the graph */ - if (dict_get_str_boolean (set_dict, "features.read-only", 0)) { + 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; @@ -1838,6 +1632,18 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, } } + /* 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; @@ -1849,6 +1655,16 @@ 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); @@ -1881,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); } @@ -1891,10 +1707,11 @@ static int perfxl_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, void *param) { - char *volname = NULL; gf_boolean_t enabled = _gf_false; + glusterd_volinfo_t *volinfo = NULL; - volname = param; + GF_ASSERT (param); + volinfo = param; if (strcmp (vme->option, "!perf") != 0) return 0; @@ -1904,7 +1721,13 @@ perfxl_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, if (!enabled) return 0; - if (volgen_graph_add (graph, vme->voltype, volname)) + /* 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; @@ -2069,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; @@ -2112,11 +1935,22 @@ 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 (dict_t * ctx, gf_boolean_t xml_out) { - - char *xlator_type = NULL; void *dl_handle = NULL; volume_opt_list_t vol_opt_handle = {{0},}; char *key = NULL; @@ -2142,46 +1976,69 @@ glusterd_get_volopt_content (dict_t * ctx, gf_boolean_t xml_out) 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) { - dl_handle = NULL; - continue; + 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*/ - continue; + 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, 2048, "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); } - - if (!strcmp (key, AUTH_ALLOW_OPT_KEY) || - !strcmp (key, AUTH_REJECT_OPT_KEY) || - !strcmp (key, NFS_DISABLE_OPT_KEY)) - GF_FREE (key); +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) @@ -2208,7 +2065,7 @@ glusterd_get_volopt_content (dict_t * ctx, 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; @@ -2470,22 +2327,33 @@ volgen_graph_build_dht_cluster (volgen_graph_t *graph, int ret = -1; char *decommissioned_children = NULL; xlator_t *dht = NULL; - char *optstr = NULL; - gf_boolean_t use_nufa = _gf_false; + char *voltype = "cluster/distribute"; - if (dict_get_str(volinfo->dict,"cluster.nufa",&optstr) == 0) { - /* Keep static analyzers quiet by "using" the value. */ - ret = gf_string2boolean(optstr,&use_nufa); + /* 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"; + clusters = volgen_graph_build_clusters (graph, volinfo, - use_nufa - ? "cluster/nufa" - : "cluster/distribute", + voltype, "%s-dht", - child_count, child_count); + child_count, + child_count); if (clusters < 0) goto out; + dht = first_of (graph); ret = _graph_get_decommissioned_children (dht, volinfo, &decommissioned_children); @@ -2579,7 +2447,7 @@ build_distribute: ret = volgen_graph_build_dht_cluster (graph, volinfo, dist_count); - if (ret) + if (ret == -1) goto out; ret = 0; @@ -2587,6 +2455,29 @@ 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) @@ -2594,7 +2485,6 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, int ret = 0; xlator_t *xl = NULL; char *volname = NULL; - data_t *tmp_data = NULL; volname = volinfo->volname; ret = volgen_graph_build_clients (graph, volinfo, set_dict, param); @@ -2602,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; @@ -2617,16 +2532,20 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, } } - /* Logic to make sure NFS doesn't have performance translators by - default for a volume */ - tmp_data = dict_get (set_dict, "nfs-volume-file"); - if (!tmp_data) - ret = volgen_graph_set_options_generic (graph, set_dict, volname, - &perfxl_option_handler); - else - ret = volgen_graph_set_options_generic (graph, set_dict, volname, - &nfsperfxl_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; @@ -3024,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); @@ -3049,6 +2970,10 @@ build_nfs_graph (volgen_graph_t *graph, dict_t *mod_dict) 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; @@ -3109,6 +3034,12 @@ build_nfs_graph (volgen_graph_t *graph, dict_t *mod_dict) 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; @@ -3191,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; + + 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; } @@ -3230,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); @@ -3239,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) { @@ -3341,7 +3275,7 @@ enumerate_transport_reqs (gf_transport_type type, char **types) } } -static int +int generate_client_volfiles (glusterd_volinfo_t *volinfo, glusterd_client_type_t client_type) { @@ -3507,6 +3441,54 @@ 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,}; @@ -3615,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; @@ -3625,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; @@ -3639,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); @@ -3646,60 +3637,12 @@ 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_wb_eagerlock (glusterd_volinfo_t *volinfo, dict_t *val_dict, - char **op_errstr) -{ - int ret = -1; - gf_boolean_t wb_val = _gf_false; - gf_boolean_t el_val = _gf_false; - char msg[2048] = {0}; - char *wb_key = NULL; - char *el_key = NULL; - - wb_key = "performance.write-behind"; - el_key = "cluster.eager-lock"; - ret = dict_get_str_boolean (val_dict, wb_key, -1); - if (ret < 0) - goto check_eager_lock; - wb_val = ret; - ret = glusterd_volinfo_get_boolean (volinfo, el_key); - if (ret < 0) - goto out; - el_val = ret; - goto done; - -check_eager_lock: - ret = dict_get_str_boolean (val_dict, el_key, -1); - if (ret < 0) { - ret = 0; //Keys of intereset to this fn are not present. - goto out; - } - el_val = ret; - ret = glusterd_volinfo_get_boolean (volinfo, wb_key); - if (ret < 0) - goto out; - wb_val = ret; - goto done; - -done: - ret = 0; - if (!wb_val && el_val) { - ret = -1; - snprintf (msg, sizeof (msg), "%s off and %s on is not " - "valid configuration", wb_key, el_key); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - if (op_errstr) - *op_errstr = gf_strdup (msg); - goto out; - } -out: - return ret; -} int validate_clientopts (glusterd_volinfo_t *volinfo, @@ -3725,7 +3668,7 @@ 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) { @@ -3736,7 +3679,7 @@ validate_brickopts (glusterd_volinfo_t *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); @@ -3758,7 +3701,7 @@ 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; @@ -3860,10 +3803,6 @@ glusterd_validate_reconfopts (glusterd_volinfo_t *volinfo, dict_t *val_dict, goto out; } - ret = validate_wb_eagerlock (volinfo, val_dict, op_errstr); - if (ret) - goto out; - ret = validate_clientopts (volinfo, val_dict, op_errstr); if (ret) { gf_log ("", GF_LOG_DEBUG, @@ -3890,19 +3829,237 @@ out: 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) { - char *completion = NULL; struct volopt_map_entry *vmep = NULL; - int ret = 0; - COMPLETE_OPTION(key, completion, ret); - for (vmep = glusterd_volopt_map; vmep->key; vmep++) { - if (strcmp (vmep->key, key) == 0) { - return vmep->op_version; + 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; } } - return 0; + /* 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; } |
